@@ -185,7 +185,10 @@ def table_batched_embedding_bag_forward_weighted_kernel(
185185
186186 col_offsets = tl .arange (0 , BLOCK_SIZE )
187187 mask = col_offsets < embedding_dim
188- bag_output = tl .zeros ((BLOCK_SIZE ,), dtype = tl .float64 )
188+ accumulator_dtype : tl .constexpr = (
189+ tl .float64 if weight_ptr .dtype .element_ty == tl .float32 else tl .float32
190+ )
191+ bag_output = tl .zeros ((BLOCK_SIZE ,), dtype = accumulator_dtype )
189192
190193 # without type hint the unrolling performance will downgrade
191194 step : tl .constexpr = 4
@@ -270,6 +273,8 @@ def table_batched_embedding_bag_forward_unweighted_kernel(
270273 T : tl .constexpr ,
271274 BLOCK_SIZE : tl .constexpr ,
272275 vbe : tl .constexpr = False ,
276+ FEATURE_START : tl .constexpr = 0 ,
277+ FEATURE_END : tl .constexpr = - 1 ,
273278 FUSED_BOUNDS_CHECK : tl .constexpr = False ,
274279) -> None :
275280
@@ -281,7 +286,8 @@ def table_batched_embedding_bag_forward_unweighted_kernel(
281286 else :
282287 output_row_base = output_ptr + b * total_embedding_dim
283288
284- for t in range (T ):
289+ feature_end : tl .constexpr = T if FEATURE_END < 0 else FEATURE_END
290+ for t in range (FEATURE_START , feature_end ):
285291 if vbe :
286292 # VBE: check if this batch index is within feature t's batch size
287293 B_start = tl .load (B_offsets_ptr + t ).to (tl .int64 )
@@ -308,7 +314,10 @@ def table_batched_embedding_bag_forward_unweighted_kernel(
308314 end = tl .load (offsets_ptr + b_t + 1 )
309315
310316 mask = col_offsets < embedding_dim
311- bag_output = tl .zeros ((BLOCK_SIZE ,), dtype = tl .float64 )
317+ accumulator_dtype : tl .constexpr = (
318+ tl .float64 if weight_ptr .dtype .element_ty == tl .float32 else tl .float32
319+ )
320+ bag_output = tl .zeros ((BLOCK_SIZE ,), dtype = accumulator_dtype )
312321
313322 step : tl .constexpr = 4
314323 ns = (end - start ) // step
@@ -401,6 +410,100 @@ def table_batched_embedding_bag_forward_unweighted_kernel(
401410 tl .atomic_add (bounds_check_warning_ptr , warning_count .to (tl .int64 ))
402411
403412
413+ @triton .jit
414+ def table_batched_embedding_bag_forward_small_table_kernel (
415+ output_ptr ,
416+ indices_ptr ,
417+ offsets_ptr ,
418+ weight_ptr ,
419+ table_offsets_ptr ,
420+ embedding_dims_ptr ,
421+ embedding_offsets_ptr ,
422+ feature_table_map_ptr ,
423+ bounds_check_warning_ptr ,
424+ total_embedding_dim : tl .constexpr ,
425+ B ,
426+ FEATURE : tl .constexpr ,
427+ NUM_ROWS : tl .constexpr ,
428+ ROW_BINS : tl .constexpr ,
429+ BLOCK_SIZE : tl .constexpr ,
430+ FUSED_BOUNDS_CHECK : tl .constexpr = False ,
431+ ) -> None :
432+ bags_per_program : tl .constexpr = 16
433+ histogram_chunk_size : tl .constexpr = 256
434+
435+ bag_slots = tl .arange (0 , bags_per_program )
436+ bags = tl .program_id (0 ).to (tl .int64 ) * bags_per_program + bag_slots
437+ bag_mask = bags < B
438+ starts = tl .load (offsets_ptr + FEATURE * B + bags , mask = bag_mask , other = 0 )
439+ ends = tl .load (offsets_ptr + FEATURE * B + bags + 1 , mask = bag_mask , other = 0 )
440+ lengths = ends - starts
441+
442+ positions = tl .arange (0 , histogram_chunk_size )
443+ input_mask = bag_mask [:, None ] & (positions [None , :] < lengths [:, None ])
444+ row_indices , invalid_indices = _load_checked_index (
445+ indices_ptr ,
446+ starts [:, None ] + positions [None , :],
447+ NUM_ROWS ,
448+ input_mask ,
449+ FUSED_BOUNDS_CHECK ,
450+ )
451+ row_indices = row_indices .to (tl .int32 )
452+ warning_count = tl .sum (invalid_indices .to (tl .int32 ))
453+ encoded_indices = row_indices + bag_slots [:, None ] * ROW_BINS
454+ counts = tl .histogram (
455+ encoded_indices .reshape ((bags_per_program * histogram_chunk_size ,)),
456+ bags_per_program * ROW_BINS ,
457+ mask = input_mask .reshape ((bags_per_program * histogram_chunk_size ,)),
458+ ).reshape ((bags_per_program , ROW_BINS ))
459+
460+ table_idx = tl .load (feature_table_map_ptr + FEATURE )
461+ table_offset = tl .load (table_offsets_ptr + table_idx )
462+ embedding_dim = tl .load (embedding_dims_ptr + FEATURE )
463+ embedding_offset = tl .load (embedding_offsets_ptr + FEATURE )
464+ rows = tl .arange (0 , ROW_BINS )
465+ columns = tl .arange (0 , BLOCK_SIZE )
466+ table = tl .load (
467+ weight_ptr + table_offset + rows [:, None ] * embedding_dim + columns [None , :],
468+ mask = (rows [:, None ] < NUM_ROWS ) & (columns [None , :] < embedding_dim ),
469+ other = 0 ,
470+ )
471+ bag_output = tl .dot (counts .to (tl .float16 ), table )
472+
473+ tail_lengths = tl .maximum (lengths - histogram_chunk_size , 0 )
474+ for tail in range (0 , tl .max (tail_lengths )):
475+ active = bag_mask & (tail < tail_lengths )
476+ row_idx , invalid = _load_checked_index (
477+ indices_ptr ,
478+ starts + histogram_chunk_size + tail ,
479+ NUM_ROWS ,
480+ active ,
481+ FUSED_BOUNDS_CHECK ,
482+ )
483+ if FUSED_BOUNDS_CHECK :
484+ warning_count += tl .sum (invalid .to (tl .int32 ))
485+ row = tl .load (
486+ weight_ptr
487+ + table_offset
488+ + row_idx [:, None ] * embedding_dim
489+ + columns [None , :],
490+ mask = active [:, None ] & (columns [None , :] < embedding_dim ),
491+ other = 0 ,
492+ )
493+ bag_output += row .to (tl .float32 )
494+
495+ tl .store (
496+ output_ptr
497+ + bags [:, None ] * total_embedding_dim
498+ + embedding_offset
499+ + columns [None , :],
500+ bag_output ,
501+ mask = bag_mask [:, None ] & (columns [None , :] < embedding_dim ),
502+ )
503+ if FUSED_BOUNDS_CHECK and warning_count > 0 :
504+ tl .atomic_add (bounds_check_warning_ptr , warning_count .to (tl .int64 ))
505+
506+
404507@triton .jit
405508def triton_tbe_backward_short_run_unweighted (
406509 dout_ptr ,
@@ -1153,6 +1256,10 @@ def forward(
11531256 precomputed_total_B : int = 0 ,
11541257 precomputed_max_B : int = 0 ,
11551258 hoist_transpose_to_forward : bool = True ,
1259+ histogram_feature : int = - 1 ,
1260+ histogram_num_rows : int = 0 ,
1261+ histogram_row_bins : int = 0 ,
1262+ histogram_block_size : int = 0 ,
11561263 bounds_check_warning : Optional [torch .Tensor ] = None ,
11571264 fused_bounds_check : bool = False ,
11581265 ) -> torch .Tensor :
@@ -1368,8 +1475,16 @@ def forward(
13681475 num_warps = num_warps ,
13691476 )
13701477 else :
1371- if is_amd ():
1372- _amd_fwd_unweighted_kernel [(B ,)](
1478+ use_small_table_kernel = (
1479+ histogram_feature >= 0
1480+ and not vbe
1481+ and not is_amd ()
1482+ and weight .dtype == torch .float16
1483+ )
1484+ if use_small_table_kernel :
1485+ table_batched_embedding_bag_forward_small_table_kernel [
1486+ (triton .cdiv (B , 16 ),)
1487+ ](
13731488 output ,
13741489 indices ,
13751490 offsets ,
@@ -1378,17 +1493,19 @@ def forward(
13781493 embedding_dims ,
13791494 embedding_offsets ,
13801495 feature_table_map ,
1381- row_output_offsets_ptr ,
1382- B_offsets_ptr ,
1496+ bounds_check_warning_ptr ,
13831497 total_embedding_dim ,
13841498 B ,
1385- T ,
1386- BLOCK_SIZE = block_size ,
1387- vbe = vbe ,
1388- num_warps = num_warps ,
1499+ FEATURE = histogram_feature ,
1500+ NUM_ROWS = histogram_num_rows ,
1501+ ROW_BINS = histogram_row_bins ,
1502+ BLOCK_SIZE = histogram_block_size ,
1503+ FUSED_BOUNDS_CHECK = fused_bounds_check ,
1504+ num_warps = 1 ,
13891505 )
1390- else :
1391- table_batched_embedding_bag_forward_unweighted_kernel [(B ,)](
1506+
1507+ if is_amd ():
1508+ _amd_fwd_unweighted_kernel [(B ,)](
13921509 output ,
13931510 indices ,
13941511 offsets ,
@@ -1397,18 +1514,50 @@ def forward(
13971514 embedding_dims ,
13981515 embedding_offsets ,
13991516 feature_table_map ,
1400- rows_cumsum ,
1401- bounds_check_warning_ptr ,
14021517 row_output_offsets_ptr ,
14031518 B_offsets_ptr ,
14041519 total_embedding_dim ,
14051520 B ,
14061521 T ,
14071522 BLOCK_SIZE = block_size ,
14081523 vbe = vbe ,
1409- FUSED_BOUNDS_CHECK = fused_bounds_check ,
14101524 num_warps = num_warps ,
14111525 )
1526+ else :
1527+ feature_ranges = (
1528+ [
1529+ (0 , histogram_feature ),
1530+ (histogram_feature + 1 , T ),
1531+ ]
1532+ if use_small_table_kernel
1533+ else [(0 , T )]
1534+ )
1535+ for feature_start , feature_end in feature_ranges :
1536+ if feature_start >= feature_end :
1537+ continue
1538+ table_batched_embedding_bag_forward_unweighted_kernel [(B ,)](
1539+ output ,
1540+ indices ,
1541+ offsets ,
1542+ weight ,
1543+ table_offsets ,
1544+ embedding_dims ,
1545+ embedding_offsets ,
1546+ feature_table_map ,
1547+ rows_cumsum ,
1548+ bounds_check_warning_ptr ,
1549+ row_output_offsets_ptr ,
1550+ B_offsets_ptr ,
1551+ total_embedding_dim ,
1552+ B ,
1553+ T ,
1554+ BLOCK_SIZE = block_size ,
1555+ vbe = vbe ,
1556+ FEATURE_START = feature_start ,
1557+ FEATURE_END = feature_end ,
1558+ FUSED_BOUNDS_CHECK = fused_bounds_check ,
1559+ num_warps = num_warps ,
1560+ )
14121561
14131562 # Record a CUDA event to mark forward kernel completion.
14141563 # This is needed for synchronization before NCCL collectives.
@@ -1906,6 +2055,10 @@ def backward(ctx, dout) -> Tuple[None, ...]:
19062055 None , # hoist_transpose_to_forward
19072056 None ,
19082057 None ,
2058+ None ,
2059+ None ,
2060+ None ,
2061+ None ,
19092062 )
19102063
19112064
@@ -1927,6 +2080,7 @@ def __init__(
19272080 optimizer : OptimType = OptimType .EXACT_SGD ,
19282081 device : Optional [torch .device ] = None ,
19292082 hoist_transpose_to_forward : bool = False ,
2083+ bag_size_hints : Optional [List [int ]] = None ,
19302084 fused_bounds_check : bool = False ,
19312085 ) -> None :
19322086 super ().__init__ ()
@@ -2005,6 +2159,35 @@ def __init__(
20052159 self .output_dtype = (
20062160 output_dtype if output_dtype is not None else weights_precision
20072161 )
2162+ if bag_size_hints is not None and len (bag_size_hints ) != self .T :
2163+ raise ValueError (
2164+ f"bag_size_hints must have { self .T } entries, "
2165+ f"got { len (bag_size_hints )} "
2166+ )
2167+
2168+ self ._histogram_feature = - 1
2169+ self ._histogram_num_rows = 0
2170+ self ._histogram_row_bins = 0
2171+ self ._histogram_block_size = 0
2172+ if (
2173+ bag_size_hints is not None
2174+ and weights_precision == torch .float16
2175+ and self .output_dtype == torch .float32
2176+ ):
2177+ candidates = []
2178+ for feature , table in enumerate (feature_table_map ):
2179+ num_rows = hash_sizes [table ]
2180+ dim = feature_dims [feature ]
2181+ bag_size = bag_size_hints [feature ]
2182+ if num_rows <= 64 and 64 <= dim <= 128 and bag_size >= 64 :
2183+ candidates .append ((bag_size * dim , feature , num_rows , dim ))
2184+ if candidates :
2185+ _ , feature , num_rows , dim = max (candidates )
2186+ self ._histogram_feature = feature
2187+ self ._histogram_num_rows = num_rows
2188+ self ._histogram_row_bins = max (32 , triton .next_power_of_2 (num_rows ))
2189+ self ._histogram_block_size = triton .next_power_of_2 (dim )
2190+
20082191 self .stochastic_rounding = stochastic_rounding
20092192 self .learning_rate = learning_rate
20102193 self .eps = eps
@@ -2269,6 +2452,10 @@ def forward(
22692452 total_B ,
22702453 max_B ,
22712454 self .hoist_transpose_to_forward ,
2455+ self ._histogram_feature ,
2456+ self ._histogram_num_rows ,
2457+ self ._histogram_row_bins ,
2458+ self ._histogram_block_size ,
22722459 self .bounds_check_warning ,
22732460 use_fused_bounds_check ,
22742461 )
0 commit comments