Skip to content

[Draft] Ptxpulib 186 fast block bucketize - #145

Draft
mkrze wants to merge 2 commits into
intel:mainfrom
mkrze:ptxpulib-186-fast-block-bucketize
Draft

mkrze wants to merge 2 commits into
intel:mainfrom
mkrze:ptxpulib-186-fast-block-bucketize

Conversation

@mkrze

@mkrze mkrze commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Draft, in progress

mkrze added 2 commits October 7, 2026 21:05
block_bucketize_sparse_features(_inference) gave each row to one
work-item that walked its indices in order. Batch-1 inference, as in
TorchRec row-wise sharding for DLRM-v3, has a few rows with thousands of
indices, so the kernel ran on a handful of work-items: 25 ms for one
16k-index row on Data Center GPU Max, against 0.12 ms on the CPU.

Add a chunked path. Rows are split into chunks of one sub-group (32
indices). One kernel counts the buckets of each chunk, a column-wise
cumsum over chunks gives every chunk its offset within its (bucket, row)
and new_lengths, and the scatter ranks each index within its chunk and
bucket with a sub-group ballot. Positions follow the input order, so the
output equals the serial kernels and the CPU kernel bit for bit, for
pooled rows too. The bucket arithmetic repeats the serial kernels.

The serial kernels stay unchanged and remain the default for many or
short rows, where they already fill the device. The chunked path is
chosen for at most 8192 rows with a mean length of at least 128, the
range where it was faster in a sweep on Data Center GPU Max.
FBGEMM_XPU_BLOCK_BUCKETIZE_KERNEL=serial|chunked forces one path.

Data Center GPU Max, one tile, sequence=True, return_bucket_mapping=True,
8 buckets: 256 / 2048 / 16384 indices in one row 0.48 / 3.3 / 25.8 ms ->
0.24 / 0.27 / 0.27 ms; three 16k rows with uneven buckets 36.6 -> 0.44 ms.

Signed-off-by: mkrze <mateusz.krzemieniewski@intel.com>
Compare every output of block_bucketize_sparse_features(_inference) with
FBGEMM's CPU kernels for the serial path, the chunked path and the
automatic choice. Row lengths straddle the 32-index chunk (0, 1, 31, 32,
33) and reach 16384, with 1 to 64 buckets, int32/int64 lengths and
indices, weights, bucketize_pos, keep_orig_idx (global and per feature),
total_num_blocks, uneven buckets, raw and out-of-range ids, variable
batch sizes and a seeded random sweep. populate_bucketized_permute must
reproduce the chunked unbucketize_permute.

Add a long-row case for both paths to the non-current-device test.

Signed-off-by: mkrze <mateusz.krzemieniewski@intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant