Skip to content

Commit 8b73aee

Browse files
authored
Fix problems with heterogeneous insert input types (#387)
1 parent e41bf45 commit 8b73aee

7 files changed

Lines changed: 221 additions & 124 deletions

File tree

include/cuco/detail/open_addressing/open_addressing_ref_impl.cuh

Lines changed: 122 additions & 61 deletions
Large diffs are not rendered by default.

include/cuco/detail/static_map/static_map_ref.inl

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
#include <cuco/operator.hpp>
2020

21+
#include <thrust/tuple.h>
22+
2123
#include <cuda/atomic>
2224

2325
#include <cooperative_groups.h>
@@ -171,7 +173,8 @@ class operator_impl<
171173
using base_type = static_map_ref<Key, T, Scope, KeyEqual, ProbingScheme, StorageRef>;
172174
using ref_type = static_map_ref<Key, T, Scope, KeyEqual, ProbingScheme, StorageRef, Operators...>;
173175
using key_type = typename base_type::key_type;
174-
using value_type = typename base_type::value_type;
176+
using value_type = typename base_type::value_type;
177+
using mapped_type = T;
175178

176179
static constexpr auto cg_size = base_type::cg_size;
177180
static constexpr auto window_size = base_type::window_size;
@@ -180,7 +183,7 @@ class operator_impl<
180183
/**
181184
* @brief Inserts an element.
182185
*
183-
* @tparam Value Input type which is implicitly convertible to 'value_type'
186+
* @tparam Value Input type which is convertible to 'value_type'
184187
*
185188
* @param value The element to insert
186189
*
@@ -196,7 +199,7 @@ class operator_impl<
196199
/**
197200
* @brief Inserts an element.
198201
*
199-
* @tparam Value Input type which is implicitly convertible to 'value_type'
202+
* @tparam Value Input type which is convertible to 'value_type'
200203
*
201204
* @param group The Cooperative Group used to perform group insert
202205
* @param value The element to insert
@@ -225,7 +228,8 @@ class operator_impl<
225228
using base_type = static_map_ref<Key, T, Scope, KeyEqual, ProbingScheme, StorageRef>;
226229
using ref_type = static_map_ref<Key, T, Scope, KeyEqual, ProbingScheme, StorageRef, Operators...>;
227230
using key_type = typename base_type::key_type;
228-
using value_type = typename base_type::value_type;
231+
using value_type = typename base_type::value_type;
232+
using mapped_type = T;
229233

230234
static constexpr auto cg_size = base_type::cg_size;
231235
static constexpr auto window_size = base_type::window_size;
@@ -238,7 +242,7 @@ class operator_impl<
238242
* @brief Inserts a key-value pair `{k, v}` if it's not present in the map. Otherwise, assigns `v`
239243
* to the mapped_type corresponding to the key `k`.
240244
*
241-
* @tparam Value Input type which is implicitly convertible to 'value_type'
245+
* @tparam Value Input type which is convertible to 'value_type'
242246
*
243247
* @param value The element to insert
244248
*/
@@ -247,8 +251,10 @@ class operator_impl<
247251
{
248252
static_assert(cg_size == 1, "Non-CG operation is incompatible with the current probing scheme");
249253

250-
ref_type& ref_ = static_cast<ref_type&>(*this);
251-
auto const key = value.first;
254+
ref_type& ref_ = static_cast<ref_type&>(*this);
255+
256+
auto const val = ref_.impl_.heterogeneous_value(value);
257+
auto const key = ref_.impl_.extract_key(val);
252258
auto& probing_scheme = ref_.impl_.probing_scheme();
253259
auto storage_ref = ref_.impl_.storage_ref();
254260
auto probing_iter = probing_scheme(key, storage_ref.window_extent());
@@ -264,14 +270,14 @@ class operator_impl<
264270
auto const intra_window_index = thrust::distance(window_slots.begin(), &slot_content);
265271
ref_.impl_.atomic_store(
266272
&((storage_ref.data() + *probing_iter)->data() + intra_window_index)->second,
267-
value.second);
273+
val.second);
268274
return;
269275
}
270276
if (eq_res == detail::equal_result::EMPTY or
271277
cuco::detail::bitwise_compare(slot_content.first, ref_.impl_.erased_key_sentinel())) {
272278
auto const intra_window_index = thrust::distance(window_slots.begin(), &slot_content);
273279
if (attempt_insert_or_assign(
274-
(storage_ref.data() + *probing_iter)->data() + intra_window_index, value)) {
280+
(storage_ref.data() + *probing_iter)->data() + intra_window_index, val)) {
275281
return;
276282
}
277283
}
@@ -286,7 +292,7 @@ class operator_impl<
286292
* @brief Inserts a key-value pair `{k, v}` if it's not present in the map. Otherwise, assigns `v`
287293
* to the mapped_type corresponding to the key `k`.
288294
*
289-
* @tparam Value Input type which is implicitly convertible to 'value_type'
295+
* @tparam Value Input type which is convertible to 'value_type'
290296
*
291297
* @param group The Cooperative Group used to perform group insert
292298
* @param value The element to insert
@@ -297,7 +303,8 @@ class operator_impl<
297303
{
298304
ref_type& ref_ = static_cast<ref_type&>(*this);
299305

300-
auto const key = value.first;
306+
auto const val = ref_.impl_.heterogeneous_value(value);
307+
auto const key = ref_.impl_.extract_key(val);
301308
auto& probing_scheme = ref_.impl_.probing_scheme();
302309
auto storage_ref = ref_.impl_.storage_ref();
303310
auto probing_iter = probing_scheme(group, key, storage_ref.window_extent());
@@ -332,7 +339,7 @@ class operator_impl<
332339
if (group.thread_rank() == src_lane) {
333340
ref_.impl_.atomic_store(
334341
&((storage_ref.data() + *probing_iter)->data() + intra_window_index)->second,
335-
value.second);
342+
val.second);
336343
}
337344
group.sync();
338345
return;
@@ -345,7 +352,7 @@ class operator_impl<
345352
auto const status =
346353
(group.thread_rank() == src_lane)
347354
? attempt_insert_or_assign(
348-
(storage_ref.data() + *probing_iter)->data() + intra_window_index, value)
355+
(storage_ref.data() + *probing_iter)->data() + intra_window_index, val)
349356
: false;
350357

