[cuco] Adds support for 1 and 2 byte key and value types in fixed_capacity_map - #10025
[cuco] Adds support for 1 and 2 byte key and value types in fixed_capacity_map#10025ryanjspears wants to merge 5 commits into
fixed_capacity_map#10025Conversation
2eb1181 to
df921f8
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughChanges
Packed map type support
Possibly related PRs
Suggested labels: Suggested reviewers: Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
cudax/include/cuda/experimental/__cuco/detail/open_addressing/open_addressing_ref_impl.cuh (1)
701-710: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy liftimportant:
device_buffer<__value_type>only guaranteesalignof(__value_type), butpacked_typecan need stricter alignment. Reinterpreting__address,__expected, and__desiredaspacked_type*is UB for small pair-like slots such asuint8_t/uint8_toruint16_t/uint16_t. Add an aligned packed contract or gate this path onalignof(__value_type) >= alignof(packed_type).
🧹 Nitpick comments (1)
cudax/test/cuco/fixed_capacity_map/test_insert_and_contains.cu (1)
38-39: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winsuggestion: Add mixed-width key/value instantiations.
map_typeuseskey_typefor both template arguments, so these cases cover(uint8_t, uint8_t)and(uint16_t, uint16_t)but not the independently changed mapped-type contract, such as 32-bit keys with 8/16-bit values. Add a separate key/value type list or a few explicit mixed-width cases. The suppliedmap_typealias and new type list show that only same-width pairs are currently exercised.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: f4680b6f-be66-4b99-97c2-382fbccbe2b1
📒 Files selected for processing (3)
cudax/include/cuda/experimental/__cuco/detail/open_addressing/open_addressing_ref_impl.cuhcudax/include/cuda/experimental/__cuco/fixed_capacity_map_ref.cuhcudax/test/cuco/fixed_capacity_map/test_insert_and_contains.cu
ddadb4d to
b886248
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: c9f14394-1f67-4604-9307-997d26e163f6
📒 Files selected for processing (3)
cudax/include/cuda/experimental/__cuco/detail/open_addressing/open_addressing_ref_impl.cuhcudax/include/cuda/experimental/__cuco/fixed_capacity_map_ref.cuhcudax/test/cuco/fixed_capacity_map/test_insert_and_contains.cu
🚧 Files skipped from review as they are similar to previous changes (1)
- cudax/include/cuda/experimental/__cuco/detail/open_addressing/open_addressing_ref_impl.cuh
b886248 to
da4bc4a
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
cudax/test/cuco/fixed_capacity_map/test_insert_and_contains.cu (1)
140-149: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winsuggestion: Exercise a mixed-width pair through
insertandcontains, not onlysizeof. The<uint8_t, uint32_t>assertion checks map instantiation and layout, but does not execute the packed CAS path where width or representation mismatches would surface.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 81d8afdd-0f78-460f-8331-697a0c6abea1
📒 Files selected for processing (6)
cudax/include/cuda/experimental/__cuco/detail/open_addressing/open_addressing_ref_impl.cuhcudax/include/cuda/experimental/__cuco/fixed_capacity_map_ref.cuhcudax/test/CMakeLists.txtcudax/test/cuco/fixed_capacity_map/test_insert_and_contains.cucudax/test/cuco/fixed_capacity_map/test_key_size_fail.cucudax/test/cuco/fixed_capacity_map/test_slot_size_fail.cu
🚧 Files skipped from review as they are similar to previous changes (2)
- cudax/include/cuda/experimental/__cuco/fixed_capacity_map_ref.cuh
- cudax/include/cuda/experimental/__cuco/detail/open_addressing/open_addressing_ref_impl.cuh
da4bc4a to
eb7d9a9
Compare
|
Thanks @ryanjspears for working on this! |
PointKernel
left a comment
There was a problem hiding this comment.
This is probably not a simple task to target right now. The original cuco::pair uses the next power-of-two alignment. Consequently, cuco::pair<int, int> is 8-byte aligned and cuco::pair<int16_t, int16_t> is 4-byte aligned, whereas the corresponding cuda::std::pair types are only 4- and 2-byte aligned.
When possible, cuco packs the key-value pair into a single integer and updates it with packed_cas. For example, a 4-byte key and 4-byte value use one 8-byte atomic CAS, which requires 8-byte alignment, not the 4-byte alignment provided by cuda::std::pair<int, int>. A power-of-two size check alone does not guarantee this alignment. The default allocation may happen to be sufficiently aligned, but external span storage and the local expected and desired objects are not guaranteed to be.
@ryanjspears Thanks for working on this. I haven’t found a clean way to preserve the original slot-alignment guarantee with cuda::std::pair yet, so we should resolve that design question before proceeding with subword support.
|
@ryanjspears I thought about this more, and I think we have a clean way forward without losing the packed CAS optimization. Currently, For the storage, we only need to check the base address when constructing the storage reference. The slots are contiguous and The storage reference can retain that result and use The resulting dispatch would be approximately: if constexpr (has_packable_representation)
{
if (storage_ref.is_packed_cas_aligned())
{
return packed_cas(...);
}
}
return non_packed_cas(...);Could you please update the PR along these lines? |
|
Thanks for the feedback @PointKernel. Yes, I will submit an update shortly! |
`fixed_capacity_map`
5fec78d to
7d91903
Compare
|
@PointKernel I updated the dispatch to your suggestion. I also created |
|
/ok to test 71d8664 |
|
@ryanjspears Thanks for the fast turnaround. The code looks great. I just pushed a single line change where the old code checks against |
|
Thanks @PointKernel , is there another |
That will be great! |
| { | ||
| constexpr uint64_t __alignmask = (sizeof(uint16_t) - 1); | ||
| uint16_t* __aligned = (uint16_t*) ((intptr_t) __ptr & (~__alignmask)); | ||
| uint16_t* __aligned = (uint16_t*) ((intptr_t) __ptr & (~__alignmask)); // NOLINT(performance-no-int-to-ptr) |
There was a problem hiding this comment.
The new small-type tests expose the existing clang-tidy false positive; atomic behavior is unchanged.
|
/ok to test b6ce4f2 |
Description
Makes progress on #9987
Adds support for 1 and 2 byte key and value types in
fixed_capacity_mapThe insert and contains tests now cover 1 and 2 byte types and dynamically assign the number of keys based on byte size. This is needed because 400 could not fit into 1 byte, thus needs to be changed accordingly.
Checklist