Skip to content

Commit

Permalink
Workaround groupby aggregate thrust::copy_if overflow (#12079)
Browse files Browse the repository at this point in the history
Workaround for limitation in `thrust::copy_if` which fails if the input-iterator spans more than int-max.
The `thrust::copy_if` hardcodes the iterator distance type to be an int
https://github.com/NVIDIA/thrust/blob/dbd144ed543b60c4ff9d456edd19869e82fe8873/thrust/system/cuda/detail/copy_if.h#L699-L708

Found existing thrust issue: https://github.com/NVIDIA/thrust/issues/1302

This calls the `copy_if` in chunks if the iterator can span greater than int-max.

Closes #12058

Authors:
  - David Wendt (https://github.com/davidwendt)

Approvers:
  - Alessandro Bellina (https://github.com/abellina)
  - Robert Maynard (https://github.com/robertmaynard)
  - Nghia Truong (https://github.com/ttnghia)

URL: #12079
  • Loading branch information
davidwendt authored Nov 10, 2022
1 parent 59bd5c3 commit 4497ed6
Showing 1 changed file with 26 additions and 11 deletions.
37 changes: 26 additions & 11 deletions cpp/src/groupby/hash/groupby.cu
Original file line number Diff line number Diff line change
Expand Up @@ -512,18 +512,33 @@ rmm::device_uvector<size_type> extract_populated_keys(map_type const& map,
{
rmm::device_uvector<size_type> populated_keys(num_keys, stream);

auto get_key = [] __device__(auto const& element) { return element.first; }; // first = key
auto get_key_it = thrust::make_transform_iterator(map.data(), get_key);
auto key_used = [unused = map.get_unused_key()] __device__(auto key) { return key != unused; };

auto end_it = thrust::copy_if(rmm::exec_policy(stream),
get_key_it,
get_key_it + map.capacity(),
populated_keys.begin(),
key_used);

populated_keys.resize(std::distance(populated_keys.begin(), end_it), stream);
auto const get_key = [] __device__(auto const& element) { return element.first; }; // first = key
auto const key_used = [unused = map.get_unused_key()] __device__(auto key) {
return key != unused;
};
auto key_itr = thrust::make_transform_iterator(map.data(), get_key);

// thrust::copy_if has a bug where it cannot iterate over int-max values
// so if map.capacity() > int-max we'll call thrust::copy_if in chunks instead
auto const copy_size =
std::min(map.capacity(), static_cast<std::size_t>(std::numeric_limits<int>::max()));
auto const key_end = key_itr + map.capacity();
auto pop_keys_itr = populated_keys.begin();

std::size_t output_size = 0;
while (key_itr != key_end) {
auto const copy_end = static_cast<std::size_t>(std::distance(key_itr, key_end)) <= copy_size
? key_end
: key_itr + copy_size;
auto const end_it =
thrust::copy_if(rmm::exec_policy(stream), key_itr, copy_end, pop_keys_itr, key_used);
auto const copied = std::distance(pop_keys_itr, end_it);
pop_keys_itr += copied;
output_size += copied;
key_itr = copy_end;
}

populated_keys.resize(output_size, stream);
return populated_keys;
}

Expand Down

0 comments on commit 4497ed6

Please sign in to comment.