@@ -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+
348451def 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
0 commit comments