Files
TheRock/rocm-systems/projects/rocprofiler-compute/sample/triton_ffn.py
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

180 lines
4.8 KiB
Python

# Copyright (c) Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
"""
Pure-Triton LLaMA-style feed-forward block (RMSNorm + gated MLP).
Implements one transformer FFN entirely in Triton:
h = rmsnorm(x)
gate = h @ Wgate
up = h @ Wup
out = x + (silu(gate) * up) @ Wdown
This exercises five distinct Triton kernels (rmsnorm, matmul, silu, mul, add);
the matmul kernel is launched from three call sites (the gate, up, and down
projections).
"""
import sys
import torch
import triton
import triton.language as tl
BLOCK_M = 64
BLOCK_N = 64
BLOCK_K = 64
ELT_BLOCK = 1024
@triton.jit
def rmsnorm_kernel(x_ptr, w_ptr, out_ptr, n_cols, eps, BLOCK: tl.constexpr):
row = tl.program_id(0)
cols = tl.arange(0, BLOCK)
mask = cols < n_cols
x = tl.load(x_ptr + row * n_cols + cols, mask=mask, other=0.0)
rstd = 1.0 / tl.sqrt(tl.sum(x * x, axis=0) / n_cols + eps)
w = tl.load(w_ptr + cols, mask=mask, other=0.0)
tl.store(out_ptr + row * n_cols + cols, x * rstd * w, mask=mask)
@triton.jit
def matmul_kernel(
a_ptr,
b_ptr,
c_ptr,
M,
N,
K,
stride_am,
stride_ak,
stride_bk,
stride_bn,
stride_cm,
stride_cn,
BLOCK_M: tl.constexpr,
BLOCK_N: tl.constexpr,
BLOCK_K: tl.constexpr,
):
pid_m = tl.program_id(0)
pid_n = tl.program_id(1)
offs_m = pid_m * BLOCK_M + tl.arange(0, BLOCK_M)
offs_n = pid_n * BLOCK_N + tl.arange(0, BLOCK_N)
offs_k = tl.arange(0, BLOCK_K)
a_ptrs = a_ptr + (offs_m[:, None] * stride_am + offs_k[None, :] * stride_ak)
b_ptrs = b_ptr + (offs_k[:, None] * stride_bk + offs_n[None, :] * stride_bn)
acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
for k in range(0, K, BLOCK_K):
k_mask = offs_k[None, :] < K - k
a = tl.load(a_ptrs, mask=k_mask, other=0.0)
b = tl.load(b_ptrs, mask=offs_k[:, None] < K - k, other=0.0)
acc += tl.dot(a, b)
a_ptrs += BLOCK_K * stride_ak
b_ptrs += BLOCK_K * stride_bk
c_ptrs = c_ptr + offs_m[:, None] * stride_cm + offs_n[None, :] * stride_cn
c_mask = (offs_m[:, None] < M) & (offs_n[None, :] < N)
tl.store(c_ptrs, acc, mask=c_mask)
@triton.jit
def silu_kernel(x_ptr, out_ptr, n, BLOCK_SIZE: tl.constexpr):
offs = tl.program_id(0) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask)
tl.store(out_ptr + offs, x * tl.sigmoid(x), mask=mask)
@triton.jit
def mul_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK_SIZE: tl.constexpr):
offs = tl.program_id(0) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask)
y = tl.load(y_ptr + offs, mask=mask)
tl.store(out_ptr + offs, x * y, mask=mask)
@triton.jit
def add_kernel(x_ptr, y_ptr, out_ptr, n, BLOCK_SIZE: tl.constexpr):
offs = tl.program_id(0) * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
mask = offs < n
x = tl.load(x_ptr + offs, mask=mask)
y = tl.load(y_ptr + offs, mask=mask)
tl.store(out_ptr + offs, x + y, mask=mask)
def rmsnorm(x, weight, eps=1e-6):
rows, cols = x.shape
out = torch.empty_like(x)
rmsnorm_kernel[(rows,)](
x, weight, out, cols, eps, BLOCK=triton.next_power_of_2(cols)
)
return out
def matmul(a, b):
m, k = a.shape
_, n = b.shape
c = torch.empty((m, n), device=a.device, dtype=a.dtype)
grid = (triton.cdiv(m, BLOCK_M), triton.cdiv(n, BLOCK_N))
matmul_kernel[grid](
a,
b,
c,
m,
n,
k,
a.stride(0),
a.stride(1),
b.stride(0),
b.stride(1),
c.stride(0),
c.stride(1),
BLOCK_M=BLOCK_M,
BLOCK_N=BLOCK_N,
BLOCK_K=BLOCK_K,
)
return c
def elementwise(kernel, *tensors):
out = torch.empty_like(tensors[0])
n = out.numel()
grid = (triton.cdiv(n, ELT_BLOCK),)
kernel[grid](*tensors, out, n, BLOCK_SIZE=ELT_BLOCK)
return out
def ffn(x, w_norm, w_gate, w_up, w_down):
h = rmsnorm(x, w_norm)
gate = matmul(h, w_gate)
up = matmul(h, w_up)
act = elementwise(silu_kernel, gate)
fused = elementwise(mul_kernel, act, up)
down = matmul(fused, w_down)
return elementwise(add_kernel, x, down)
def main():
if not torch.cuda.is_available():
print("GPU is required for this sample. Exiting.")
sys.exit(1)
tokens, hidden, inter = 512, 512, 2048
dev = "cuda"
x = torch.randn(tokens, hidden, device=dev)
w_norm = torch.randn(hidden, device=dev)
w_gate = torch.randn(hidden, inter, device=dev)
w_up = torch.randn(hidden, inter, device=dev)
w_down = torch.randn(inter, hidden, device=dev)
for _ in range(3):
out = ffn(x, w_norm, w_gate, w_up, w_down)
torch.cuda.synchronize()
print(f"FFN completed, output sum: {out.sum().item():.3f}")
if __name__ == "__main__":
main()