Skip to content

Commit 4107a57

Browse files
authored
w8a8 matmul add splitk (#2700)
1 parent b8b560c commit 4107a57

3 files changed

Lines changed: 252 additions & 1 deletion

File tree

src/flag_gems/runtime/backend/_nvidia/hopper/ops/w8a8_block_fp8_matmul.py

Lines changed: 182 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,109 @@ def w8a8_block_fp8_matmul_kernel_host_tma(
345345
c_desc.store([offset_am, offset_bn], acc.to(c_desc.dtype))
346346

347347

348+
@libentry()
349+
@libtuner(
350+
configs=runtime.ops_get_configs(
351+
"w8a8_block_fp8_general_splitk",
352+
yaml_path=EXPAND_CONFIG_FILENAME,
353+
)
354+
if os.environ.get("USE_FLAGTUNE") == "1"
355+
else _get_placeholder_tuner_configs(pre_hook=None),
356+
key=["M", "N", "K", "stride_am", "stride_bk"],
357+
strategy=runtime.get_expand_config(
358+
"w8a8_block_fp8_general_splitk", yaml_path=EXPAND_CONFIG_FILENAME
359+
)["strategy"]
360+
if os.environ.get("USE_FLAGTUNE") == "1"
361+
else ["align32", "align32", "align32", "align32", "align32"],
362+
warmup=5,
363+
rep=5,
364+
)
365+
@triton.jit
366+
def w8a8_block_fp8_matmul_kernel_splitk(
367+
A,
368+
B,
369+
C,
370+
As,
371+
Bs,
372+
M,
373+
N,
374+
K,
375+
group_n,
376+
group_k,
377+
stride_am,
378+
stride_ak,
379+
stride_bk,
380+
stride_bn,
381+
stride_cm,
382+
stride_cn,
383+
stride_As_m,
384+
stride_As_k,
385+
stride_Bs_k,
386+
stride_Bs_n,
387+
BLOCK_M: tl.constexpr,
388+
BLOCK_N: tl.constexpr,
389+
BLOCK_K: tl.constexpr,
390+
SPLIT_K: tl.constexpr,
391+
):
392+
pid = tl.program_id(0)
393+
pid_k = tl.program_id(1)
394+
395+
# grid_m = tl.cdiv(M, BLOCK_M)
396+
grid_n = tl.cdiv(N, BLOCK_N)
397+
pid_m = pid // grid_n
398+
pid_n = pid % grid_n
399+
400+
offset_am = pid_m * BLOCK_M
401+
offset_bn = pid_n * BLOCK_N
402+
offs_am = offset_am + tl.arange(0, BLOCK_M)
403+
offs_bn = offset_bn + tl.arange(0, BLOCK_N)
404+
405+
total_k_iters = tl.cdiv(K, BLOCK_K)
406+
k_per_split = tl.cdiv(total_k_iters, SPLIT_K)
407+
k_start = pid_k * k_per_split
408+
k_end = min((pid_k + 1) * k_per_split, total_k_iters)
409+
410+
acc = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
411+
for k in range(k_start, k_end):
412+
offset_k = k * BLOCK_K
413+
offs_k = offset_k + tl.arange(0, BLOCK_K)
414+
415+
a = tl.load(
416+
A + offs_am[:, None] * stride_am + offs_k[None, :] * stride_ak,
417+
mask=(offs_am[:, None] < M) & (offs_k[None, :] < K),
418+
other=0.0,
419+
)
420+
b = tl.load(
421+
B + offs_k[:, None] * stride_bk + offs_bn[None, :] * stride_bn,
422+
mask=(offs_k[:, None] < K) & (offs_bn[None, :] < N),
423+
other=0.0,
424+
)
425+
426+
offs_ks = offset_k // group_k
427+
a_s = tl.load(
428+
As + offs_am * stride_As_m + offs_ks * stride_As_k,
429+
mask=offs_am < M,
430+
other=0.0,
431+
)
432+
b_s = tl.load(
433+
Bs + offs_ks * stride_Bs_k + (offs_bn // group_n) * stride_Bs_n,
434+
mask=offs_bn < N,
435+
other=0.0,
436+
)
437+
acc += tl.dot(a, b, out_dtype=tl.float32) * a_s[:, None] * b_s[None, :]
438+
439+
offs_cm = offset_am + tl.arange(0, BLOCK_M)
440+
offs_cn = offset_bn + tl.arange(0, BLOCK_N)
441+
c_ptrs = C + offs_cm[:, None] * stride_cm + offs_cn[None, :] * stride_cn
442+
mask = (offs_cm < M)[:, None] & (offs_cn < N)[None, :]
443+
if C.dtype.element_ty == tl.bfloat16:
444+
tl.atomic_add(c_ptrs, acc.to(tl.bfloat16), mask=mask)
445+
elif C.dtype.element_ty == tl.float16:
446+
tl.atomic_add(c_ptrs, acc.to(tl.float16), mask=mask)
447+
else:
448+
tl.atomic_add(c_ptrs, acc.to(tl.float32), mask=mask)
449+
450+
348451
def general_w8a8_block_fp8_matmul(a, b, c, a_s, b_s, M, N, K, group_n, group_k):
349452
logger.debug(
350453
"GEMS w8a8_block_fp8_matmul-hopper, [scenario]: general, [shape info]: [-, %s, %s, %s](batch, M, N, K), "
@@ -355,10 +458,88 @@ def general_w8a8_block_fp8_matmul(a, b, c, a_s, b_s, M, N, K, group_n, group_k):
355458
a.stride(0) == 1,
356459
b.stride(0) == 1,
357460
)
461+
462+
use_flagtune = os.environ.get("USE_FLAGTUNE") == "1"
463+
464+
# Split-K path for small-N, large-K shapes
465+
if N <= 512 and K == 7168 and M < 8276:
466+
if use_flagtune:
467+
splitk_grid = lambda META: (
468+
triton.cdiv(M, META["BLOCK_M"]) * triton.cdiv(N, META["BLOCK_N"]),
469+
META["SPLIT_K"],
470+
)
471+
c.zero_()
472+
with torch_device_fn.device(a.device):
473+
w8a8_block_fp8_matmul_kernel_splitk[splitk_grid](
474+
a,
475+
b,
476+
c,
477+
a_s,
478+
b_s,
479+
M,
480+
N,
481+
K,
482+
group_n,
483+
group_k,
484+
a.stride(0),
485+
a.stride(1),
486+
b.stride(1),
487+
b.stride(0),
488+
c.stride(0),
489+
c.stride(1),
490+
a_s.stride(0),
491+
a_s.stride(1),
492+
b_s.stride(1),
493+
b_s.stride(0),
494+
)
495+
else:
496+
SPLITK_BLOCK_K = 128
497+
SPLITK_BLOCK_M = 16 if M <= 16 else 64
498+
SPLITK_BLOCK_N = 64 if N > 256 else 32
499+
500+
grid_m = triton.cdiv(M, SPLITK_BLOCK_M)
501+
grid_n = triton.cdiv(N, SPLITK_BLOCK_N)
502+
grid_mn = grid_m * grid_n
503+
total_k_iters = triton.cdiv(K, SPLITK_BLOCK_K)
504+
505+
SM_COUNT = torch.cuda.get_device_properties(a.device).multi_processor_count
506+
split_k = min(total_k_iters, max(4, 2 * SM_COUNT // max(grid_mn, 1)))
507+
508+
c.zero_()
509+
splitk_grid = (grid_mn, split_k)
510+
511+
with torch_device_fn.device(a.device):
512+
w8a8_block_fp8_matmul_kernel_splitk.fn.fn[splitk_grid](
513+
a,
514+
b,
515+
c,
516+
a_s,
517+
b_s,
518+
M,
519+
N,
520+
K,
521+
group_n,
522+
group_k,
523+
a.stride(0),
524+
a.stride(1),
525+
b.stride(1),
526+
b.stride(0),
527+
c.stride(0),
528+
c.stride(1),
529+
a_s.stride(0),
530+
a_s.stride(1),
531+
b_s.stride(1),
532+
b_s.stride(0),
533+
BLOCK_M=SPLITK_BLOCK_M,
534+
BLOCK_N=SPLITK_BLOCK_N,
535+
BLOCK_K=SPLITK_BLOCK_K,
536+
SPLIT_K=split_k,
537+
)
538+
return c
539+
358540
grid = lambda meta: (
359541
triton.cdiv(M, meta["BLOCK_M"]) * triton.cdiv(N, meta["BLOCK_N"]),
360542
)
361-
use_flagtune = os.environ.get("USE_FLAGTUNE") == "1"
362543
fixed_meta = (
363544
None
364545
if use_flagtune

src/flag_gems/runtime/backend/_nvidia/hopper/w8a8_block_fp8_matmul_hopper_expand.yaml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,44 @@ w8a8_block_fp8_general:
3535
stride_am: default
3636
stride_bk: default
3737

38+
w8a8_block_fp8_general_splitk:
39+
- config:
40+
param_map:
41+
META:
42+
BLOCK_M: block_m
43+
BLOCK_N: block_n
44+
BLOCK_K: block_k
45+
SPLIT_K: split_k
46+
num_stages: stages
47+
num_warps: warps
48+
block_m:
49+
- 16
50+
- 64
51+
- 128
52+
block_n:
53+
- 32
54+
- 64
55+
block_k:
56+
- 128
57+
split_k:
58+
- 4
59+
- 8
60+
- 16
61+
- 28
62+
stages:
63+
- 1
64+
- 2
65+
- 3
66+
warps:
67+
- 4
68+
- 8
69+
- strategy:
70+
M: default
71+
N: default
72+
K: default
73+
stride_am: default
74+
stride_bk: default
75+
3876
w8a8_block_fp8_general_tma:
3977
- config:
4078
param_map:

src/flag_gems/runtime/configloader.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030
"align32",
3131
"align32",
3232
],
33+
"w8a8_block_fp8_general_splitk": [
34+
"align32",
35+
"align32",
36+
"align32",
37+
"align32",
38+
"align32",
39+
],
3340
"w8a8_block_fp8_general_tma": [
3441
"align32",
3542
"align32",
@@ -59,6 +66,7 @@
5966
"baddbmm": ["M", "N", "K"],
6067
"mv": ["M", "N"],
6168
"w8a8_block_fp8_general": ["M", "N", "K", "stride_am", "stride_bk"],
69+
"w8a8_block_fp8_general_splitk": ["M", "N", "K", "stride_am", "stride_bk"],
6270
"w8a8_block_fp8_general_tma": ["M", "N", "K", "stride_am", "stride_bk", "dtype"],
6371
"mm_general_tma": ["M", "N", "K", "stride_am", "stride_bk", "dtype"],
6472
"gemv": ["M", "K", "stride_am", "stride_bk"],
@@ -330,6 +338,27 @@ def _build_configs_by_op(self, op_name, ranges, pre_hook=None):
330338
for w in ranges["w"]
331339
]
332340

341+
if op_name == "w8a8_block_fp8_general_splitk":
342+
return [
343+
triton.Config(
344+
{
345+
"BLOCK_M": block_m,
346+
"BLOCK_N": block_n,
347+
"BLOCK_K": block_k,
348+
"SPLIT_K": split_k,
349+
},
350+
num_stages=s,
351+
num_warps=w,
352+
pre_hook=pre_hook,
353+
)
354+
for block_m in ranges["BLOCK_M"]
355+
for block_n in ranges["BLOCK_N"]
356+
for block_k in ranges["BLOCK_K"]
357+
for split_k in ranges["SPLIT_K"]
358+
for s in ranges["s"]
359+
for w in ranges["w"]
360+
]
361+
333362
return []
334363

335364
def _build_single_expand_spec(
@@ -362,6 +391,9 @@ def _build_expand_registry(self):
362391
"w8a8_block_fp8_general": self._build_single_expand_spec(
363392
"w8a8_block_fp8_general"
364393
),
394+
"w8a8_block_fp8_general_splitk": self._build_single_expand_spec(
395+
"w8a8_block_fp8_general_splitk"
396+
),
365397
"w8a8_block_fp8_general_tma": self._build_single_expand_spec(
366398
"w8a8_block_fp8_general_tma"
367399
),

0 commit comments

Comments
 (0)