Skip to content

Speed up cooperative bloom filter layouts - #866

Draft
sleeepyjack wants to merge 14 commits into
NVIDIA:devfrom
sleeepyjack:bloom-warp-tile
Draft

sleeepyjack wants to merge 14 commits into
NVIDIA:devfrom
sleeepyjack:bloom-warp-tile

Conversation

@sleeepyjack

@sleeepyjack sleeepyjack commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #865 (this PR's changes).

  • Select each lane's salts once, not per key. The per-key salt selection was a branchy decision tree on the lane rank. Per-thread layouts (horizontal layout 1) now use the same path with compile-time salts, so the separate per-thread pattern code goes away.
  • Full-warp masks in the bulk kernels. Cooperative-groups tiles sync with a per-tile mask that ptxas can't prove uniform, so every tile vote took the divergent WARPSYNC path. The bulk kernels now use a small stateless tile whose shuffles and votes use the full-warp mask. The device API keeps the caller's group.

Default 32 B layouts are unchanged; results are identical.

GB200 (1965 MHz lock), int64 keys, k = words per block, 2^28 keys per launch, G keys/s, #865 → this PR:

16 MB 2 GB
contains, 32 B blocks, 2x4 61 → 177 46.7 → 48.2
contains, 64 B blocks, 2x8 (default) 56 → 133 42.8 → 48.1
add, 64 B blocks, 16x1 (default) 52 → 91 same
add, 64 B blocks, 16x1, FastL2Add 44 → 77 same
default 32 B layouts within ±1% same

Known: 32 B 2x4 add (not a useful layout) is 9% slower for DRAM-resident filters.

Take the skipped-word index from the top bits of the hash instead of a
salted product, and with one word per thread compare the word index
against it directly. The add loop needs two instructions per key for the
skip instead of four. Which word a key skips changes; the false-positive
rate does not (8-24 bits/key, int64 keys, 256-bit blocks).

On GB200, where FastL2Add's add is issue-bound, add is 5% faster with one
key per thread (127.2 -> 133.7 G keys/s at 16 MB) and 4% faster with four
(144.0 -> 149.9); contains is within 0.4%.
Contains cleared the skipped word's expected pattern, so the compiler could
no longer test each word's single fingerprint bit directly. Exclude the
skipped word by comparing its index instead; contains then compiles to the
default policy's bit tests plus one predicate per word.

On GB200 FastL2Add contains is 5% faster with one key per thread (184.8 ->
193.9 G keys/s at 16 MB) and 2% with four. Results and the bit pattern are
unchanged.
Cooperative contains (horizontal layout > 1) now also excludes the skipped
word by index, and a thread that owns the whole first sector issues one
atomic less, shifting past the skipped word, instead of a conditional
atomic per word. Adds 64-byte-block and 64-bit-word cases for the
per-thread add path to the tests.
Cooperative add/contains selected each lane's salts per key through a
binary decision tree on the lane rank. With 16 lanes per key the tree
stayed branchy, which also put convergence checks around every shuffle.
Select the salts once per group (thread_salts) and reuse them for all
keys. Works for any add/contains layout, including mixed ones; adds a
mixed-layout equivalence test.

Larger horizontal layouts now keep more keys in flight and can use more
registers; the layout docs say so.
The bulk kernels used cooperative-groups tiles, whose collectives sync
with a per-tile mask. That mask differs between lanes, so every tile
vote in contains took the divergent WARPSYNC path, and with 16-lane
tiles every shuffle carried a convergence check.

Every lane of the bulk kernels reaches the collectives, so give them a
stateless warp_tile that syncs with the full-warp mask and computes a
tile vote from one warp ballot. The partial-tile add/contains paths now
shuffle outside the per-key validity branch; an invalid contains key
probes block 0 and its result is discarded. The device API keeps the
caller's group.
array_pattern takes a ClearSkipped flag instead of a separate
full_array_pattern, and the contains index check moves into one
bloom_filter_impl helper, so matches_pattern is no longer needed.
The flag says whether a zero pattern is dropped, not whether FastL2Add
is on: the FastL2Add path that skips the word by index passes false.
# Conflicts:
#	include/cuco/detail/bloom_filter/bloom_filter_impl.cuh
#	include/cuco/detail/bloom_filter/bloom_filter_policy.cuh
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