351358
// Exit if inserted or assigned
@@ -377,7 +384,8 @@ class operator_impl<
377384
ref_type& ref_ = static_cast<ref_type&>(*this);
378385
auto const expected_key = ref_.impl_.empty_slot_sentinel().first;
379386

380-
auto old_key = ref_.impl_.compare_and_swap(&slot->first, expected_key, value.first);
387+
auto old_key =
388+
ref_.impl_.compare_and_swap(&slot->first, expected_key, static_cast<key_type>(value.first));
381389
auto* old_key_ptr = reinterpret_cast<key_type*>(&old_key);
382390

383391
// if key success or key was already present in the map
@@ -406,6 +414,7 @@ class operator_impl<
406414
using ref_type = static_map_ref<Key, T, Scope, KeyEqual, ProbingScheme, StorageRef, Operators...>;
407415
using key_type = typename base_type::key_type;
408416
using value_type = typename base_type::value_type;
417+
using mapped_type = T;
409418
using iterator = typename base_type::iterator;
410419
using const_iterator = typename base_type::const_iterator;
411420

@@ -446,7 +455,7 @@ class operator_impl<
446455
* element that prevented the insertion) and a `bool` denoting whether the insertion took place or
447456
* not.
448457
*
449-
* @tparam Value Input type which is implicitly convertible to 'value_type'
458+
* @tparam Value Input type which is convertible to 'value_type'
450459
*
451460
* @param value The element to insert
452461
*
@@ -467,7 +476,7 @@ class operator_impl<
467476
* element that prevented the insertion) and a `bool` denoting whether the insertion took place or
468477
* not.
469478
*
470-
* @tparam Value Input type which is implicitly convertible to 'value_type'
479+
* @tparam Value Input type which is convertible to 'value_type'
471480
*
472481
* @param group The Cooperative Group used to perform group insert_and_find
473482
* @param value The element to insert
@@ -506,7 +515,7 @@ class operator_impl<
506515
/**
507516
* @brief Erases an element.
508517
*
509-
* @tparam ProbeKey Input type which is implicitly convertible to 'key_type'
518+
* @tparam ProbeKey Input key type which is convertible to 'key_type'
510519
*
511520
* @param key The element to erase
512521
*
@@ -522,7 +531,7 @@ class operator_impl<
522531
/**
523532
* @brief Erases an element.
524533
*
525-
* @tparam ProbeKey Input type which is implicitly convertible to 'key_type'
534+
* @tparam ProbeKey Input key type which is convertible to 'key_type'
526535
*
527536
* @param group The Cooperative Group used to perform group insert
528537
* @param key The element to erase
@@ -563,7 +572,7 @@ class operator_impl<
563572
* @note If the probe key `key` was inserted into the container, returns
564573
* true. Otherwise, returns false.
565574
*
566-
* @tparam ProbeKey Probe key type
575+
* @tparam ProbeKey Input key type which is convertible to 'key_type'
567576
*
568577
* @param key The key to search for
569578
*
@@ -583,7 +592,7 @@ class operator_impl<
583592
* @note If the probe key `key` was inserted into the container, returns
584593
* true. Otherwise, returns false.
585594
*
586-
* @tparam ProbeKey Probe key type
595+
* @tparam ProbeKey Input key type which is convertible to 'key_type'
587596
*
588597
* @param group The Cooperative Group used to perform group contains
589598
* @param key The key to search for
@@ -652,7 +661,7 @@ class operator_impl<
652661
* @note Returns a un-incrementable input iterator to the element whose key is equivalent to
653662
* `key`. If no such element exists, returns `end()`.
654663
*
655-
* @tparam ProbeKey Probe key type
664+
* @tparam ProbeKey Input key type which is convertible to 'key_type'
656665
*
657666
* @param key The key to search for
658667
*
@@ -672,7 +681,7 @@ class operator_impl<
672681
* @note Returns a un-incrementable input iterator to the element whose key is equivalent to
673682
* `key`. If no such element exists, returns `end()`.
674683
*
675-
* @tparam ProbeKey Probe key type
684+
* @tparam ProbeKey Input key type which is convertible to 'key_type'
676685
*
677686
* @param group The Cooperative Group used to perform this operation
678687
* @param key The key to search for

include/cuco/detail/static_set/static_set_ref.inl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ class operator_impl<op::insert_tag,
148148
/**
149149
* @brief Inserts an element.
150150
*
151-
* @tparam Value Input type which is implicitly convertible to 'value_type'
151+
* @tparam Value Input type which is convertible to 'value_type'
152152
*
153153
* @param value The element to insert
154154
*
@@ -164,7 +164,7 @@ class operator_impl<op::insert_tag,
164164
/**
165165
* @brief Inserts an element.
166166
*
167-
* @tparam Value Input type which is implicitly convertible to 'value_type'
167+
* @tparam Value Input type which is convertible to 'value_type'
168168
*
169169
* @param group The Cooperative Group used to perform group insert
170170
* @param value The element to insert
@@ -232,7 +232,7 @@ class operator_impl<op::insert_and_find_tag,
232232
* element that prevented the insertion) and a `bool` denoting whether the insertion took place or
233233
* not.
234234
*
235-
* @tparam Value Input type which is implicitly convertible to 'value_type'
235+
* @tparam Value Input type which is convertible to 'value_type'
236236
*
237237
* @param value The element to insert
238238
*
@@ -253,7 +253,7 @@ class operator_impl<op::insert_and_find_tag,
253253
* element that prevented the insertion) and a `bool` denoting whether the insertion took place or
254254
* not.
255255
*
256-
* @tparam Value Input type which is implicitly convertible to 'value_type'
256+
* @tparam Value Input type which is convertible to 'value_type'
257257
*
258258
* @param group The Cooperative Group used to perform group insert_and_find
259259
* @param value The element to insert
@@ -290,7 +290,7 @@ class operator_impl<op::erase_tag,
290290
/**
291291
* @brief Erases an element.
292292
*
293-
* @tparam ProbeKey Input type which is implicitly convertible to 'key_type'
293+
* @tparam ProbeKey Input type which is convertible to 'key_type'
294294
*
295295
* @param key The element to erase
296296
*
@@ -306,7 +306,7 @@ class operator_impl<op::erase_tag,
306306
/**
307307
* @brief Erases an element.
308308
*
309-
* @tparam ProbeKey Input type which is implicitly convertible to 'key_type'
309+
* @tparam ProbeKey Input type which is convertible to 'key_type'
310310
*
311311
* @param group The Cooperative Group used to perform group erase
312312
* @param value The element to erase
@@ -345,7 +345,7 @@ class operator_impl<op::contains_tag,
345345
* @note If the probe key `key` was inserted into the container, returns true. Otherwise, returns
346346
* false.
347347
*
348-
* @tparam ProbeKey Probe key type
348+
* @tparam ProbeKey Input type which is convertible to 'key_type'
349349
*
350350
* @param key The key to search for
351351
*
@@ -364,7 +364,7 @@ class operator_impl<op::contains_tag,
364364
* @note If the probe key `key` was inserted into the container, returns true. Otherwise, returns
365365
* false.
366366
*
367-
* @tparam ProbeKey Probe key type
367+
* @tparam ProbeKey Input type which is convertible to 'key_type'
368368
*
369369
* @param group The Cooperative Group used to perform group contains
370370
* @param key The key to search for
@@ -431,7 +431,7 @@ class operator_impl<op::find_tag,
431431
* @note Returns a un-incrementable input iterator to the element whose key is equivalent to
432432
* `key`. If no such element exists, returns `end()`.
433433
*
434-
* @tparam ProbeKey Probe key type
434+
* @tparam ProbeKey Input type which is convertible to 'key_type'
435435
*
436436
* @param key The key to search for
437437
*
@@ -451,7 +451,7 @@ class operator_impl<op::find_tag,
451451
* @note Returns a un-incrementable input iterator to the element whose key is equivalent to
452452
* `key`. If no such element exists, returns `end()`.
453453
*
454-
* @tparam ProbeKey Probe key type
454+
* @tparam ProbeKey Input type which is convertible to 'key_type'
455455
*
456456
* @param group The Cooperative Group used to perform this operation
457457
* @param key The key to search for

include/cuco/detail/traits.hpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
#include <thrust/device_reference.h>
1919
#include <thrust/tuple.h>
2020

21+
#include <cuda/std/tuple>
2122
#include <cuda/std/type_traits>
22-
2323
#include <tuple>
2424

2525
namespace cuco::detail {
@@ -36,6 +36,20 @@ struct is_std_pair_like<T,
3636
conditional_t<std::tuple_size<T>::value == 2, cuda::std::true_type, cuda::std::false_type> {
3737
};
3838

39+
template <typename T, typename = void>
40+
struct is_cuda_std_pair_like : cuda::std::false_type {
41+
};
42+
43+
template <typename T>
44+
struct is_cuda_std_pair_like<
45+
T,
46+
cuda::std::void_t<decltype(cuda::std::get<0>(cuda::std::declval<T>())),
47+
decltype(cuda::std::get<1>(cuda::std::declval<T>()))>>
48+
: cuda::std::conditional_t<cuda::std::tuple_size<T>::value == 2,
49+
cuda::std::true_type,
50+
cuda::std::false_type> {
51+
};
52+
3953
template <typename T, typename = void>
4054
struct is_thrust_pair_like_impl : cuda::std::false_type {
4155
};

include/cuco/pair.cuh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <thrust/tuple.h>
2424

2525
#include <cuda/std/tuple>
26+
#include <tuple>
2627
#include <type_traits>
2728

2829
namespace cuco {
@@ -86,6 +87,19 @@ struct alignas(detail::pair_alignment<First, Second>()) pair {
8687
* @param p The input pair to copy from
8788
*/
8889
template <typename T, std::enable_if_t<detail::is_std_pair_like<T>::value>* = nullptr>
90+
__host__ __device__ constexpr pair(T const& p)
91+
: pair{std::get<0>(thrust::raw_reference_cast(p)), std::get<1>(thrust::raw_reference_cast(p))}
92+
{
93+
}
94+
95+
/**
96+
* @brief Constructs a pair from the given cuda::std::pair-like `p`.
97+
*
98+
* @tparam T Type of the pair to copy from
99+
*
100+
* @param p The input pair to copy from
101+
*/
102+
template <typename T, std::enable_if_t<detail::is_cuda_std_pair_like<T>::value>* = nullptr>
89103
__host__ __device__ constexpr pair(T const& p)
90104
: pair{cuda::std::get<0>(thrust::raw_reference_cast(p)),
91105
cuda::std::get<1>(thrust::raw_reference_cast(p))}

0 commit comments

Comments
 (0)