-
Notifications
You must be signed in to change notification settings - Fork 108
Add small key type tests #812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from all commits
e7f0ce2
3d06afd
e77f232
22ad7ae
72fb2dd
6dc9527
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,6 +47,22 @@ struct packed { | |
| using type = void; ///< `void` type by default | ||
| }; | ||
|
|
||
| /** | ||
| * @brief Denotes the packed type when the size of the object is 1. | ||
| */ | ||
| template <> | ||
| struct packed<sizeof(uint8_t)> { | ||
| using type = uint8_t; ///< Packed type as `uint8_t` if the size of the object is 1 | ||
| }; | ||
|
|
||
| /** | ||
| * @brief Denotes the packed type when the size of the object is 2. | ||
| */ | ||
| template <> | ||
| struct packed<sizeof(uint16_t)> { | ||
| using type = uint16_t; ///< Packed type as `uint16_t` if the size of the object is 2 | ||
| }; | ||
|
Comment on lines
+61
to
+64
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could we add a 2B key-value pair in the map unit test to exercise this code path? One test case is sufficient. |
||
|
|
||
| /** | ||
| * @brief Denotes the packed type when the size of the object is 8. | ||
| */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -69,6 +69,7 @@ TEST_CASE("atomic_storage_test", "") | |
| cuda::proclaim_return_type<Key>(build_fn{})); | ||
|
|
||
| set.insert_async(keys_begin, keys_begin + num_keys); | ||
| CUCO_CUDA_TRY(cudaDeviceSynchronize()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. question: why is this needed?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It shouldn't be required since it is running on the default stream IIUC. It's probably a red herring trying to fix open bug #804. |
||
| auto const count = set.size(); | ||
|
|
||
| REQUIRE(count == num_keys); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,10 +26,12 @@ | |
|
|
||
| #include <catch2/catch_template_test_macros.hpp> | ||
|
|
||
| #include <cstdint> | ||
|
|
||
| using size_type = std::size_t; | ||
|
|
||
| template <typename Set> | ||
| void test_for_each(Set& set, size_type num_keys) | ||
| void test_for_each(Set& set, size_type num_keys, size_type expected_evens, size_type expected_odds) | ||
| { | ||
| using Key = typename Set::key_type; | ||
|
|
||
|
|
@@ -40,7 +42,7 @@ void test_for_each(Set& set, size_type num_keys) | |
| // Insert keys | ||
| auto keys_begin = cuda::make_transform_iterator( | ||
| cuda::counting_iterator<size_type>{0}, cuda::proclaim_return_type<Key>([] __device__(auto i) { | ||
| // generates a sequence of 1, 2, 1, 2, ... | ||
| // generates a sequence of 0, 1, 2, ... | ||
| return static_cast<Key>(i); | ||
| })); | ||
| set.insert(keys_begin, keys_begin + num_keys, stream); | ||
|
|
@@ -56,7 +58,7 @@ void test_for_each(Set& set, size_type num_keys) | |
| if (slot % 2 == 0) { counter->fetch_add(slot, cuda::memory_order_relaxed); } | ||
| }, | ||
| stream); | ||
| REQUIRE(counter_storage.load_to_host(stream) == 249'500); | ||
| REQUIRE(counter_storage.load_to_host(stream) == expected_evens); | ||
|
|
||
| counter_storage.reset(stream); | ||
|
|
||
|
|
@@ -68,13 +70,19 @@ void test_for_each(Set& set, size_type num_keys) | |
| if (!(slot % 2 == 0)) { counter->fetch_add(slot, cuda::memory_order_relaxed); } | ||
| }, | ||
| stream); | ||
| REQUIRE(counter_storage.load_to_host(stream) == 250'000); | ||
| REQUIRE(counter_storage.load_to_host(stream) == expected_odds); | ||
| } | ||
|
|
||
| TEMPLATE_TEST_CASE_SIG( | ||
| "static_set for_each tests", | ||
| "", | ||
| ((typename Key, cuco::test::probe_sequence Probe, int CGSize), Key, Probe, CGSize), | ||
| (uint8_t, cuco::test::probe_sequence::double_hashing, 1), | ||
| (uint8_t, cuco::test::probe_sequence::linear_probing, 1), | ||
| (uint16_t, cuco::test::probe_sequence::double_hashing, 1), | ||
| (uint16_t, cuco::test::probe_sequence::double_hashing, 2), | ||
| (uint16_t, cuco::test::probe_sequence::linear_probing, 1), | ||
| (uint16_t, cuco::test::probe_sequence::linear_probing, 2), | ||
|
Comment on lines
+80
to
+85
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if using signed integers (as in the rest of the tests) would make sense for consistency. Plus, it would probably also catch some unintended overflow/wrap-around errors. Just a suggestion though - no hard requirement. |
||
| (int32_t, cuco::test::probe_sequence::double_hashing, 1), | ||
| (int32_t, cuco::test::probe_sequence::double_hashing, 2), | ||
| (int64_t, cuco::test::probe_sequence::double_hashing, 1), | ||
|
|
@@ -92,7 +100,14 @@ TEMPLATE_TEST_CASE_SIG( | |
| #endif | ||
| ) | ||
| { | ||
| constexpr size_type num_keys{1'000}; | ||
| // Limit key count for small types: leave room for the 0xFF/0xFFFF sentinel. | ||
| // Expected sums are pre-computed per type class: | ||
| // uint8_t (num_keys=100): sum of evens 0..98 = 2450, sum of odds 1..99 = 2500 | ||
| // uint16_t+ (num_keys=1000): sum of evens 0..998 = 249'500, sum of odds 1..999 = 250'000 | ||
| constexpr size_type num_keys = (sizeof(Key) == 1) ? 100 : 1'000; | ||
| constexpr size_type expected_evens = (sizeof(Key) == 1) ? 2'450 : 249'500; | ||
| constexpr size_type expected_odds = (sizeof(Key) == 1) ? 2'500 : 250'000; | ||
|
|
||
| using probe = std::conditional_t< | ||
| Probe == cuco::test::probe_sequence::linear_probing, | ||
| cuco::linear_probing<CGSize, cuco::murmurhash3_32<Key>>, | ||
|
|
@@ -107,5 +122,5 @@ TEMPLATE_TEST_CASE_SIG( | |
| cuco::storage<2>>; | ||
|
|
||
| auto set = set_t{num_keys, cuco::empty_key<Key>{static_cast<Key>(-1)}}; | ||
| test_for_each(set, num_keys); | ||
| test_for_each(set, num_keys, expected_evens, expected_odds); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We pack paired data (e.g., a 32-bit key and 32-bit value) into a single 64-bit unit for CAS, used only in map scenarios. Therefore, the smallest CAS we need is 8 bits (1B), and the smallest packed type is 2B, making the 1B overload unnecessary.