Skip to content

Commit fd43949

Browse files
committed
Merge remote-tracking branch 'origin/main' into nvtext-mr-tokenize
# Conflicts: # cpp/src/text/bpe/byte_pair_encoding.cu
2 parents e7ae95b + d38b634 commit fd43949

27 files changed

Lines changed: 811 additions & 76 deletions

‎cpp/include/cudf/dictionary/dictionary_factories.hpp‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,14 @@ std::unique_ptr<column> make_dictionary_column(std::unique_ptr<column> keys_colu
8383
* @brief Construct a dictionary column by taking ownership of the provided keys
8484
* and indices columns.
8585
*
86-
* The `keys_column` must contain no nulls and is assumed to have elements
87-
* that are unique and are in a strict, total order. Meaning, `keys_column[i]`
88-
* is ordered before `keys_column[i+1]` for all `i in [0,n-1)` where `n` is the
89-
* number of keys.
86+
* The `keys_column` must contain no nulls. The keys are not required to be sorted
87+
* or unique.
9088
*
9189
* The `indices_column` can be any integer type and should contain the null-mask
9290
* to be used for the output column.
9391
* The indices values must be in the range [0,keys_column.size()).
92+
* Unsigned indices are converted to the signed type of the same width, or to the
93+
* next wider signed type if the same width cannot hold `keys_column.size() - 1`.
9494
*
9595
* @throw cudf::logic_error if keys_column contains nulls
9696
*

‎cpp/include/cudf/interop.hpp‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ using owned_columns_t = std::vector<std::unique_ptr<cudf::column>>;
146146
* @brief functor for a custom deleter to a unique_ptr of table_view
147147
*
148148
* When converting from an ArrowDeviceArray, there are cases where data can't
149-
* be zero-copy (i.e. bools or non-UINT32 dictionary indices). This custom deleter
150-
* is used to maintain ownership over the data allocated since a `cudf::table_view`
151-
* doesn't hold ownership.
149+
* be zero-copy (i.e. bools or unsigned dictionary indices that must be widened to fit
150+
* the number of keys). This custom deleter is used to maintain ownership over the data
151+
* allocated since a `cudf::table_view` doesn't hold ownership.
152152
*/
153153
template <typename ViewType>
154154
struct custom_view_deleter {

‎cpp/include/cudf_test/nanoarrow_utils.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ DEFINE_NANOARROW_STORAGE(int32_t, INT32);
290290
DEFINE_NANOARROW_STORAGE(int64_t, INT64);
291291
DEFINE_NANOARROW_STORAGE(uint8_t, UINT8);
292292
DEFINE_NANOARROW_STORAGE(uint16_t, UINT16);
293+
DEFINE_NANOARROW_STORAGE(uint32_t, UINT32);
293294
DEFINE_NANOARROW_STORAGE(uint64_t, UINT64);
294295
DEFINE_NANOARROW_STORAGE(bool, BOOL);
295296
DEFINE_NANOARROW_STORAGE(cudf::duration_D, INT32);

‎cpp/src/dictionary/dictionary_factories.cu‎

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <cudf/utilities/memory_resource.hpp>
1414
#include <cudf/utilities/type_dispatcher.hpp>
1515

16+
#include <cuda/std/limits>
1617
#include <cuda/std/type_traits>
1718
#include <cuda/stream>
1819

@@ -93,16 +94,25 @@ std::unique_ptr<column> make_dictionary_column(std::unique_ptr<column> keys_colu
9394
namespace {
9495

9596
/**
96-
* @brief This functor maps unsigned type_ids to signed counterparts
97+
* @brief This functor maps unsigned type_ids to the narrowest signed type_id
98+
* that can address all the keys
9799
*/
98100
struct make_signed_fn {
101+
size_type num_keys;
102+
99103
template <cudf::concepts::index_type T>
100-
constexpr cudf::type_id operator()()
104+
constexpr cudf::type_id operator()() const
101105
{
102-
return cudf::type_to_id<cuda::std::make_signed_t<T>>();
106+
using SignedType = cuda::std::make_signed_t<T>;
107+
if constexpr (cuda::std::is_unsigned_v<T> && sizeof(T) < sizeof(size_type)) {
108+
if (num_keys - 1 > cuda::std::numeric_limits<SignedType>::max()) {
109+
return sizeof(T) == 1 ? type_id::INT16 : type_id::INT32;
110+
}
111+
}
112+
return cudf::type_to_id<SignedType>();
103113
}
104114
template <typename T>
105-
constexpr cudf::type_id operator()()
115+
constexpr cudf::type_id operator()() const
106116
{
107117
return cudf::type_to_id<T>();
108118
}
@@ -122,21 +132,23 @@ std::unique_ptr<column> make_dictionary_column(std::unique_ptr<column> keys,
122132
auto const null_count = indices->null_count(); // before calling release()
123133
auto contents = indices->release();
124134

125-
auto const new_type_id = cudf::type_dispatcher(indices_type, make_signed_fn{});
135+
auto const new_type =
136+
data_type{cudf::type_dispatcher(indices_type, make_signed_fn{keys->size()})};
126137

127138
// create the dictionary indices: convert to signed and remove nulls if necessary
128139
auto indices_column = [&] {
129-
// If the types match, then just commandeer the column's data buffer.
130-
if (new_type_id == indices_type.id()) {
131-
return std::make_unique<column>(indices_type,
140+
// If the widths match, then just commandeer the column's data buffer.
141+
// Every valid index is less than keys->size() so its bits are the same in both types.
142+
if (new_type == indices_type || cudf::size_of(new_type) == cudf::size_of(indices_type)) {
143+
return std::make_unique<column>(new_type,
132144
indices_size,
133145
std::move(*(contents.data.release())),
134146
cudf::create_null_mask(0, cudf::mask_state::UNALLOCATED),
135147
0);
136148
}
137-
// If the new type does not match, then convert the data.
149+
// If the widths do not match, then convert the data.
138150
cudf::column_view cast_view{indices_type, indices_size, contents.data->data(), nullptr, 0};
139-
return cudf::detail::cast(cast_view, data_type{new_type_id}, stream, mr);
151+
return cudf::detail::cast(cast_view, new_type, stream, mr);
140152
}();
141153

142154
return make_dictionary_column(std::move(keys),

‎cpp/src/interop/arrow_utilities.cpp‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,30 @@ ArrowType id_to_arrow_storage_type(cudf::type_id id)
163163
}
164164
}
165165

166+
dictionary_indices_types get_dictionary_indices_types(ArrowType storage_type, int64_t num_keys)
167+
{
168+
auto const same = [](type_id id) {
169+
return dictionary_indices_types{data_type{id}, data_type{id}};
170+
};
171+
auto const max_index = num_keys - 1;
172+
switch (storage_type) {
173+
case NANOARROW_TYPE_INT8: return same(type_id::INT8);
174+
case NANOARROW_TYPE_INT16: return same(type_id::INT16);
175+
case NANOARROW_TYPE_INT32: return same(type_id::INT32);
176+
case NANOARROW_TYPE_INT64: return same(type_id::INT64);
177+
case NANOARROW_TYPE_UINT8:
178+
return max_index <= std::numeric_limits<int8_t>::max()
179+
? same(type_id::INT8)
180+
: dictionary_indices_types{data_type{type_id::UINT8}, data_type{type_id::INT16}};
181+
case NANOARROW_TYPE_UINT16:
182+
return max_index <= std::numeric_limits<int16_t>::max()
183+
? same(type_id::INT16)
184+
: dictionary_indices_types{data_type{type_id::UINT16}, data_type{type_id::INT32}};
185+
case NANOARROW_TYPE_UINT32: return same(type_id::INT32);
186+
default: CUDF_FAIL("Unsupported type_id for dictionary indices", cudf::data_type_error);
187+
}
188+
}
189+
166190
int initialize_array(ArrowArray* arr, ArrowType storage_type, cudf::column_view column)
167191
{
168192
NANOARROW_RETURN_NOT_OK(ArrowArrayInitFromType(arr, storage_type));

‎cpp/src/interop/arrow_utilities.hpp‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ ArrowType id_to_arrow_type(cudf::type_id id);
9696
*/
9797
ArrowType id_to_arrow_storage_type(cudf::type_id id);
9898

99+
/**
100+
* @brief cudf types used to import the indices of an Arrow dictionary array
101+
*/
102+
struct dictionary_indices_types {
103+
data_type storage; ///< Type used to read the Arrow indices buffer
104+
data_type output; ///< Signed type of the resulting cudf dictionary indices
105+
};
106+
107+
/**
108+
* @brief Return the cudf types used to import Arrow dictionary indices
109+
*
110+
* Signed index types are returned unchanged. Unsigned index types are mapped to the
111+
* narrowest signed type that can represent every valid index `[0, num_keys - 1]`:
112+
* the same-width signed type when it fits, otherwise the next wider signed type.
113+
*
114+
* @throw cudf::data_type_error if `storage_type` is not an 8, 16, or 32-bit unsigned or
115+
* an 8, 16, 32, or 64-bit signed integer type
116+
*
117+
* @param storage_type Arrow storage type of the dictionary indices
118+
* @param num_keys Number of keys in the dictionary, at most `size_type` max
119+
* @return Types to read the Arrow buffer with and to output
120+
*/
121+
dictionary_indices_types get_dictionary_indices_types(ArrowType storage_type, int64_t num_keys);
122+
99123
/**
100124
* @brief Helper to initialize ArrowArray struct
101125
*

‎cpp/src/interop/from_arrow_device.cu‎

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -233,26 +233,24 @@ dispatch_tuple_t dispatch_from_arrow_device::operator()<cudf::dictionary32>(
233233
auto [keys_view, owned_cols] =
234234
get_column(&keys_schema_view, input->dictionary, keys_type, true, stream, mr);
235235

236-
auto const dict_indices_type = [&schema]() -> data_type {
237-
// cudf dictionary requires a signed type for the indices
238-
switch (schema->storage_type) {
239-
case NANOARROW_TYPE_INT8: return data_type(type_id::INT8);
240-
case NANOARROW_TYPE_INT16: return data_type(type_id::INT16);
241-
case NANOARROW_TYPE_INT32: return data_type(type_id::INT32);
242-
case NANOARROW_TYPE_INT64: return data_type(type_id::INT64);
243-
default: CUDF_FAIL("Unsupported type_id for dictionary indices", cudf::data_type_error);
244-
}
245-
}();
236+
auto const indices_types =
237+
get_dictionary_indices_types(schema->storage_type, input->dictionary->length);
246238

247239
size_type const num_rows = input->length;
248240
size_type const offset = input->offset;
249241
size_type const null_count = input->null_count;
250-
column_view indices_view = column_view{dict_indices_type,
242+
column_view indices_view = column_view{indices_types.storage,
251243
offset + num_rows,
252244
input->buffers[fixed_width_data_buffer_idx],
253245
nullptr,
254246
0,
255247
0};
248+
// Widen the full [0, offset + num_rows) range since the parent offset applies to the indices
249+
if (indices_types.storage != indices_types.output) {
250+
auto widened = cudf::detail::cast(indices_view, indices_types.output, stream, mr);
251+
indices_view = widened->view();
252+
owned_cols.emplace_back(std::move(widened));
253+
}
256254

257255
return std::make_tuple<column_view, owned_columns_t>(
258256
{type,

‎cpp/src/interop/from_arrow_host.cu‎

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -257,18 +257,9 @@ std::unique_ptr<column> dispatch_copy_from_arrow_host::operator()<cudf::dictiona
257257
auto keys_column =
258258
get_column_copy(&keys_schema_view, input->dictionary, keys_type, true, stream, mr);
259259

260-
auto const dict_indices_type = [&schema]() -> data_type {
261-
// cudf dictionary requires a signed type for the indices
262-
switch (schema->storage_type) {
263-
case NANOARROW_TYPE_INT8: return data_type(type_id::INT8);
264-
case NANOARROW_TYPE_INT16: return data_type(type_id::INT16);
265-
case NANOARROW_TYPE_INT32: return data_type(type_id::INT32);
266-
case NANOARROW_TYPE_INT64: return data_type(type_id::INT64);
267-
default: CUDF_FAIL("Unsupported type_id for dictionary indices", cudf::data_type_error);
268-
}
269-
}();
270-
271-
auto indices_column = get_column_copy(schema, input, dict_indices_type, skip_mask, stream, mr);
260+
auto const indices_type =
261+
get_dictionary_indices_types(schema->storage_type, input->dictionary->length).storage;
262+
auto indices_column = get_column_copy(schema, input, indices_type, skip_mask, stream, mr);
272263

273264
return make_dictionary_column(std::move(keys_column), std::move(indices_column), stream, mr);
274265
}

‎cpp/src/io/avro/reader_impl.cu‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include <cudf/detail/null_mask.hpp>
1414
#include <cudf/detail/structs/utilities.hpp>
15+
#include <cudf/detail/utilities/buffer_factories.hpp>
1516
#include <cudf/detail/utilities/cuda_memcpy.hpp>
1617
#include <cudf/detail/utilities/vector_factories.hpp>
1718
#include <cudf/io/datasource.hpp>
@@ -22,7 +23,6 @@
2223
#include <cudf/utilities/span.hpp>
2324
#include <cudf/utilities/traits.hpp>
2425

25-
#include <rmm/device_uvector.hpp>
2626
#include <rmm/exec_policy.hpp>
2727

2828
#include <cuda/buffer>
@@ -297,7 +297,8 @@ cuda::device_buffer<std::uint8_t> decompress_data(
297297

298298
cuda::device_buffer<std::uint8_t> decompressed_data(
299299
stream, cudf::get_current_device_resource_ref(), uncompressed_data_size, cuda::no_init);
300-
rmm::device_uvector<device_span<uint8_t>> decompressed_blocks(num_blocks, stream);
300+
cuda::device_buffer<device_span<uint8_t>> decompressed_blocks(
301+
stream, cudf::get_current_device_resource_ref(), num_blocks, cuda::no_init);
301302
thrust::tabulate(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()),
302303
decompressed_blocks.begin(),
303304
decompressed_blocks.end(),
@@ -307,7 +308,8 @@ cuda::device_buffer<std::uint8_t> decompress_data(
307308
return device_span<uint8_t>{data + off[i], size[i]};
308309
});
309310

310-
rmm::device_uvector<codec_exec_result> decomp_results(num_blocks, stream);
311+
cuda::device_buffer<codec_exec_result> decomp_results(
312+
stream, cudf::get_current_device_resource_ref(), num_blocks, cuda::no_init);
311313
thrust::fill(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()),
312314
decomp_results.begin(),
313315
decomp_results.end(),
@@ -425,7 +427,7 @@ std::vector<column_buffer> decode_data(metadata& meta,
425427
}
426428
}
427429

428-
auto block_list = cudf::detail::make_device_uvector_async(
430+
auto block_list = cudf::detail::make_device_buffer_async(
429431
meta.block_list, stream, cudf::get_current_device_resource_ref());
430432

431433
schema_desc.host_to_device_async(stream);
@@ -539,8 +541,10 @@ table_with_metadata read_avro(std::unique_ptr<cudf::io::datasource>&& source,
539541
}
540542
}
541543

542-
auto d_global_dict = rmm::device_uvector<string_index_pair>(0, stream);
543-
auto d_global_dict_data = rmm::device_uvector<char>(0, stream);
544+
cuda::device_buffer<string_index_pair> d_global_dict(
545+
stream, cudf::get_current_device_resource_ref(), 0, cuda::no_init);
546+
cuda::device_buffer<char> d_global_dict_data(
547+
stream, cudf::get_current_device_resource_ref(), 0, cuda::no_init);
544548

545549
if (total_dictionary_entries > 0) {
546550
auto h_global_dict =
@@ -566,9 +570,9 @@ table_with_metadata read_avro(std::unique_ptr<cudf::io::datasource>&& source,
566570
}
567571
}
568572

569-
d_global_dict = cudf::detail::make_device_uvector_async(
573+
d_global_dict = cudf::detail::make_device_buffer_async(
570574
h_global_dict, stream, cudf::get_current_device_resource_ref());
571-
d_global_dict_data = cudf::detail::make_device_uvector_async(
575+
d_global_dict_data = cudf::detail::make_device_buffer_async(
572576
h_global_dict_data, stream, cudf::get_current_device_resource_ref());
573577

574578
stream.sync();

‎cpp/src/io/fst/logical_stack.cuh‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <cudf_test/print_utilities.cuh>
88

9+
#include <cudf/detail/utilities/cuda.hpp>
10+
#include <cudf/detail/utilities/cuda_memcpy.hpp>
911
#include <cudf/types.hpp>
1012
#include <cudf/utilities/default_stream.hpp>
1113
#include <cudf/utilities/error.hpp>
@@ -455,9 +457,12 @@ void sparse_stack_op_to_top_of_stack(StackSymbolItT d_symbols,
455457
// temp_storage_bytes
456458
total_temp_storage_bytes = temp_storage.size();
457459

458-
rmm::device_uvector<SymbolPositionT> d_symbol_position_alt{num_symbols_in, stream};
459-
rmm::device_uvector<StackOpT> d_kv_ops_current{num_symbols_in, stream};
460-
rmm::device_uvector<StackOpT> d_kv_ops_alt{num_symbols_in, stream};
460+
cuda::device_buffer<SymbolPositionT> d_symbol_position_alt(
461+
stream, cudf::get_current_device_resource_ref(), num_symbols_in, cuda::no_init);
462+
cuda::device_buffer<StackOpT> d_kv_ops_current{
463+
stream, cudf::get_current_device_resource_ref(), num_symbols_in, cuda::no_init};
464+
cuda::device_buffer<StackOpT> d_kv_ops_alt(
465+
stream, cudf::get_current_device_resource_ref(), num_symbols_in, cuda::no_init);
461466

462467
//------------------------------------------------------------------------------
463468
// ALGORITHM
@@ -476,7 +481,8 @@ void sparse_stack_op_to_top_of_stack(StackSymbolItT d_symbols,
476481
d_symbols,
477482
detail::NewlineToResetStackSegmentOp<StackSymbolToStackOpTypeT>{symbol_to_stack_op});
478483

479-
rmm::device_uvector<StackSegmentT> key_segments{num_symbols_in, stream};
484+
cuda::device_buffer<StackSegmentT> key_segments(
485+
stream, cudf::get_current_device_resource_ref(), num_symbols_in, cuda::no_init);
480486
CUDF_CUDA_TRY(cub::DeviceScan::InclusiveSum(
481487
temp_storage.data(),
482488
total_temp_storage_bytes,
@@ -508,7 +514,10 @@ void sparse_stack_op_to_top_of_stack(StackSymbolItT d_symbols,
508514

509515
// Check if the last element of d_kv_operations is 0. If not, then we have a problem.
510516
if (num_symbols_in && !supports_reset_op) {
511-
StackOpT last_symbol = d_kv_ops_current.element(num_symbols_in - 1, stream);
517+
StackOpT last_symbol;
518+
CUDF_CUDA_TRY(cudf::detail::memcpy_async(
519+
&last_symbol, d_kv_ops_current.data() + num_symbols_in - 1, sizeof(last_symbol), stream));
520+
cudf::detail::sync_stream(stream);
512521
CUDF_EXPECTS(last_symbol.stack_level == 0, "The logical stack is not empty!");
513522
}
514523

0 commit comments

Comments
 (0)