diff --git a/cpp/include/cudf/detail/row_operator/equality.cuh b/cpp/include/cudf/detail/row_operator/equality.cuh index f38acc8b7d78..95061ea7274c 100644 --- a/cpp/include/cudf/detail/row_operator/equality.cuh +++ b/cpp/include/cudf/detail/row_operator/equality.cuh @@ -407,9 +407,10 @@ class self_comparator { * @param t The table to compare * @param stream The stream to construct this object on. Not the stream that will be used for * comparisons using this object. + * @param mr Memory resources used for temporary device allocations */ - self_comparator(table_view const& t, rmm::cuda_stream_view stream) - : d_t(preprocessed_table::create(t, stream)) + self_comparator(table_view const& t, rmm::cuda_stream_view stream, cudf::memory_resources mr) + : d_t(preprocessed_table::create(t, stream, mr)) { } @@ -515,10 +516,12 @@ class two_table_comparator { * @param right The right table to compare. * @param stream The stream to construct this object on. Not the stream that will be used for * comparisons using this object. + * @param mr Memory resources used for temporary device allocations */ two_table_comparator(table_view const& left, table_view const& right, - rmm::cuda_stream_view stream); + rmm::cuda_stream_view stream, + cudf::memory_resources mr); /** * @brief Construct an owning object for performing equality comparisons between two rows from two diff --git a/cpp/include/cudf/detail/row_operator/hashing.cuh b/cpp/include/cudf/detail/row_operator/hashing.cuh index e71fc5213483..db23e797f004 100644 --- a/cpp/include/cudf/detail/row_operator/hashing.cuh +++ b/cpp/include/cudf/detail/row_operator/hashing.cuh @@ -240,9 +240,10 @@ class row_hasher { * @param t The table containing rows to hash * @param stream The stream to construct this object on. Not the stream that will be used for * comparisons using this object. + * @param mr Memory resources used for temporary device allocations */ - row_hasher(table_view const& t, rmm::cuda_stream_view stream) - : d_t(preprocessed_table::create(t, stream)) + row_hasher(table_view const& t, rmm::cuda_stream_view stream, cudf::memory_resources mr) + : d_t(preprocessed_table::create(t, stream, mr)) { } diff --git a/cpp/include/cudf/detail/row_operator/preprocessed_table.cuh b/cpp/include/cudf/detail/row_operator/preprocessed_table.cuh index 233294201ccd..bffebd13c3b9 100644 --- a/cpp/include/cudf/detail/row_operator/preprocessed_table.cuh +++ b/cpp/include/cudf/detail/row_operator/preprocessed_table.cuh @@ -6,6 +6,7 @@ #pragma once #include +#include #include #include @@ -47,10 +48,12 @@ struct preprocessed_table { * * @param table The table to preprocess * @param stream The cuda stream to use while preprocessing. + * @param mr Memory resources used for temporary device allocations * @return A preprocessed table as shared pointer */ static std::shared_ptr create(table_view const& table, - rmm::cuda_stream_view stream); + rmm::cuda_stream_view stream, + cudf::memory_resources mr); /** * @brief Implicit conversion operator to a `table_device_view` of the preprocessed table. diff --git a/cpp/include/cudf_test/base_fixture.hpp b/cpp/include/cudf_test/base_fixture.hpp index 583abe9931d8..7933f2ba08f1 100644 --- a/cpp/include/cudf_test/base_fixture.hpp +++ b/cpp/include/cudf_test/base_fixture.hpp @@ -1,21 +1,26 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include +#include #include +#include #include #include #include +#include #include #include +#include + namespace CUDF_EXPORT cudf { namespace test { @@ -39,6 +44,46 @@ class BaseFixture : public ::testing::Test { rmm::device_async_resource_ref mr() { return _mr; } }; +/** + * @brief Base fixture that instruments tests with a memory-resource harness. + * + * Each test instantiates a fresh harness. The failing current-device-resource scope is installed + * after `_harness` so accidental fallback to the default MR fails the test. Tests should construct + * results with `resources()`. `TearDown` asserts that no output or temporary allocations remain + * live; the prior current resource is restored when the optional scope is reset or destroyed. + */ +struct BaseFixtureWithHarness : public BaseFixture { + /** + * @brief Assert that the harness has no live output or temporary allocations. + */ + void TearDown() override { _harness.expect_no_live_allocations(stream()); } + + /** + * @brief Return the default stream used by tests inheriting from this fixture. + * @return CUDA stream view + */ + [[nodiscard]] rmm::cuda_stream_view stream() const { return cudf::test::get_default_stream(); } + + /** + * @brief Return the harness output and temporary memory resources. + * @return Explicit output and temporary resources that do not consult the current resource + */ + cudf::memory_resources resources() { return _harness.resources(); } + + /** + * @brief Clear the failing current-device-resource scope for the remainder of the test. + * + * After this call, APIs may allocate from the restored current device resource without failing + * the test. Prefer removing the need for this once those APIs accept explicit resources. + */ + void disable_current_device_resource_use() { _fail_on_current.reset(); } + + protected: + memory_resource_test_harness _harness{mr()}; + std::optional _fail_on_current{ + _harness.fail_on_current_device_resource_use()}; +}; + /** * @brief Base test fixture that takes a parameter. * diff --git a/cpp/include/cudf_test/column_wrapper.hpp b/cpp/include/cudf_test/column_wrapper.hpp index f0a7a64e3d29..a2e3e608070a 100644 --- a/cpp/include/cudf_test/column_wrapper.hpp +++ b/cpp/include/cudf_test/column_wrapper.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -147,21 +148,25 @@ struct fixed_width_type_converter { * @tparam InputIterator Iterator type for `begin` and `end` * @param begin Beginning of the sequence of elements * @param end End of the sequence of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned buffer * @return rmm::device_buffer Buffer containing all elements in the range `[begin,end)` */ template ()>* = nullptr> -rmm::device_buffer make_elements(InputIterator begin, InputIterator end) +rmm::device_buffer make_elements(InputIterator begin, + InputIterator end, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { static_assert(cudf::is_fixed_width(), "Unexpected non-fixed width type."); auto transformer = fixed_width_type_converter{}; auto transform_begin = thrust::make_transform_iterator(begin, transformer); auto const size = cudf::distance(begin, end); auto const elements = thrust::host_vector(transform_begin, transform_begin + size); - return rmm::device_buffer{ - elements.data(), size * sizeof(ElementTo), cudf::test::get_default_stream()}; + return rmm::device_buffer{elements.data(), size * sizeof(ElementTo), stream, mr.get_output_mr()}; } // The two signatures below are identical to the above overload apart from @@ -176,6 +181,8 @@ rmm::device_buffer make_elements(InputIterator begin, InputIterator end) * @tparam InputIterator Iterator type for `begin` and `end` * @param begin Beginning of the sequence of elements * @param end End of the sequence of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned buffer * @return rmm::device_buffer Buffer containing all elements in the range `[begin,end)` */ template () and cudf::is_fixed_point()>* = nullptr> -rmm::device_buffer make_elements(InputIterator begin, InputIterator end) +rmm::device_buffer make_elements(InputIterator begin, + InputIterator end, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { using RepType = typename ElementTo::rep; auto transformer = fixed_width_type_converter{}; auto transform_begin = thrust::make_transform_iterator(begin, transformer); auto const size = cudf::distance(begin, end); auto const elements = thrust::host_vector(transform_begin, transform_begin + size); - return rmm::device_buffer{ - elements.data(), size * sizeof(RepType), cudf::test::get_default_stream()}; + return rmm::device_buffer{elements.data(), size * sizeof(RepType), stream, mr.get_output_mr()}; } /** @@ -202,6 +211,8 @@ rmm::device_buffer make_elements(InputIterator begin, InputIterator end) * @tparam InputIterator Iterator type for `begin` and `end` * @param begin Beginning of the sequence of elements * @param end End of the sequence of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned buffer * @return rmm::device_buffer Buffer containing all elements in the range `[begin,end)` */ template () and cudf::is_fixed_point()>* = nullptr> -rmm::device_buffer make_elements(InputIterator begin, InputIterator end) +rmm::device_buffer make_elements(InputIterator begin, + InputIterator end, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { using namespace numeric; using RepType = typename ElementTo::rep; @@ -221,8 +235,7 @@ rmm::device_buffer make_elements(InputIterator begin, InputIterator end) auto transformer_begin = thrust::make_transform_iterator(begin, to_rep); auto const size = cudf::distance(begin, end); auto const elements = thrust::host_vector(transformer_begin, transformer_begin + size); - return rmm::device_buffer{ - elements.data(), size * sizeof(RepType), cudf::test::get_default_stream()}; + return rmm::device_buffer{elements.data(), size * sizeof(RepType), stream, mr.get_output_mr()}; } //! @endcond @@ -269,17 +282,23 @@ std::pair, cudf::size_type> make_null_mask_vector(Vali * @tparam ValidityIterator * @param begin The beginning of the validity indicator sequence * @param end The end of the validity indicator sequence + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned buffer * @return rmm::device_buffer Contains a bitmask where bits are set for every * element in `[begin,end)` that evaluated to `true`. */ template -std::pair make_null_mask(ValidityIterator begin, - ValidityIterator end) +std::pair make_null_mask( + ValidityIterator begin, + ValidityIterator end, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { auto [null_mask, null_count] = make_null_mask_vector(begin, end); auto d_mask = rmm::device_buffer{null_mask.data(), cudf::bitmask_allocation_size_bytes(cudf::distance(begin, end)), - cudf::test::get_default_stream()}; + stream, + mr.get_output_mr()}; return {std::move(d_mask), null_count}; } @@ -328,17 +347,22 @@ template class fixed_width_column_wrapper : public detail::column_wrapper { public: /** - * @brief Default constructor initializes an empty column with proper dtype + * @brief Initializes an empty column with proper dtype + * + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - fixed_width_column_wrapper() : column_wrapper{} + fixed_width_column_wrapper(rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { std::vector empty; - wrapped.reset( - new cudf::column{cudf::data_type{cudf::type_to_id()}, - 0, - detail::make_elements(empty.begin(), empty.end()), - rmm::device_buffer{}, - 0}); + wrapped.reset(new cudf::column{ + cudf::data_type{cudf::type_to_id()}, + 0, + detail::make_elements(empty.begin(), empty.end(), stream, mr), + rmm::device_buffer{}, + 0}); } /** @@ -358,16 +382,23 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - fixed_width_column_wrapper(InputIterator begin, InputIterator end) : column_wrapper{} + fixed_width_column_wrapper(InputIterator begin, + InputIterator end, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { auto const size = cudf::distance(begin, end); - wrapped.reset(new cudf::column{cudf::data_type{cudf::type_to_id()}, - size, - detail::make_elements(begin, end), - rmm::device_buffer{}, - 0}); + wrapped.reset( + new cudf::column{cudf::data_type{cudf::type_to_id()}, + size, + detail::make_elements(begin, end, stream, mr), + rmm::device_buffer{}, + 0}); } /** @@ -392,18 +423,28 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - fixed_width_column_wrapper(InputIterator begin, InputIterator end, ValidityIterator v) + template < + typename InputIterator, + typename ValidityIterator, + std::enable_if_t>* = nullptr> + fixed_width_column_wrapper(InputIterator begin, + InputIterator end, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { auto const size = cudf::distance(begin, end); - auto [null_mask, null_count] = detail::make_null_mask(v, v + size); - wrapped.reset(new cudf::column{cudf::data_type{cudf::type_to_id()}, - size, - detail::make_elements(begin, end), - std::move(null_mask), - null_count}); + auto [null_mask, null_count] = detail::make_null_mask(v, v + size, stream, mr); + wrapped.reset( + new cudf::column{cudf::data_type{cudf::type_to_id()}, + size, + detail::make_elements(begin, end, stream, mr), + std::move(null_mask), + null_count}); } /** @@ -417,10 +458,14 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * @endcode * * @param elements The list of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - fixed_width_column_wrapper(std::initializer_list elements) - : fixed_width_column_wrapper(std::cbegin(elements), std::cend(elements)) + fixed_width_column_wrapper(std::initializer_list elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_width_column_wrapper(std::cbegin(elements), std::cend(elements), stream, mr) { } @@ -440,11 +485,16 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * * @param elements The list of elements * @param validity The list of validity indicator booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template fixed_width_column_wrapper(std::initializer_list elements, - std::initializer_list validity) - : fixed_width_column_wrapper(std::cbegin(elements), std::cend(elements), std::cbegin(validity)) + std::initializer_list validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_width_column_wrapper( + std::cbegin(elements), std::cend(elements), std::cbegin(validity), stream, mr) { } @@ -464,10 +514,18 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * convertible to `bool` * @param element_list The list of elements * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - fixed_width_column_wrapper(std::initializer_list element_list, ValidityIterator v) - : fixed_width_column_wrapper(std::cbegin(element_list), std::cend(element_list), v) + template < + typename ValidityIterator, + typename ElementFrom, + std::enable_if_t>* = nullptr> + fixed_width_column_wrapper(std::initializer_list element_list, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_width_column_wrapper(std::cbegin(element_list), std::cend(element_list), v, stream, mr) { } @@ -488,12 +546,16 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements * @param validity The list of validity indicator booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template fixed_width_column_wrapper(InputIterator begin, InputIterator end, - std::initializer_list const& validity) - : fixed_width_column_wrapper(begin, end, std::cbegin(validity)) + std::initializer_list const& validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_width_column_wrapper(begin, end, std::cbegin(validity), stream, mr) { } @@ -513,16 +575,21 @@ class fixed_width_column_wrapper : public detail::column_wrapper { * @endcode * * @param elements The list of pairs of element and validity booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - fixed_width_column_wrapper(std::initializer_list> elements) + fixed_width_column_wrapper(std::initializer_list> elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { auto begin = thrust::make_transform_iterator(elements.begin(), [](auto const& e) { return e.first; }); auto end = begin + elements.size(); auto v = thrust::make_transform_iterator(elements.begin(), [](auto const& e) { return e.second; }); - wrapped = fixed_width_column_wrapper(begin, end, v).release(); + wrapped = + fixed_width_column_wrapper(begin, end, v, stream, mr).release(); } }; @@ -549,11 +616,15 @@ class fixed_point_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements * @param scale The scale of the elements in the column + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template fixed_point_column_wrapper(FixedPointRepIterator begin, FixedPointRepIterator end, - numeric::scale_type scale) + numeric::scale_type scale, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { CUDF_EXPECTS(numeric::is_supported_representation_type(), "not valid representation type"); @@ -566,7 +637,7 @@ class fixed_point_column_wrapper : public detail::column_wrapper { wrapped.reset(new cudf::column{ data_type, size, - rmm::device_buffer{elements.data(), size * sizeof(Rep), cudf::test::get_default_stream()}, + rmm::device_buffer{elements.data(), size * sizeof(Rep), stream, mr.get_output_mr()}, rmm::device_buffer{}, 0}); } @@ -582,9 +653,14 @@ class fixed_point_column_wrapper : public detail::column_wrapper { * * @param values The initializer list of already shifted values * @param scale The scale of the elements in the column + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - fixed_point_column_wrapper(std::initializer_list values, numeric::scale_type scale) - : fixed_point_column_wrapper(std::cbegin(values), std::cend(values), scale) + fixed_point_column_wrapper(std::initializer_list values, + numeric::scale_type scale, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_point_column_wrapper(std::cbegin(values), std::cend(values), scale, stream, mr) { } @@ -614,12 +690,16 @@ class fixed_point_column_wrapper : public detail::column_wrapper { * @param end The end of the sequence of elements * @param v The beginning of the sequence of validity indicators * @param scale The scale of the elements in the column + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template fixed_point_column_wrapper(FixedPointRepIterator begin, FixedPointRepIterator end, ValidityIterator v, - numeric::scale_type scale) + numeric::scale_type scale, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { CUDF_EXPECTS(numeric::is_supported_representation_type(), "not valid representation type"); @@ -628,11 +708,11 @@ class fixed_point_column_wrapper : public detail::column_wrapper { auto const elements = thrust::host_vector(begin, end); auto const id = type_to_id>(); auto const data_type = cudf::data_type{id, static_cast(scale)}; - auto [null_mask, null_count] = detail::make_null_mask(v, v + size); + auto [null_mask, null_count] = detail::make_null_mask(v, v + size, stream, mr); wrapped.reset(new cudf::column{ data_type, size, - rmm::device_buffer{elements.data(), size * sizeof(Rep), cudf::test::get_default_stream()}, + rmm::device_buffer{elements.data(), size * sizeof(Rep), stream, mr.get_output_mr()}, std::move(null_mask), null_count}); } @@ -653,12 +733,16 @@ class fixed_point_column_wrapper : public detail::column_wrapper { * @param elements The initializer list of elements * @param validity The initializer list of validity indicator booleans * @param scale The scale of the elements in the column + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ fixed_point_column_wrapper(std::initializer_list elements, std::initializer_list validity, - numeric::scale_type scale) + numeric::scale_type scale, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : fixed_point_column_wrapper( - std::cbegin(elements), std::cend(elements), std::cbegin(validity), scale) + std::cbegin(elements), std::cend(elements), std::cbegin(validity), scale, stream, mr) { } @@ -679,12 +763,17 @@ class fixed_point_column_wrapper : public detail::column_wrapper { * @param element_list The initializer list of elements * @param v The beginning of the sequence of validity indicators * @param scale The scale of the elements in the column + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template fixed_point_column_wrapper(std::initializer_list element_list, ValidityIterator v, - numeric::scale_type scale) - : fixed_point_column_wrapper(std::cbegin(element_list), std::cend(element_list), v, scale) + numeric::scale_type scale, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_point_column_wrapper( + std::cbegin(element_list), std::cend(element_list), v, scale, stream, mr) { } @@ -707,13 +796,17 @@ class fixed_point_column_wrapper : public detail::column_wrapper { * @param end The end of the sequence of elements * @param validity The initializer list of validity indicator booleans * @param scale The scale of the elements in the column + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template fixed_point_column_wrapper(FixedPointRepIterator begin, FixedPointRepIterator end, std::initializer_list const& validity, - numeric::scale_type scale) - : fixed_point_column_wrapper(begin, end, std::cbegin(validity), scale) + numeric::scale_type scale, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : fixed_point_column_wrapper(begin, end, std::cbegin(validity), scale, stream, mr) { } }; @@ -725,8 +818,16 @@ class strings_column_wrapper : public detail::column_wrapper { public: /** * @brief Default constructor initializes an empty column of strings + * + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - strings_column_wrapper() : strings_column_wrapper(std::initializer_list{}) {} + // Non-explicit so `{}` can copy-initialize empty string columns (e.g. nested in structs). + strings_column_wrapper(rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : strings_column_wrapper(std::initializer_list{}, stream, mr) + { + } /** * @brief Construct a non-nullable column of strings from the range @@ -747,9 +848,15 @@ class strings_column_wrapper : public detail::column_wrapper { * dereferencing a `StringsIterator`. * @param begin The beginning of the sequence * @param end The end of the sequence + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - strings_column_wrapper(StringsIterator begin, StringsIterator end) : column_wrapper{} + strings_column_wrapper(StringsIterator begin, + StringsIterator end, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { size_type num_strings = std::distance(begin, end); if (num_strings == 0) { @@ -758,11 +865,9 @@ class strings_column_wrapper : public detail::column_wrapper { } auto all_valid = cuda::make_constant_iterator(true); auto [chars, offsets] = detail::make_chars_and_offsets(begin, end, all_valid); - auto d_chars = cudf::detail::make_device_uvector_async( - chars, cudf::test::get_default_stream(), cudf::get_current_device_resource_ref()); + auto d_chars = cudf::detail::make_device_uvector_async(chars, stream, mr.get_output_mr()); auto d_offsets = std::make_unique( - cudf::detail::make_device_uvector( - offsets, cudf::test::get_default_stream(), cudf::get_current_device_resource_ref()), + cudf::detail::make_device_uvector(offsets, stream, mr.get_output_mr()), rmm::device_buffer{}, 0); wrapped = @@ -796,9 +901,18 @@ class strings_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence * @param end The end of the sequence * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - strings_column_wrapper(StringsIterator begin, StringsIterator end, ValidityIterator v) + template < + typename StringsIterator, + typename ValidityIterator, + std::enable_if_t>* = nullptr> + strings_column_wrapper(StringsIterator begin, + StringsIterator end, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { size_type num_strings = std::distance(begin, end); @@ -808,16 +922,13 @@ class strings_column_wrapper : public detail::column_wrapper { } auto [chars, offsets] = detail::make_chars_and_offsets(begin, end, v); auto [null_mask, null_count] = detail::make_null_mask_vector(v, v + num_strings); - auto d_chars = cudf::detail::make_device_uvector_async( - chars, cudf::test::get_default_stream(), cudf::get_current_device_resource_ref()); + auto d_chars = cudf::detail::make_device_uvector_async(chars, stream, mr.get_output_mr()); auto d_offsets = std::make_unique( - cudf::detail::make_device_uvector_async( - offsets, cudf::test::get_default_stream(), cudf::get_current_device_resource_ref()), + cudf::detail::make_device_uvector_async(offsets, stream, mr.get_output_mr()), rmm::device_buffer{}, 0); - auto d_bitmask = cudf::detail::make_device_uvector( - null_mask, cudf::test::get_default_stream(), cudf::get_current_device_resource_ref()); - wrapped = cudf::make_strings_column( + auto d_bitmask = cudf::detail::make_device_uvector(null_mask, stream, mr.get_output_mr()); + wrapped = cudf::make_strings_column( num_strings, std::move(d_offsets), d_chars.release(), null_count, d_bitmask.release()); } @@ -832,9 +943,13 @@ class strings_column_wrapper : public detail::column_wrapper { * @endcode * * @param strings The list of strings + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - strings_column_wrapper(std::initializer_list strings) - : strings_column_wrapper(std::cbegin(strings), std::cend(strings)) + strings_column_wrapper(std::initializer_list strings, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : strings_column_wrapper(std::cbegin(strings), std::cend(strings), stream, mr) { } @@ -855,10 +970,17 @@ class strings_column_wrapper : public detail::column_wrapper { * convertible to `bool` * @param strings The list of strings * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - strings_column_wrapper(std::initializer_list strings, ValidityIterator v) - : strings_column_wrapper(std::cbegin(strings), std::cend(strings), v) + template < + typename ValidityIterator, + std::enable_if_t>* = nullptr> + strings_column_wrapper(std::initializer_list strings, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : strings_column_wrapper(std::cbegin(strings), std::cend(strings), v, stream, mr) { } @@ -876,10 +998,15 @@ class strings_column_wrapper : public detail::column_wrapper { * * @param strings The list of strings * @param validity The list of validity indicator booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ strings_column_wrapper(std::initializer_list strings, - std::initializer_list validity) - : strings_column_wrapper(std::cbegin(strings), std::cend(strings), std::cbegin(validity)) + std::initializer_list validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : strings_column_wrapper( + std::cbegin(strings), std::cend(strings), std::cbegin(validity), stream, mr) { } @@ -902,15 +1029,19 @@ class strings_column_wrapper : public detail::column_wrapper { * @endcode * * @param strings The list of pairs of strings and validity booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - strings_column_wrapper(std::initializer_list> strings) + strings_column_wrapper(std::initializer_list> strings, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { auto begin = thrust::make_transform_iterator(strings.begin(), [](auto const& s) { return s.first; }); auto end = begin + strings.size(); auto v = thrust::make_transform_iterator(strings.begin(), [](auto const& s) { return s.second; }); - wrapped = strings_column_wrapper(begin, end, v).release(); + wrapped = strings_column_wrapper(begin, end, v, stream, mr).release(); } }; @@ -932,9 +1063,17 @@ class dictionary_column_wrapper : public detail::column_wrapper { /** * @brief Default constructor initializes an empty column with dictionary type. + * + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - dictionary_column_wrapper() : column_wrapper{} + // Non-explicit so `{}` can copy-initialize empty dictionary columns. + dictionary_column_wrapper(rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { + static_cast(stream); + static_cast(mr); wrapped = cudf::make_empty_column(cudf::type_id::DICTIONARY32); } @@ -956,15 +1095,21 @@ class dictionary_column_wrapper : public detail::column_wrapper { * * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - dictionary_column_wrapper(InputIterator begin, InputIterator end) : column_wrapper{} + dictionary_column_wrapper(InputIterator begin, + InputIterator end, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { - wrapped = - cudf::dictionary::encode(fixed_width_column_wrapper(begin, end), - cudf::data_type{type_id::INT32}, - cudf::test::get_default_stream(), - cudf::get_current_device_resource_ref()); + wrapped = cudf::dictionary::encode(fixed_width_column_wrapper( + begin, end, stream, mr.get_temporary_mr()), + cudf::data_type{type_id::INT32}, + stream, + mr.get_output_mr()); } /** @@ -991,15 +1136,25 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - dictionary_column_wrapper(InputIterator begin, InputIterator end, ValidityIterator v) + template < + typename InputIterator, + typename ValidityIterator, + std::enable_if_t>* = nullptr> + dictionary_column_wrapper(InputIterator begin, + InputIterator end, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { - wrapped = cudf::dictionary::encode( - fixed_width_column_wrapper(begin, end, v), - cudf::data_type{type_id::INT32}, - cudf::test::get_default_stream()); + wrapped = cudf::dictionary::encode(fixed_width_column_wrapper( + begin, end, v, stream, mr.get_temporary_mr()), + cudf::data_type{type_id::INT32}, + stream, + mr.get_output_mr()); } /** @@ -1014,10 +1169,14 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @endcode * * @param elements The list of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - dictionary_column_wrapper(std::initializer_list elements) - : dictionary_column_wrapper(std::cbegin(elements), std::cend(elements)) + dictionary_column_wrapper(std::initializer_list elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper(std::cbegin(elements), std::cend(elements), stream, mr) { } @@ -1038,11 +1197,16 @@ class dictionary_column_wrapper : public detail::column_wrapper { * * @param elements The list of elements * @param validity The list of validity indicator booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template dictionary_column_wrapper(std::initializer_list elements, - std::initializer_list validity) - : dictionary_column_wrapper(std::cbegin(elements), std::cend(elements), std::cbegin(validity)) + std::initializer_list validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper( + std::cbegin(elements), std::cend(elements), std::cbegin(validity), stream, mr) { } @@ -1063,10 +1227,18 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @tparam ValidityIterator Dereferencing a ValidityIterator must be convertible to `bool` * @param element_list The list of elements * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - dictionary_column_wrapper(std::initializer_list element_list, ValidityIterator v) - : dictionary_column_wrapper(std::cbegin(element_list), std::cend(element_list), v) + template < + typename ValidityIterator, + typename ElementFrom, + std::enable_if_t>* = nullptr> + dictionary_column_wrapper(std::initializer_list element_list, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper(std::cbegin(element_list), std::cend(element_list), v, stream, mr) { } @@ -1089,12 +1261,16 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence of elements * @param end The end of the sequence of elements * @param validity The list of validity indicator booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template dictionary_column_wrapper(InputIterator begin, InputIterator end, - std::initializer_list const& validity) - : dictionary_column_wrapper(begin, end, std::cbegin(validity)) + std::initializer_list const& validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper(begin, end, std::cbegin(validity), stream, mr) { } }; @@ -1135,8 +1311,16 @@ class dictionary_column_wrapper : public detail::column_wrapper { /** * @brief Default constructor initializes an empty dictionary column of strings + * + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - dictionary_column_wrapper() : dictionary_column_wrapper(std::initializer_list{}) {} + // Non-explicit so `{}` can copy-initialize empty dictionary columns. + dictionary_column_wrapper(rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper(std::initializer_list{}, stream, mr) + { + } /** * @brief Construct a non-nullable dictionary column of strings from the range @@ -1157,14 +1341,21 @@ class dictionary_column_wrapper : public detail::column_wrapper { * dereferencing a `StringsIterator`. * @param begin The beginning of the sequence * @param end The end of the sequence + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template - dictionary_column_wrapper(StringsIterator begin, StringsIterator end) : column_wrapper{} + dictionary_column_wrapper(StringsIterator begin, + StringsIterator end, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { - wrapped = cudf::dictionary::encode(strings_column_wrapper(begin, end), - cudf::data_type{type_id::INT32}, - cudf::test::get_default_stream(), - cudf::get_current_device_resource_ref()); + wrapped = + cudf::dictionary::encode(strings_column_wrapper(begin, end, stream, mr.get_temporary_mr()), + cudf::data_type{type_id::INT32}, + stream, + mr.get_output_mr()); } /** @@ -1194,14 +1385,25 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @param begin The beginning of the sequence * @param end The end of the sequence * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - dictionary_column_wrapper(StringsIterator begin, StringsIterator end, ValidityIterator v) + template < + typename StringsIterator, + typename ValidityIterator, + std::enable_if_t>* = nullptr> + dictionary_column_wrapper(StringsIterator begin, + StringsIterator end, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { - wrapped = cudf::dictionary::encode(strings_column_wrapper(begin, end, v), - cudf::data_type{type_id::INT32}, - cudf::test::get_default_stream()); + wrapped = + cudf::dictionary::encode(strings_column_wrapper(begin, end, v, stream, mr.get_temporary_mr()), + cudf::data_type{type_id::INT32}, + stream, + mr.get_output_mr()); } /** @@ -1215,9 +1417,13 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @endcode * * @param strings The list of strings + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - dictionary_column_wrapper(std::initializer_list strings) - : dictionary_column_wrapper(std::cbegin(strings), std::cend(strings)) + dictionary_column_wrapper(std::initializer_list strings, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper(std::cbegin(strings), std::cend(strings), stream, mr) { } @@ -1238,10 +1444,17 @@ class dictionary_column_wrapper : public detail::column_wrapper { * @tparam ValidityIterator Dereferencing a ValidityIterator must be convertible to `bool` * @param strings The list of strings * @param v The beginning of the sequence of validity indicators + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template - dictionary_column_wrapper(std::initializer_list strings, ValidityIterator v) - : dictionary_column_wrapper(std::cbegin(strings), std::cend(strings), v) + template < + typename ValidityIterator, + std::enable_if_t>* = nullptr> + dictionary_column_wrapper(std::initializer_list strings, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper(std::cbegin(strings), std::cend(strings), v, stream, mr) { } @@ -1259,10 +1472,15 @@ class dictionary_column_wrapper : public detail::column_wrapper { * * @param strings The list of strings * @param validity The list of validity indicator booleans + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ dictionary_column_wrapper(std::initializer_list strings, - std::initializer_list validity) - : dictionary_column_wrapper(std::cbegin(strings), std::cend(strings), std::cbegin(validity)) + std::initializer_list validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : dictionary_column_wrapper( + std::cbegin(strings), std::cend(strings), std::cbegin(validity), stream, mr) { } }; @@ -1322,12 +1540,19 @@ class lists_column_wrapper : public detail::column_wrapper { * @endcode * * @param elements The list of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template ()>* = nullptr> - lists_column_wrapper(std::initializer_list elements) : column_wrapper{} + lists_column_wrapper(std::initializer_list elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { build_from_non_nested( - cudf::test::fixed_width_column_wrapper(elements).release()); + cudf::test::fixed_width_column_wrapper(elements, stream, mr).release(), + stream, + mr); } /** @@ -1344,14 +1569,22 @@ class lists_column_wrapper : public detail::column_wrapper { * * @param begin Beginning of the sequence * @param end End of the sequence + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template ()>* = nullptr> - lists_column_wrapper(InputIterator begin, InputIterator end) : column_wrapper{} + lists_column_wrapper(InputIterator begin, + InputIterator end, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { build_from_non_nested( - cudf::test::fixed_width_column_wrapper(begin, end).release()); + cudf::test::fixed_width_column_wrapper(begin, end, stream, mr).release(), + stream, + mr); } /** @@ -1368,15 +1601,24 @@ class lists_column_wrapper : public detail::column_wrapper { * * @param elements The list of elements * @param v The validity iterator + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template ()>* = nullptr> - lists_column_wrapper(std::initializer_list elements, ValidityIterator v) + template < + typename Element = T, + typename ValidityIterator, + std::enable_if_t() && + !std::is_convertible_v>* = nullptr> + lists_column_wrapper(std::initializer_list elements, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { build_from_non_nested( - cudf::test::fixed_width_column_wrapper(elements, v).release()); + cudf::test::fixed_width_column_wrapper(elements, v, stream, mr).release(), + stream, + mr); } /** @@ -1395,16 +1637,27 @@ class lists_column_wrapper : public detail::column_wrapper { * @param begin Beginning of the sequence * @param end End of the sequence * @param v The validity iterator + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template ()>* = nullptr> - lists_column_wrapper(InputIterator begin, InputIterator end, ValidityIterator v) + template < + typename Element = T, + typename InputIterator, + typename ValidityIterator, + std::enable_if_t() && + !std::is_convertible_v>* = nullptr> + lists_column_wrapper(InputIterator begin, + InputIterator end, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { build_from_non_nested( - cudf::test::fixed_width_column_wrapper(begin, end, v).release()); + cudf::test::fixed_width_column_wrapper(begin, end, v, stream, mr) + .release(), + stream, + mr); } /** @@ -1419,13 +1672,20 @@ class lists_column_wrapper : public detail::column_wrapper { * @endcode * * @param elements The list of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template >* = nullptr> - lists_column_wrapper(std::initializer_list elements) : column_wrapper{} + lists_column_wrapper(std::initializer_list elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { build_from_non_nested( - cudf::test::strings_column_wrapper(elements.begin(), elements.end()).release()); + cudf::test::strings_column_wrapper(elements.begin(), elements.end(), stream, mr).release(), + stream, + mr); } /** @@ -1442,15 +1702,24 @@ class lists_column_wrapper : public detail::column_wrapper { * * @param elements The list of elements * @param v The validity iterator + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template >* = nullptr> - lists_column_wrapper(std::initializer_list elements, ValidityIterator v) + template < + typename Element = T, + typename ValidityIterator, + std::enable_if_t && + !std::is_convertible_v>* = nullptr> + lists_column_wrapper(std::initializer_list elements, + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { build_from_non_nested( - cudf::test::strings_column_wrapper(elements.begin(), elements.end(), v).release()); + cudf::test::strings_column_wrapper(elements.begin(), elements.end(), v, stream, mr).release(), + stream, + mr); } /** @@ -1473,16 +1742,20 @@ class lists_column_wrapper : public detail::column_wrapper { * @endcode * * @param elements The list of elements + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - lists_column_wrapper(std::initializer_list> elements) + lists_column_wrapper(std::initializer_list> elements, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { std::vector valids; - build_from_nested(elements, valids); + build_from_nested(elements, valids, stream, mr); } /** - * @brief Construct am empty lists column + * @brief Construct an empty lists column * * Example: * @code{.cpp} @@ -1491,10 +1764,14 @@ class lists_column_wrapper : public detail::column_wrapper { * lists_column_wrapper l{}; * @endcode * + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - lists_column_wrapper() : column_wrapper{} + lists_column_wrapper(rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) + : column_wrapper{} { - build_from_non_nested(make_empty_column(cudf::type_to_id())); + build_from_non_nested(make_empty_column(cudf::type_to_id()), stream, mr); } /** @@ -1521,10 +1798,16 @@ class lists_column_wrapper : public detail::column_wrapper { * * @param elements The list of elements * @param v The validity iterator + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template + template < + typename ValidityIterator, + std::enable_if_t>* = nullptr> lists_column_wrapper(std::initializer_list> elements, - ValidityIterator v) + ValidityIterator v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) : column_wrapper{} { std::vector validity; @@ -1533,25 +1816,33 @@ class lists_column_wrapper : public detail::column_wrapper { v, std::back_inserter(validity), [](lists_column_wrapper const& l, bool valid) { return valid; }); - build_from_nested(elements, validity); + build_from_nested(elements, validity, stream, mr); } /** * @brief Construct a list column containing a single empty, optionally null row. * * @param valid Whether or not the empty row is also null + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column * @return A list column containing a single empty row */ - static lists_column_wrapper make_one_empty_row_column(bool valid = true) + static lists_column_wrapper make_one_empty_row_column( + bool valid = true, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { - cudf::test::fixed_width_column_wrapper offsets{0, 0}; - cudf::test::fixed_width_column_wrapper values{}; + cudf::test::fixed_width_column_wrapper offsets({0, 0}, stream, mr); + cudf::test::fixed_width_column_wrapper values(stream, mr); return lists_column_wrapper( 1, offsets.release(), values.release(), valid ? 0 : 1, - valid ? rmm::device_buffer{} : cudf::create_null_mask(1, cudf::mask_state::ALL_NULL)); + valid ? rmm::device_buffer{} + : cudf::create_null_mask(1, cudf::mask_state::ALL_NULL, stream, mr.get_output_mr()), + stream, + mr); } private: @@ -1563,13 +1854,18 @@ class lists_column_wrapper : public detail::column_wrapper { * @param values The column of values bounded by the offsets * @param null_count The number of null list entries * @param null_mask The bits specifying the null lists in device memory + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources associated with the adopted constituent parts */ lists_column_wrapper(size_type num_rows, std::unique_ptr&& offsets, std::unique_ptr&& values, size_type null_count, - rmm::device_buffer&& null_mask) + rmm::device_buffer&& null_mask, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { + static_cast(mr); // construct the list column wrapped = make_lists_column( num_rows, std::move(offsets), std::move(values), null_count, std::move(null_mask)); @@ -1589,10 +1885,14 @@ class lists_column_wrapper : public detail::column_wrapper { * * @param elements Input columns to be wrapped * @param v The validity of each row + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column * */ void build_from_nested(std::initializer_list> elements, - std::vector const& v) + std::vector const& v, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { auto valids = cudf::detail::make_counting_transform_iterator( 0, [&v](auto i) { return v.empty() ? true : v[i]; }); @@ -1609,7 +1909,8 @@ class lists_column_wrapper : public detail::column_wrapper { int32_t const expected_depth = hierarchy_and_depth.second; // preprocess columns so that every column_view in 'cols' is an equivalent hierarchy - auto [cols, stubs] = preprocess_columns(elements, expected_hierarchy, expected_depth); + auto [cols, stubs] = + preprocess_columns(elements, expected_hierarchy, expected_depth, stream, mr); // generate offsets size_type count = 0; @@ -1627,7 +1928,8 @@ class lists_column_wrapper : public detail::column_wrapper { // add the final offset offsetv.push_back(count); auto offsets = - cudf::test::fixed_width_column_wrapper(offsetv.begin(), offsetv.end()).release(); + cudf::test::fixed_width_column_wrapper(offsetv.begin(), offsetv.end(), stream, mr) + .release(); // concatenate them together, skipping children that are null. std::vector children; @@ -1638,16 +1940,14 @@ class lists_column_wrapper : public detail::column_wrapper { cuda::std::identity{}); auto data = children.empty() ? cudf::empty_like(expected_hierarchy) - : cudf::concatenate(children, - cudf::test::get_default_stream(), - cudf::get_current_device_resource_ref()); + : cudf::concatenate(children, stream, mr.get_output_mr()); // increment depth depth = expected_depth + 1; auto [null_mask, null_count] = [&] { if (v.size() <= 0) return std::make_pair(rmm::device_buffer{}, cudf::size_type{0}); - return cudf::test::detail::make_null_mask(v.begin(), v.end()); + return cudf::test::detail::make_null_mask(v.begin(), v.end(), stream, mr); }(); // construct the list column @@ -1660,9 +1960,13 @@ class lists_column_wrapper : public detail::column_wrapper { * will be "unwrapped" when used in the nesting (list of lists) case. * * @param c Input column to be wrapped + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column * */ - void build_from_non_nested(std::unique_ptr c) + void build_from_non_nested(std::unique_ptr c, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { CUDF_EXPECTS(c->type().id() == type_id::EMPTY || !cudf::is_nested(c->type()), "Unexpected type"); @@ -1673,7 +1977,8 @@ class lists_column_wrapper : public detail::column_wrapper { offsetv.push_back(c->size()); } auto offsets = - cudf::test::fixed_width_column_wrapper(offsetv.begin(), offsetv.end()).release(); + cudf::test::fixed_width_column_wrapper(offsetv.begin(), offsetv.end(), stream, mr) + .release(); // construct the list column. mark this as a root root = true; @@ -1715,11 +2020,16 @@ class lists_column_wrapper : public detail::column_wrapper { * * @param col Input column to be normalized * @param expected_hierarchy Input column which represents the expected hierarchy + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used for temporary normalized copies * * @return A new column representing a normalized copy of col */ - std::unique_ptr normalize_column(column_view const& col, - column_view const& expected_hierarchy) + std::unique_ptr normalize_column( + column_view const& col, + column_view const& expected_hierarchy, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { // if are at the bottom of the short column, it must be empty if (col.type().id() != type_id::LIST) { @@ -1732,18 +2042,19 @@ class lists_column_wrapper : public detail::column_wrapper { lists_column_view lcv(col); return make_lists_column( col.size(), - std::make_unique(lcv.offsets()), - normalize_column(lists_column_view(col).child(), - lists_column_view(expected_hierarchy).child()), + std::make_unique(lcv.offsets(), stream, mr.get_temporary_mr()), + normalize_column( + lists_column_view(col).child(), lists_column_view(expected_hierarchy).child(), stream, mr), col.null_count(), - cudf::copy_bitmask( - col, cudf::test::get_default_stream(), cudf::get_current_device_resource_ref())); + cudf::copy_bitmask(col, stream, mr.get_temporary_mr())); } std::pair, std::vector>> preprocess_columns( std::initializer_list> const& elements, column_view& expected_hierarchy, - int expected_depth) + int expected_depth, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { std::vector> stubs; std::vector cols; @@ -1751,37 +2062,38 @@ class lists_column_wrapper : public detail::column_wrapper { // preprocess the incoming lists. // - unwrap any "root" lists // - handle incomplete hierarchies - std::transform(elements.begin(), - elements.end(), - std::back_inserter(cols), - [&](lists_column_wrapper const& l) -> column_view { - // depth mismatch. attempt to normalize the short column. - // this function will also catch if this is a legitimately broken - // set of input - if (l.depth < expected_depth) { - if (l.root) { - // this exception distinguishes between the following two cases: - // - // { {{{1, 2, 3}}}, {} } - // In this case, row 0 is a List>>, whereas row 1 is - // just a List<> which is an apparent mismatch. However, because row 1 - // is empty we will allow that to semantically mean - // "a List>> that's empty at the top level" - // - // { {{{1, 2, 3}}}, {4, 5, 6} } - // In this case, row 1 is a concrete List with actual values. - // There is no way to rectify the differences so we will treat it as a - // true column mismatch. - CUDF_EXPECTS(l.wrapped->size() == 0, "Mismatch in column types!"); - stubs.push_back(empty_like(expected_hierarchy)); - } else { - stubs.push_back(normalize_column(l.get_view(), expected_hierarchy)); - } - return *(stubs.back()); - } - // the empty hierarchy case - return l.get_view(); - }); + std::transform( + elements.begin(), + elements.end(), + std::back_inserter(cols), + [&](lists_column_wrapper const& l) -> column_view { + // depth mismatch. attempt to normalize the short column. + // this function will also catch if this is a legitimately broken + // set of input + if (l.depth < expected_depth) { + if (l.root) { + // this exception distinguishes between the following two cases: + // + // { {{{1, 2, 3}}}, {} } + // In this case, row 0 is a List>>, whereas row 1 is + // just a List<> which is an apparent mismatch. However, because row 1 + // is empty we will allow that to semantically mean + // "a List>> that's empty at the top level" + // + // { {{{1, 2, 3}}}, {4, 5, 6} } + // In this case, row 1 is a concrete List with actual values. + // There is no way to rectify the differences so we will treat it as a + // true column mismatch. + CUDF_EXPECTS(l.wrapped->size() == 0, "Mismatch in column types!"); + stubs.push_back(empty_like(expected_hierarchy)); + } else { + stubs.push_back(normalize_column(l.get_view(), expected_hierarchy, stream, mr)); + } + return *(stubs.back()); + } + // the empty hierarchy case + return l.get_view(); + }); return {std::move(cols), std::move(stubs)}; } @@ -1824,13 +2136,24 @@ class structs_column_wrapper : public detail::column_wrapper { * auto struct_col {structs_col.release()}; * @endcode * + * The existing allocations in adopted child columns retain their original memory-resource + * provenance. The supplied output resource controls the struct null mask and any child + * allocations created while sanitizing null struct rows. + * + * To pass an explicit stream/mr with no parent nulls, pass an empty validity: + * `structs_column_wrapper(std::move(children), {}, stream, mr)`. + * * @param child_columns The vector of pre-constructed child columns * @param validity The vector of bools representing the column validity values + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used for new allocations owned by the returned column */ structs_column_wrapper(std::vector>&& child_columns, - std::vector const& validity = {}) + std::vector const& validity = {}, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { - init(std::move(child_columns), validity); + init(std::move(child_columns), validity, stream, mr); } /** @@ -1850,12 +2173,22 @@ class structs_column_wrapper : public detail::column_wrapper { * auto struct_col {structs_col.release()}; * @endcode * + * Child wrappers are deep-copied, so all allocations in the returned children use the supplied + * output resource. The source wrappers retain their original allocations. + * + * To pass an explicit stream/mr with no parent nulls, pass an empty validity: + * `structs_column_wrapper({wrappers}, {}, stream, mr)`. + * * @param child_column_wrappers The list of child column wrappers * @param validity The vector of bools representing the column validity values + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ structs_column_wrapper( std::initializer_list> child_column_wrappers, - std::vector const& validity = {}) + std::vector const& validity = {}, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { std::vector> child_columns; child_columns.reserve(child_column_wrappers.size()); @@ -1863,10 +2196,10 @@ class structs_column_wrapper : public detail::column_wrapper { child_column_wrappers.end(), std::back_inserter(child_columns), [&](auto const& column_wrapper) { - return std::make_unique(column_wrapper.get(), - cudf::test::get_default_stream()); + return std::make_unique( + column_wrapper.get(), stream, mr.get_output_mr()); }); - init(std::move(child_columns), validity); + init(std::move(child_columns), validity, stream, mr); } /** @@ -1888,11 +2221,17 @@ class structs_column_wrapper : public detail::column_wrapper { * * @param child_column_wrappers The list of child column wrappers * @param validity_iter Iterator returning the per-row validity bool + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ - template + template && + !std::is_convertible_v>* = nullptr> structs_column_wrapper( std::initializer_list> child_column_wrappers, - V validity_iter) + V validity_iter, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { std::vector> child_columns; child_columns.reserve(child_column_wrappers.size()); @@ -1900,15 +2239,17 @@ class structs_column_wrapper : public detail::column_wrapper { child_column_wrappers.end(), std::back_inserter(child_columns), [&](auto const& column_wrapper) { - return std::make_unique(column_wrapper.get(), - cudf::test::get_default_stream()); + return std::make_unique( + column_wrapper.get(), stream, mr.get_output_mr()); }); - init(std::move(child_columns), validity_iter); + init(std::move(child_columns), validity_iter, stream, mr); } private: void init(std::vector>&& child_columns, - std::vector const& validity) + std::vector const& validity, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { size_type num_rows = child_columns.empty() ? 0 : child_columns[0]->size(); @@ -1922,19 +2263,22 @@ class structs_column_wrapper : public detail::column_wrapper { auto [null_mask, null_count] = [&] { if (validity.size() <= 0) return std::make_pair(rmm::device_buffer{}, cudf::size_type{0}); - return cudf::test::detail::make_null_mask(validity.begin(), validity.end()); + return cudf::test::detail::make_null_mask(validity.begin(), validity.end(), stream, mr); }(); wrapped = cudf::make_structs_column(num_rows, std::move(child_columns), null_count, std::move(null_mask), - cudf::test::get_default_stream(), - cudf::get_current_device_resource_ref()); + stream, + mr.get_output_mr()); } template - void init(std::vector>&& child_columns, V validity_iterator) + void init(std::vector>&& child_columns, + V validity_iterator, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { size_type const num_rows = child_columns.empty() ? 0 : child_columns[0]->size(); @@ -1946,7 +2290,7 @@ class structs_column_wrapper : public detail::column_wrapper { std::vector validity(num_rows); std::copy(validity_iterator, validity_iterator + num_rows, validity.begin()); - init(std::move(child_columns), validity); + init(std::move(child_columns), validity, stream, mr); } }; diff --git a/cpp/include/cudf_test/memory_resource_utilities.hpp b/cpp/include/cudf_test/memory_resource_utilities.hpp index 4c63e6741c52..f1986eada3c4 100644 --- a/cpp/include/cudf_test/memory_resource_utilities.hpp +++ b/cpp/include/cudf_test/memory_resource_utilities.hpp @@ -5,6 +5,7 @@ #pragma once +#include #include #include @@ -17,8 +18,10 @@ #include #include +#include #include #include +#include #include namespace CUDF_EXPORT cudf { @@ -28,9 +31,10 @@ namespace test { * @brief Exception-safe owner for a temporary current device resource. * * The installed resource and the previous resource are held by owning type-erased resource values. - * Destruction restores the previous resource, including during stack unwinding. Because the current - * resource is device-global state, scopes must not overlap concurrent work that changes or uses the - * current resource. + * Destruction restores the previous resource, including during stack unwinding. The object is + * movable: the moved-from object no longer restores on destruction. Because the current resource is + * device-global state, scopes must not overlap concurrent work that changes or uses the current + * resource. */ class scoped_current_device_resource { public: @@ -46,11 +50,13 @@ class scoped_current_device_resource { scoped_current_device_resource(scoped_current_device_resource const&) = delete; scoped_current_device_resource& operator=(scoped_current_device_resource const&) = delete; - scoped_current_device_resource(scoped_current_device_resource&&) = delete; - scoped_current_device_resource& operator=(scoped_current_device_resource&&) = delete; + scoped_current_device_resource(scoped_current_device_resource&&) noexcept; + scoped_current_device_resource& operator=(scoped_current_device_resource&&) noexcept; private: - cuda::mr::any_resource _previous; + void restore() noexcept; + + std::optional> _previous; }; /** @brief Expected relationship between live and total output-resource allocations. */ @@ -154,6 +160,24 @@ class memory_resource_test_harness { rmm::mr::callback_memory_resource _failing_mr; }; +/** + * @brief Callable that accepts a statistics resource and returns a column wrapper. + */ +template +concept column_wrapper_statistics_resource_factory = + requires(Factory& factory, rmm::mr::statistics_resource_adaptor& mr) { + { std::invoke(factory, mr) } -> std::derived_from; + }; + +/** + * @brief Callable that accepts `cudf::memory_resources` and returns a column wrapper. + */ +template +concept column_wrapper_memory_resources_factory = + requires(Factory& factory, cudf::memory_resources mr) { + { std::invoke(factory, mr) } -> std::derived_from; + }; + /** * @brief Verify that an owning result uses one explicitly supplied output resource. * @@ -169,7 +193,7 @@ class memory_resource_test_harness { * @param output_expectation Expected relationship between live and total output bytes * @param stream Stream to synchronize before inspecting allocation counters */ -template +template void expect_output_uses_resource( Factory&& factory, output_allocation_expectation output_expectation = output_allocation_expectation::EXACT, @@ -207,7 +231,7 @@ void expect_output_uses_resource( * @param expectations Expected output and temporary allocation behavior * @param stream Stream to synchronize before inspecting allocation counters */ -template +template void expect_output_uses_distinct_resources( Factory&& factory, memory_resource_expectations expectations = {}, diff --git a/cpp/include/cudf_test/timestamp_utilities.cuh b/cpp/include/cudf_test/timestamp_utilities.cuh index 62b8a1c8db87..f4386aac972e 100644 --- a/cpp/include/cudf_test/timestamp_utilities.cuh +++ b/cpp/include/cudf_test/timestamp_utilities.cuh @@ -1,11 +1,12 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2024, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #pragma once #include +#include #include #include @@ -32,11 +33,16 @@ using time_point_ms = * @param count The number of timestamps to create * @param start The first timestamp as a cuda::std::chrono::time_point * @param stop The last timestamp as a cuda::std::chrono::time_point + * @param stream CUDA stream used for device memory operations + * @param mr Memory resources used to allocate the returned column */ template -inline cudf::test::fixed_width_column_wrapper generate_timestamps(int32_t count, - time_point_ms start, - time_point_ms stop) +inline cudf::test::fixed_width_column_wrapper generate_timestamps( + int32_t count, + time_point_ms start, + time_point_ms stop, + rmm::cuda_stream_view stream = cudf::test::get_default_stream(), + cudf::memory_resources mr = cudf::get_current_device_resource_ref()) { using Rep = typename T::rep; using Period = typename T::period; @@ -57,10 +63,10 @@ inline cudf::test::fixed_width_column_wrapper generate_timestamps(in if (nullable) { auto mask = cudf::detail::make_counting_transform_iterator(0, [](auto i) { return i % 2 == 0; }); - return cudf::test::fixed_width_column_wrapper(iter, iter + count, mask); + return cudf::test::fixed_width_column_wrapper(iter, iter + count, mask, stream, mr); } else { // This needs to be in an else to quash `statement_not_reachable` warnings - return cudf::test::fixed_width_column_wrapper(iter, iter + count); + return cudf::test::fixed_width_column_wrapper(iter, iter + count, stream, mr); } } diff --git a/cpp/src/binaryop/compiled/struct_binary_ops.cuh b/cpp/src/binaryop/compiled/struct_binary_ops.cuh index 18f4a193b4cd..1126c12a8365 100644 --- a/cpp/src/binaryop/compiled/struct_binary_ops.cuh +++ b/cpp/src/binaryop/compiled/struct_binary_ops.cuh @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -146,7 +146,8 @@ void apply_struct_equality_op(mutable_column_view& out, auto tlhs = table_view{{lhs}}; auto trhs = table_view{{rhs}}; - auto table_comparator = cudf::detail::row::equality::two_table_comparator{tlhs, trhs, stream}; + auto table_comparator = cudf::detail::row::equality::two_table_comparator{ + tlhs, trhs, stream, cudf::get_current_device_resource_ref()}; auto outd = column_device_view::create(out, stream); auto optional_iter = diff --git a/cpp/src/dictionary/detail/concatenate.cu b/cpp/src/dictionary/detail/concatenate.cu index 9b2b275aa9c9..3bef24ea4331 100644 --- a/cpp/src/dictionary/detail/concatenate.cu +++ b/cpp/src/dictionary/detail/concatenate.cu @@ -187,8 +187,8 @@ std::unique_ptr concatenate(host_span columns, cudf::detail::row::hash::device_row_hasher>; auto const tv = cudf::table_view({all_keys->view()}); - auto const row_hash = cudf::detail::row::hash::row_hasher(tv, stream); - auto const row_equal = cudf::detail::row::equality::self_comparator(tv, stream); + auto const row_hash = cudf::detail::row::hash::row_hasher(tv, stream, mr); + auto const row_equal = cudf::detail::row::equality::self_comparator(tv, stream, mr); auto const comparator = cudf::detail::row::equality::nan_equal_physical_equality_comparator{}; auto const d_equal = row_equal.equal_to(cudf::nullate::NO{}, null_equality::EQUAL, comparator); diff --git a/cpp/src/dictionary/encode.cu b/cpp/src/dictionary/encode.cu index a43d18c080a4..67d53703c6f7 100644 --- a/cpp/src/dictionary/encode.cu +++ b/cpp/src/dictionary/encode.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -82,8 +82,8 @@ std::unique_ptr encode(column_view const& input, auto const has_nulls = nullate::DYNAMIC{input.has_nulls()}; auto const tv = cudf::table_view({input}); - auto const row_hash = cudf::detail::row::hash::row_hasher(tv, stream); - auto const row_equal = cudf::detail::row::equality::self_comparator(tv, stream); + auto const row_hash = cudf::detail::row::hash::row_hasher(tv, stream, mr); + auto const row_equal = cudf::detail::row::equality::self_comparator(tv, stream, mr); auto const comparator = cudf::detail::row::equality::nan_equal_physical_equality_comparator{}; auto const d_equal = row_equal.equal_to(has_nulls, null_equality::EQUAL, comparator); auto const empty_key = cuco::empty_key{cudf::detail::CUDF_SIZE_TYPE_SENTINEL}; diff --git a/cpp/src/dictionary/match_keys.cu b/cpp/src/dictionary/match_keys.cu index 3637d231d41d..2f1653ecb9a9 100644 --- a/cpp/src/dictionary/match_keys.cu +++ b/cpp/src/dictionary/match_keys.cu @@ -50,8 +50,8 @@ struct unique_keys_dispatch_fn { auto const has_nulls = nullate::DYNAMIC{false}; auto const keys_tv = table_view({all_keys}); - auto const row_hash = cudf::detail::row::hash::row_hasher(keys_tv, stream); - auto const row_equal = cudf::detail::row::equality::self_comparator(keys_tv, stream); + auto const row_hash = cudf::detail::row::hash::row_hasher(keys_tv, stream, mr); + auto const row_equal = cudf::detail::row::equality::self_comparator(keys_tv, stream, mr); auto const comparator = cudf::detail::row::equality::nan_equal_physical_equality_comparator{}; auto const d_equal = row_equal.equal_to(has_nulls, null_equality::EQUAL, comparator); auto const empty_key = cuco::empty_key{cudf::detail::CUDF_SIZE_TYPE_SENTINEL}; diff --git a/cpp/src/groupby/hash/groupby.cu b/cpp/src/groupby/hash/groupby.cu index 161b0384537b..b42c0fe5ae36 100644 --- a/cpp/src/groupby/hash/groupby.cu +++ b/cpp/src/groupby/hash/groupby.cu @@ -42,7 +42,7 @@ std::unique_ptr dispatch_groupby(table_view const& keys, auto const has_null = nullate::DYNAMIC{cudf::has_nested_nulls(keys)}; auto const skip_rows_with_nulls = keys_have_nulls and include_null_keys == null_policy::EXCLUDE; - auto preprocessed_keys = cudf::detail::row::hash::preprocessed_table::create(keys, stream); + auto preprocessed_keys = cudf::detail::row::hash::preprocessed_table::create(keys, stream, mr); auto const comparator = cudf::detail::row::equality::self_comparator{preprocessed_keys}; auto const row_hash = cudf::detail::row::hash::row_hasher{std::move(preprocessed_keys)}; auto const d_row_hash = row_hash.device_hasher(has_null); diff --git a/cpp/src/groupby/sort/group_nunique.cu b/cpp/src/groupby/sort/group_nunique.cu index 96aaa4cace1c..692739455352 100644 --- a/cpp/src/groupby/sort/group_nunique.cu +++ b/cpp/src/groupby/sort/group_nunique.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -79,7 +79,7 @@ std::unique_ptr group_nunique(column_view const& values, if (num_groups == 0) { return result; } auto const values_view = table_view{{values}}; - auto const comparator = cudf::detail::row::equality::self_comparator{values_view, stream}; + auto const comparator = cudf::detail::row::equality::self_comparator{values_view, stream, mr}; auto const d_values_view = column_device_view::create(values, stream); diff --git a/cpp/src/groupby/sort/group_rank_scan.cu b/cpp/src/groupby/sort/group_rank_scan.cu index 31ed09ff8cd7..221a09d7b8f6 100644 --- a/cpp/src/groupby/sort/group_rank_scan.cu +++ b/cpp/src/groupby/sort/group_rank_scan.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -94,7 +94,8 @@ std::unique_ptr rank_generator(column_view const& grouped_values, rmm::device_async_resource_ref mr) { auto const grouped_values_view = table_view{{grouped_values}}; - auto const comparator = cudf::detail::row::equality::self_comparator{grouped_values_view, stream}; + auto const comparator = + cudf::detail::row::equality::self_comparator{grouped_values_view, stream, mr}; auto ranks = make_fixed_width_column( data_type{type_to_id()}, grouped_values.size(), mask_state::UNALLOCATED, stream, mr); diff --git a/cpp/src/groupby/sort/sort_helper_group_offsets.cuh b/cpp/src/groupby/sort/sort_helper_group_offsets.cuh index 958d424e2bf4..9cb483beb8c7 100644 --- a/cpp/src/groupby/sort/sort_helper_group_offsets.cuh +++ b/cpp/src/groupby/sort/sort_helper_group_offsets.cuh @@ -38,7 +38,8 @@ size_type compute_group_offsets(table_view const& keys, rmm::device_uvector& group_offsets, rmm::cuda_stream_view stream) { - auto const comparator = cudf::detail::row::equality::self_comparator{keys, stream}; + auto const comparator = cudf::detail::row::equality::self_comparator{ + keys, stream, cudf::get_current_device_resource_ref()}; auto const d_key_equal = comparator.equal_to( cudf::nullate::DYNAMIC{cudf::has_nested_nulls(keys)}, null_equality::EQUAL); // Using a temporary buffer for intermediate transform results from the iterator containing diff --git a/cpp/src/groupby/streaming_groupby/insert.cuh b/cpp/src/groupby/streaming_groupby/insert.cuh index 39be36b4af7e..4c51f0d9eefd 100644 --- a/cpp/src/groupby/streaming_groupby/insert.cuh +++ b/cpp/src/groupby/streaming_groupby/insert.cuh @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -34,7 +34,8 @@ streaming_groupby::impl::batch_insert_result streaming_groupby::impl::probe_and_ auto const has_null = cudf::nullate::DYNAMIC{_has_nullable_keys}; // Preprocess batch for row operators. - auto preprocessed_batch = cudf::detail::row::hash::preprocessed_table::create(batch_keys, stream); + auto preprocessed_batch = + cudf::detail::row::hash::preprocessed_table::create(batch_keys, stream, temp_mr); auto const batch_hasher_obj = cudf::detail::row::hash::row_hasher{preprocessed_batch}; auto const d_batch_hash = batch_hasher_obj.device_hasher(has_null); @@ -110,7 +111,7 @@ streaming_groupby::impl::batch_insert_result streaming_groupby::impl::probe_and_ temp_mr); auto preprocessed_compacted = - cudf::detail::row::hash::preprocessed_table::create(compacted->view(), stream); + cudf::detail::row::hash::preprocessed_table::create(compacted->view(), stream, temp_mr); // Store the compacted batch. auto const new_batch_id = static_cast(_compacted_batches.size()); diff --git a/cpp/src/hash/murmurhash3_x86_32.cu b/cpp/src/hash/murmurhash3_x86_32.cu index f82d552456d7..109e77ef6380 100644 --- a/cpp/src/hash/murmurhash3_x86_32.cu +++ b/cpp/src/hash/murmurhash3_x86_32.cu @@ -67,7 +67,7 @@ std::unique_ptr murmurhash3_x86_32(table_view const& input, rmm::device_async_resource_ref mr) { auto const preprocessed_input = - cudf::detail::row::hash::preprocessed_table::create(input, stream); + cudf::detail::row::hash::preprocessed_table::create(input, stream, mr); return murmurhash3_x86_32_impl( preprocessed_input, input.num_rows(), seed, nullate::DYNAMIC{has_nulls(input)}, stream, mr); } diff --git a/cpp/src/hash/xxhash_32.cu b/cpp/src/hash/xxhash_32.cu index 759a491b193b..712dced0c71c 100644 --- a/cpp/src/hash/xxhash_32.cu +++ b/cpp/src/hash/xxhash_32.cu @@ -31,7 +31,7 @@ std::unique_ptr xxhash_32(table_view const& input, if (input.num_rows() == 0) { return output; } bool const nullable = has_nulls(input); - auto const row_hasher = cudf::detail::row::hash::row_hasher(input, stream); + auto const row_hasher = cudf::detail::row::hash::row_hasher(input, stream, mr); auto output_view = output->mutable_view(); // Compute the hash value for each row diff --git a/cpp/src/hash/xxhash_64.cu b/cpp/src/hash/xxhash_64.cu index fcf7009bd128..11b2b34f7cf5 100644 --- a/cpp/src/hash/xxhash_64.cu +++ b/cpp/src/hash/xxhash_64.cu @@ -33,7 +33,7 @@ std::unique_ptr xxhash_64(table_view const& input, if (input.num_rows() == 0) { return output; } bool const nullable = has_nulls(input); - auto const row_hasher = cudf::detail::row::hash::row_hasher(input, stream); + auto const row_hasher = cudf::detail::row::hash::row_hasher(input, stream, mr); auto output_view = output->mutable_view(); // Compute the hash value for each row diff --git a/cpp/src/join/distinct_hash_join.cu b/cpp/src/join/distinct_hash_join.cu index 8a5cf7b2a279..7b4c26e59a2e 100644 --- a/cpp/src/join/distinct_hash_join.cu +++ b/cpp/src/join/distinct_hash_join.cu @@ -163,7 +163,8 @@ distinct_hash_join::distinct_hash_join(cudf::table_view const& right, : _has_nested_columns{cudf::has_nested_columns(right)}, _nulls_equal{compare_nulls}, _right{right}, - _preprocessed_right{cudf::detail::row::equality::preprocessed_table::create(_right, stream)}, + _preprocessed_right{ + cudf::detail::row::equality::preprocessed_table::create(_right, stream, mr)}, _hash_table{cuco::extent{static_cast(right.num_rows())}, checked_load_factor(load_factor), cuco::empty_key{cuco::pair{std::numeric_limits::max(), @@ -240,7 +241,8 @@ distinct_hash_join::inner_join(cudf::table_view const& left, auto found_indices = rmm::device_uvector(left_table_num_rows, stream); auto const found_begin = cuda::make_transform_output_iterator(found_indices.begin(), output_fn{}); - auto preprocessed_left = cudf::detail::row::equality::preprocessed_table::create(left, stream); + auto preprocessed_left = + cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); if (cudf::detail::is_primitive_row_op_compatible(_right)) { auto const d_hasher = cudf::detail::row::primitive::row_hasher{nullate::DYNAMIC{has_nulls}, preprocessed_left}; @@ -333,7 +335,8 @@ std::unique_ptr> distinct_hash_join::left_join( auto const output_begin = cuda::make_transform_output_iterator(right_indices->begin(), output_fn{}); - auto preprocessed_left = cudf::detail::row::equality::preprocessed_table::create(left, stream); + auto preprocessed_left = + cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); if (cudf::detail::is_primitive_row_op_compatible(_right)) { auto const d_hasher = diff --git a/cpp/src/join/filtered_join/filtered_join.cu b/cpp/src/join/filtered_join/filtered_join.cu index d1766f0ffab3..40345b88e3db 100644 --- a/cpp/src/join/filtered_join/filtered_join.cu +++ b/cpp/src/join/filtered_join/filtered_join.cu @@ -103,11 +103,11 @@ filtered_join::filtered_join(cudf::table_view const& right, : _right_mode{select_row_operator_mode(right)}, _bucket_storage{cuco::extent{compute_bucket_storage_size( right.num_rows(), checked_load_factor(load_factor), _right_mode)}, - rmm::mr::polymorphic_allocator{std::move(mr)}, + rmm::mr::polymorphic_allocator{mr}, stream.value()}, _right{right}, _nulls_equal{compare_nulls}, - _preprocessed_right{cudf::detail::row::equality::preprocessed_table::create(_right, stream)} + _preprocessed_right{cudf::detail::row::equality::preprocessed_table::create(_right, stream, mr)} { cudf::scoped_range range{"filtered_join::filtered_join"}; if (_right.num_rows() == 0) return; @@ -129,9 +129,9 @@ std::unique_ptr> filtered_join::semi_anti_j { cudf::scoped_range range{"filtered_join::semi_anti_join"}; - auto const preprocessed_left = [&left, stream] { + auto const preprocessed_left = [&left, stream, mr] { cudf::scoped_range range{"filtered_join::semi_anti_join::preprocessed_left"}; - return cudf::detail::row::equality::preprocessed_table::create(left, stream); + return cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); }(); auto contains_map = rmm::device_uvector(left.num_rows(), stream); diff --git a/cpp/src/join/hash_join/hash_join.cu b/cpp/src/join/hash_join/hash_join.cu index b699e04fff42..944950cbbeee 100644 --- a/cpp/src/join/hash_join/hash_join.cu +++ b/cpp/src/join/hash_join/hash_join.cu @@ -127,10 +127,10 @@ hash_join::hash_join(cudf::table_view const& right, {}, {}, {}, - rmm::mr::polymorphic_allocator{std::move(mr)}, + rmm::mr::polymorphic_allocator{mr}, stream.value()}})}, _right{right}, - _preprocessed_right{cudf::detail::row::equality::preprocessed_table::create(_right, stream)} + _preprocessed_right{cudf::detail::row::equality::preprocessed_table::create(_right, stream, mr)} { CUDF_FUNC_RANGE(); CUDF_EXPECTS(0 != right.num_columns(), "Hash join right table is empty", std::invalid_argument); diff --git a/cpp/src/join/hash_join/match_context.cu b/cpp/src/join/hash_join/match_context.cu index 5fc2dd5ba9cf..b4d4964adf24 100644 --- a/cpp/src/join/hash_join/match_context.cu +++ b/cpp/src/join/hash_join/match_context.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -46,7 +46,7 @@ std::unique_ptr> make_join_match_counts( std::invalid_argument); auto const preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left, stream); + cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); auto const left_table_num_rows = left.num_rows(); auto count_matches = [&](auto equality, auto d_hasher) { diff --git a/cpp/src/join/hash_join/partitioned_join_retrieve.cu b/cpp/src/join/hash_join/partitioned_join_retrieve.cu index 77dcae1e9325..97bc7cd494fc 100644 --- a/cpp/src/join/hash_join/partitioned_join_retrieve.cu +++ b/cpp/src/join/hash_join/partitioned_join_retrieve.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -107,7 +107,7 @@ hash_join::partitioned_join_retrieve(join_kind join, validate_hash_join_probe(_right, left_partition_view, _has_nulls); auto const preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left_partition_view, stream); + cudf::detail::row::equality::preprocessed_table::create(left_partition_view, stream, mr); // For FULL_JOIN, probe with LEFT_JOIN semantics (no complement here) bool const is_outer = (join != join_kind::INNER_JOIN); diff --git a/cpp/src/join/hash_join/retrieve_impl.cuh b/cpp/src/join/hash_join/retrieve_impl.cuh index 5efe69afe850..e9042d2c4614 100644 --- a/cpp/src/join/hash_join/retrieve_impl.cuh +++ b/cpp/src/join/hash_join/retrieve_impl.cuh @@ -174,7 +174,7 @@ hash_join::join_retrieve(cudf::table_view const& left, } auto const preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left, stream); + cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); auto join_indices = cudf::detail::probe_join_hash_table(_right, left, diff --git a/cpp/src/join/hash_join/size_impl.cuh b/cpp/src/join/hash_join/size_impl.cuh index 3e20ebc7367e..fb84237e9aa8 100644 --- a/cpp/src/join/hash_join/size_impl.cuh +++ b/cpp/src/join/hash_join/size_impl.cuh @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #pragma once @@ -80,8 +80,8 @@ std::size_t hash_join::join_size(cudf::table_view const& left, "Left table has nulls while right table was not hashed with null check.", std::invalid_argument); - auto const preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left, stream); + auto const preprocessed_left = cudf::detail::row::equality::preprocessed_table::create( + left, stream, cudf::get_current_device_resource_ref()); return cudf::detail::compute_join_output_size(_right, left, @@ -110,9 +110,7 @@ std::size_t hash_join::join_size(cudf::table_view const& left, std::invalid_argument); auto const preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left, stream); - - return cudf::detail::get_full_join_size(_right, + cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); left, _preprocessed_right, preprocessed_left, diff --git a/cpp/src/join/key_remapping.cu b/cpp/src/join/key_remapping.cu index ef8540c261f4..4222f0822724 100644 --- a/cpp/src/join/key_remapping.cu +++ b/cpp/src/join/key_remapping.cu @@ -395,7 +395,7 @@ class key_remap_table : public key_remap_table_interface { cuda::make_transform_output_iterator(result->begin(), extract_index{}); auto preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left_keys, stream); + cudf::detail::row::equality::preprocessed_table::create(left_keys, stream, mr); if (cudf::detail::is_primitive_row_op_compatible(_right)) { auto const d_hasher = cudf::detail::row::primitive::row_hasher{ @@ -500,7 +500,8 @@ std::unique_ptr create_key_remap_table( if (right.num_rows() == 0 || right.num_columns() == 0) { return nullptr; } - auto preprocessed_right = cudf::detail::row::equality::preprocessed_table::create(right, stream); + auto preprocessed_right = + cudf::detail::row::equality::preprocessed_table::create(right, stream, mr); if (cudf::detail::is_primitive_row_op_compatible(right)) { auto const d_hasher = cudf::detail::row::primitive::row_hasher{ diff --git a/cpp/src/join/mark_join.cu b/cpp/src/join/mark_join.cu index c050170e3853..e246e7f55eea 100644 --- a/cpp/src/join/mark_join.cu +++ b/cpp/src/join/mark_join.cu @@ -597,7 +597,7 @@ mark_join::mark_join(cudf::table_view const& left, _left{left}, _nulls_equal{compare_nulls}, _prefilter{prefilter}, - _preprocessed_left{cudf::detail::row::equality::preprocessed_table::create(left, stream)}, + _preprocessed_left{cudf::detail::row::equality::preprocessed_table::create(left, stream, mr)}, _bucket_storage{ cuco::extent{compute_mark_join_capacity(left, checked_load_factor(load_factor))}, rmm::mr::polymorphic_allocator{mr}, @@ -742,9 +742,9 @@ std::unique_ptr> mark_join::semi_anti_join( { clear_marks(stream); - auto const preprocessed_right = [&right, stream] { + auto const preprocessed_right = [&right, stream, mr] { cudf::scoped_range range{"mark_join::semi_anti_join::preprocessed_right"}; - return cudf::detail::row::equality::preprocessed_table::create(right, stream); + return cudf::detail::row::equality::preprocessed_table::create(right, stream, mr); }(); if (is_primitive_row_op_compatible(_left)) { diff --git a/cpp/src/join/mixed_join_semi.cu b/cpp/src/join/mixed_join_semi.cu index 8021cdab21bc..e9707e73d3fb 100644 --- a/cpp/src/join/mixed_join_semi.cu +++ b/cpp/src/join/mixed_join_semi.cu @@ -106,9 +106,9 @@ std::unique_ptr> mixed_join_semi( auto right_conditional_view = table_device_view::create(right_conditional, stream); auto const preprocessed_right = - cudf::detail::row::equality::preprocessed_table::create(right, stream); + cudf::detail::row::equality::preprocessed_table::create(right, stream, mr); auto const preprocessed_left = - cudf::detail::row::equality::preprocessed_table::create(left, stream); + cudf::detail::row::equality::preprocessed_table::create(left, stream, mr); auto const row_comparator = cudf::detail::row::equality::two_table_comparator{preprocessed_left, preprocessed_right}; auto const equality_left = row_comparator.equal_to(has_nulls, compare_nulls); @@ -134,7 +134,7 @@ std::unique_ptr> mixed_join_semi( auto const equality_right_equality = row_comparator_right.equal_to(right_nulls, compare_nulls); auto const preprocessed_right_condtional = - cudf::detail::row::equality::preprocessed_table::create(right_conditional, stream); + cudf::detail::row::equality::preprocessed_table::create(right_conditional, stream, mr); auto const row_comparator_conditional_right = cudf::detail::row::equality::two_table_comparator{ preprocessed_right_condtional, preprocessed_right_condtional}; auto const equality_right_conditional = @@ -157,8 +157,7 @@ std::unique_ptr> mixed_join_semi( row_set.insert_async(iter, iter + right_num_rows, stream.value()); } else { cuda::counting_iterator stencil(0); - auto const [row_bitmask, _] = - cudf::detail::bitmask_and(right, stream, cudf::get_current_device_resource_ref()); + auto const [row_bitmask, _] = cudf::detail::bitmask_and(right, stream, mr); row_is_valid pred{static_cast(row_bitmask.data())}; // insert valid rows diff --git a/cpp/src/lists/contains.cu b/cpp/src/lists/contains.cu index 58251a141111..d696cc21af1f 100644 --- a/cpp/src/lists/contains.cu +++ b/cpp/src/lists/contains.cu @@ -211,7 +211,7 @@ std::unique_ptr dispatch_index_of(lists_column_view const& lists, auto const child_tview = cudf::table_view{{child}}; auto const has_nulls = has_nested_nulls(child_tview) || has_nested_nulls(keys_tview); auto const comparator = - cudf::detail::row::equality::two_table_comparator(child_tview, keys_tview, stream); + cudf::detail::row::equality::two_table_comparator(child_tview, keys_tview, stream, mr); if (cudf::is_nested(search_keys.type())) { auto const d_comp = comparator.equal_to(nullate::DYNAMIC{has_nulls}); index_of(input_it, num_rows, output_it, child, search_keys, find_option, d_comp, stream); diff --git a/cpp/src/partitioning/partitioning.cu b/cpp/src/partitioning/partitioning.cu index d9bf0d99864f..7f6827aa3b98 100644 --- a/cpp/src/partitioning/partitioning.cu +++ b/cpp/src/partitioning/partitioning.cu @@ -576,7 +576,7 @@ std::pair, std::vector> hash_partition_table( { auto const num_rows = table_to_hash.num_rows(); - auto const row_hasher = detail::row::hash::row_hasher(table_to_hash, stream); + auto const row_hasher = detail::row::hash::row_hasher(table_to_hash, stream, mr); auto const hasher = row_hasher.device_hasher(nullate::DYNAMIC{hash_has_nulls}, seed); diff --git a/cpp/src/reductions/approx_distinct_count.cu b/cpp/src/reductions/approx_distinct_count.cu index 70b1c46ff58b..c1a4e514dc38 100644 --- a/cpp/src/reductions/approx_distinct_count.cu +++ b/cpp/src/reductions/approx_distinct_count.cu @@ -223,7 +223,7 @@ void approx_distinct_count::add(table_view const& input, rmm::cuda_strea auto const has_nulls = nullate::DYNAMIC{cudf::has_nested_nulls(input)}; auto const preprocessed_input = - cudf::detail::row::hash::preprocessed_table::create(input, stream); + cudf::detail::row::hash::preprocessed_table::create(input, stream, _mr); auto const row_hasher = cudf::detail::row::hash::row_hasher(preprocessed_input); auto const hash_key = row_hasher.device_hasher(has_nulls); diff --git a/cpp/src/reductions/distinct_count.cu b/cpp/src/reductions/distinct_count.cu index bd2571e2dd0b..35f64a1cb7bb 100644 --- a/cpp/src/reductions/distinct_count.cu +++ b/cpp/src/reductions/distinct_count.cu @@ -136,10 +136,11 @@ cudf::size_type distinct_count(table_view const& keys, if (num_rows == 0) { return 0; } // early exit for empty input auto const has_nulls = nullate::DYNAMIC{cudf::has_nested_nulls(keys)}; - auto const preprocessed_input = cudf::detail::row::hash::preprocessed_table::create(keys, stream); - auto const row_hasher = cudf::detail::row::hash::row_hasher(preprocessed_input); - auto const hash_key = row_hasher.device_hasher(has_nulls); - auto const row_comp = cudf::detail::row::equality::self_comparator(preprocessed_input); + auto const preprocessed_input = cudf::detail::row::hash::preprocessed_table::create( + keys, stream, cudf::get_current_device_resource_ref()); + auto const row_hasher = cudf::detail::row::hash::row_hasher(preprocessed_input); + auto const hash_key = row_hasher.device_hasher(has_nulls); + auto const row_comp = cudf::detail::row::equality::self_comparator(preprocessed_input); auto const comparator_helper = [&](auto const row_equal) { using hasher_type = decltype(hash_key); diff --git a/cpp/src/reductions/histogram.cu b/cpp/src/reductions/histogram.cu index e0408d64ee4f..2737fc685083 100644 --- a/cpp/src/reductions/histogram.cu +++ b/cpp/src/reductions/histogram.cu @@ -112,7 +112,7 @@ compute_row_frequencies(table_view const& input, std::invalid_argument); auto const preprocessed_input = - cudf::detail::row::hash::preprocessed_table::create(input, stream); + cudf::detail::row::hash::preprocessed_table::create(input, stream, mr); auto const has_nulls = nullate::DYNAMIC{cudf::has_nested_nulls(input)}; auto const row_hasher = cudf::detail::row::hash::row_hasher(preprocessed_input); diff --git a/cpp/src/reductions/scan/rank_scan.cu b/cpp/src/reductions/scan/rank_scan.cu index 4d99f4199224..01cdf8cb9807 100644 --- a/cpp/src/reductions/scan/rank_scan.cu +++ b/cpp/src/reductions/scan/rank_scan.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -60,7 +60,7 @@ std::unique_ptr rank_generator(column_view const& order_by, rmm::device_async_resource_ref mr) { auto const order_by_tview = table_view{{order_by}}; - auto comp = cudf::detail::row::equality::self_comparator(order_by_tview, stream); + auto comp = cudf::detail::row::equality::self_comparator(order_by_tview, stream, mr); auto ranks = make_fixed_width_column( data_type{type_to_id()}, order_by.size(), mask_state::UNALLOCATED, stream, mr); diff --git a/cpp/src/reductions/segmented/nunique.cu b/cpp/src/reductions/segmented/nunique.cu index 62730cbb78c2..6ca10f6a058b 100644 --- a/cpp/src/reductions/segmented/nunique.cu +++ b/cpp/src/reductions/segmented/nunique.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -52,8 +52,9 @@ std::unique_ptr segmented_nunique(column_view const& col, // compute the unique identifiers within each segment auto const identifiers = [&] { - auto const d_col = column_device_view::create(col, stream); - auto const comparator = cudf::detail::row::equality::self_comparator{table_view({col}), stream}; + auto const d_col = column_device_view::create(col, stream); + auto const comparator = + cudf::detail::row::equality::self_comparator{table_view({col}), stream, mr}; auto const row_equal = comparator.equal_to(cudf::nullate::DYNAMIC{col.has_nulls()}, null_equality::EQUAL); diff --git a/cpp/src/reductions/unique_count.cu b/cpp/src/reductions/unique_count.cu index 278a12391e26..98534699cfa0 100644 --- a/cpp/src/reductions/unique_count.cu +++ b/cpp/src/reductions/unique_count.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,8 @@ cudf::size_type unique_count(table_view const& keys, null_equality nulls_equal, rmm::cuda_stream_view stream) { - auto const row_comp = cudf::detail::row::equality::self_comparator(keys, stream); + auto const row_comp = cudf::detail::row::equality::self_comparator( + keys, stream, cudf::get_current_device_resource_ref()); if (cudf::detail::has_nested_columns(keys)) { auto const comp = row_comp.equal_to(nullate::DYNAMIC{has_nested_nulls(keys)}, nulls_equal); diff --git a/cpp/src/reductions/unique_count_column.cu b/cpp/src/reductions/unique_count_column.cu index effdd3a5a323..48e62a0f7010 100644 --- a/cpp/src/reductions/unique_count_column.cu +++ b/cpp/src/reductions/unique_count_column.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -61,8 +61,9 @@ cudf::size_type unique_count(column_view const& input, auto device_view = *input_device_view; auto input_table_view = table_view{{input}}; - auto const comparator = cudf::detail::row::equality::self_comparator{input_table_view, stream}; - auto const comp = comparator.equal_to( + auto const comparator = cudf::detail::row::equality::self_comparator{ + input_table_view, stream, cudf::get_current_device_resource_ref()}; + auto const comp = comparator.equal_to( nullate::DYNAMIC{cudf::has_nulls(input_table_view)}, null_equality::EQUAL, cudf::detail::row::equality::nan_equal_physical_equality_comparator{}); diff --git a/cpp/src/row_operator/row_operators.cu b/cpp/src/row_operator/row_operators.cu index 698b184abef8..ce24199df6fe 100644 --- a/cpp/src/row_operator/row_operators.cu +++ b/cpp/src/row_operator/row_operators.cu @@ -843,26 +843,29 @@ two_table_comparator::two_table_comparator(table_view const& left, namespace equality { std::shared_ptr preprocessed_table::create(table_view const& t, - rmm::cuda_stream_view stream) + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { check_eq_compatibility(t); auto [null_pushed_table, nullable_data] = - structs::detail::push_down_nulls(t, stream, cudf::get_current_device_resource_ref()); + structs::detail::push_down_nulls(t, stream, mr.get_temporary_mr()); auto struct_offset_removed_table = remove_struct_child_offsets(null_pushed_table); auto verticalized_t = std::get<0>(decompose_structs(struct_offset_removed_table, decompose_lists_column::YES)); - auto d_t = table_device_view_owner(table_device_view::create(verticalized_t, stream)); + auto d_t = table_device_view_owner( + table_device_view::create(verticalized_t, stream, mr.get_temporary_mr())); return std::shared_ptr(new preprocessed_table( std::move(d_t), std::move(nullable_data.new_null_masks), std::move(nullable_data.new_columns))); } two_table_comparator::two_table_comparator(table_view const& left, table_view const& right, - rmm::cuda_stream_view stream) - : d_left_table{preprocessed_table::create(left, stream)}, - d_right_table{preprocessed_table::create(right, stream)} + rmm::cuda_stream_view stream, + cudf::memory_resources mr) + : d_left_table{preprocessed_table::create(left, stream, mr)}, + d_right_table{preprocessed_table::create(right, stream, mr)} { check_shape_compatibility(left, right); } diff --git a/cpp/src/search/contains_scalar.cu b/cpp/src/search/contains_scalar.cu index 3f70f0260f69..4b27c5c2ac07 100644 --- a/cpp/src/search/contains_scalar.cu +++ b/cpp/src/search/contains_scalar.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -93,30 +93,30 @@ struct contains_scalar_dispatch { // In addition, haystack and needle structure compatibility will be checked later on by // constructor of the table comparator. - auto const haystack_tv = table_view{{haystack}}; - auto const needle_as_col = - make_column_from_scalar(needle, 1, stream, cudf::get_current_device_resource_ref()); - auto const needle_tv = table_view{{needle_as_col->view()}}; - auto const has_nulls = has_nested_nulls(haystack_tv) || has_nested_nulls(needle_tv); + auto const haystack_tv = table_view{{haystack}}; + auto const mr = cudf::get_current_device_resource_ref(); + auto const needle_as_col = make_column_from_scalar(needle, 1, stream, mr); + auto const needle_tv = table_view{{needle_as_col->view()}}; + auto const has_nulls = has_nested_nulls(haystack_tv) || has_nested_nulls(needle_tv); auto const comparator = - cudf::detail::row::equality::two_table_comparator(haystack_tv, needle_tv, stream); + cudf::detail::row::equality::two_table_comparator(haystack_tv, needle_tv, stream, mr); auto const begin = cudf::detail::row::lhs_iterator(0); auto const end = begin + haystack.size(); using cudf::detail::row::rhs_index_type; auto const check_nulls = haystack.has_nulls(); - auto const haystack_cdv_ptr = column_device_view::create(haystack, stream); + auto const haystack_cdv_ptr = column_device_view::create(haystack, stream, mr); auto const d_comp = comparator.equal_to(nullate::DYNAMIC{has_nulls}); // Using a temporary buffer for intermediate transform results from the lambda containing // the comparator speeds up compile-time significantly without much degradation in // runtime performance over using the comparator in a transform iterator with thrust::count_if. - auto d_results = rmm::device_uvector(haystack.size(), stream); + auto d_results = rmm::device_uvector(haystack.size(), stream, mr); thrust::transform( - rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), + rmm::exec_policy_nosync(stream, mr), begin, end, d_results.begin(), @@ -127,10 +127,8 @@ struct contains_scalar_dispatch { return d_comp(idx, rhs_index_type{0}); // compare haystack[idx] == needle[0]. }); - return thrust::count(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), - d_results.begin(), - d_results.end(), - true) > 0; + return thrust::count( + rmm::exec_policy_nosync(stream, mr), d_results.begin(), d_results.end(), true) > 0; } }; diff --git a/cpp/src/search/contains_table.cu b/cpp/src/search/contains_table.cu index c3ff93adf4a3..b05752aea55f 100644 --- a/cpp/src/search/contains_table.cu +++ b/cpp/src/search/contains_table.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -36,9 +36,9 @@ rmm::device_uvector contains(table_view const& haystack, auto const has_any_nulls = haystack_has_nulls || needles_has_nulls; auto const preprocessed_needles = - cudf::detail::row::equality::preprocessed_table::create(needles, stream); + cudf::detail::row::equality::preprocessed_table::create(needles, stream, mr); auto const preprocessed_haystack = - cudf::detail::row::equality::preprocessed_table::create(haystack, stream); + cudf::detail::row::equality::preprocessed_table::create(haystack, stream, mr); // The output vector. auto contained = rmm::device_uvector(needles.num_rows(), stream, mr); diff --git a/cpp/src/sort/rank.cu b/cpp/src/sort/rank.cu index 27e9f3596845..79293016f006 100644 --- a/cpp/src/sort/rank.cu +++ b/cpp/src/sort/rank.cu @@ -61,7 +61,8 @@ rmm::device_uvector sorted_dense_rank(column_view input_col, rmm::cuda_stream_view stream) { auto const t_input = table_view{{input_col}}; - auto const comparator = cudf::detail::row::equality::self_comparator{t_input, stream}; + auto const mr = cudf::get_current_device_resource_ref(); + auto const comparator = cudf::detail::row::equality::self_comparator{t_input, stream, mr}; auto const sorted_index_order = cuda::make_permutation_iterator( sorted_order_view.begin(), cuda::counting_iterator{0}); @@ -70,7 +71,7 @@ rmm::device_uvector sorted_dense_rank(column_view input_col, rmm::device_uvector dense_rank_sorted(input_size, stream); auto const comparator_helper = [&](auto const device_comparator) { - thrust::transform(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), + thrust::transform(rmm::exec_policy_nosync(stream, mr), cuda::counting_iterator{0}, cuda::counting_iterator{input_size}, dense_rank_sorted.data(), @@ -88,7 +89,7 @@ rmm::device_uvector sorted_dense_rank(column_view input_col, comparator_helper(device_comparator); } - thrust::inclusive_scan(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), + thrust::inclusive_scan(rmm::exec_policy_nosync(stream, mr), dense_rank_sorted.begin(), dense_rank_sorted.end(), dense_rank_sorted.data()); diff --git a/cpp/src/stream_compaction/distinct.cu b/cpp/src/stream_compaction/distinct.cu index 9db6bbd76c8c..4e66a0fa22a1 100644 --- a/cpp/src/stream_compaction/distinct.cu +++ b/cpp/src/stream_compaction/distinct.cu @@ -87,7 +87,7 @@ rmm::device_uvector distinct_indices(table_view const& input, } auto const preprocessed_input = - cudf::detail::row::hash::preprocessed_table::create(input, stream); + cudf::detail::row::hash::preprocessed_table::create(input, stream, mr); auto const has_nulls = nullate::DYNAMIC{cudf::has_nested_nulls(input)}; auto const has_nested_columns = cudf::detail::has_nested_columns(input); diff --git a/cpp/src/stream_compaction/unique.cu b/cpp/src/stream_compaction/unique.cu index 12ccfcb97129..4914336d35d0 100644 --- a/cpp/src/stream_compaction/unique.cu +++ b/cpp/src/stream_compaction/unique.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -55,7 +55,7 @@ std::unique_ptr
unique(table_view const& input, auto mutable_view = mutable_column_device_view::create(*unique_indices, stream); auto keys_view = input.select(keys); - auto comp = cudf::detail::row::equality::self_comparator(keys_view, stream); + auto comp = cudf::detail::row::equality::self_comparator(keys_view, stream, mr); size_type const unique_size = [&] { if (cudf::detail::has_nested_columns(keys_view)) { diff --git a/cpp/src/table/table_equal.cu b/cpp/src/table/table_equal.cu index 0cc97e0da260..183ccb3e7406 100644 --- a/cpp/src/table/table_equal.cu +++ b/cpp/src/table/table_equal.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -31,11 +31,11 @@ template null_equality nulls_equal, rmm::cuda_stream_view stream) { - auto const comparator = detail::row::equality::two_table_comparator{left, right, stream}; + auto const mr = cudf::get_current_device_resource_ref(); + auto const comparator = detail::row::equality::two_table_comparator{left, right, stream, mr}; auto const rows_equal = comparator.equal_to( nullate::DYNAMIC{has_nested_nulls(left) or has_nested_nulls(right)}, nulls_equal); - rmm::device_uvector eq_rows{ - static_cast(left.num_rows()), stream, cudf::get_current_device_resource_ref()}; + rmm::device_uvector eq_rows{static_cast(left.num_rows()), stream, mr}; CUDF_CUDA_TRY(cub::DeviceTransform::Transform( cuda::counting_iterator{0}, eq_rows.begin(), diff --git a/cpp/src/transform/one_hot_encode.cu b/cpp/src/transform/one_hot_encode.cu index 098618c7d96c..2a54fcf430c8 100644 --- a/cpp/src/transform/one_hot_encode.cu +++ b/cpp/src/transform/one_hot_encode.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2021-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -68,9 +68,10 @@ std::pair, table_view> one_hot_encode(column_view const& auto all_encodings = make_numeric_column(data_type{type_id::BOOL8}, total_size, mask_state::UNALLOCATED, stream, mr); - auto const t_lhs = table_view{{input}}; - auto const t_rhs = table_view{{categories}}; - auto const comparator = cudf::detail::row::equality::two_table_comparator{t_lhs, t_rhs, stream}; + auto const t_lhs = table_view{{input}}; + auto const t_rhs = table_view{{categories}}; + auto const comparator = + cudf::detail::row::equality::two_table_comparator{t_lhs, t_rhs, stream, mr}; auto const comparator_helper = [&](auto const d_equal) { thrust::transform(rmm::exec_policy_nosync(stream, cudf::get_current_device_resource_ref()), diff --git a/cpp/tests/copying/concatenate_tests.cpp b/cpp/tests/copying/concatenate_tests.cpp index 8875add31856..6f42323bfe99 100644 --- a/cpp/tests/copying/concatenate_tests.cpp +++ b/cpp/tests/copying/concatenate_tests.cpp @@ -823,8 +823,7 @@ TEST_F(StructsColumnTest, ConcatenateStructs) {true, false})); src.push_back(cudf::test::structs_column_wrapper({name_cols[1], age_cols[1], is_human_cols[1]}, {true, true})); - src.push_back( - cudf::test::structs_column_wrapper({name_cols[2], age_cols[2], is_human_cols[2]}, {})); + src.push_back(cudf::test::structs_column_wrapper({name_cols[2], age_cols[2], is_human_cols[2]})); src.push_back(cudf::test::structs_column_wrapper({name_cols[3], age_cols[3], is_human_cols[3]}, {true, false})); diff --git a/cpp/tests/copying/scatter_tests.cpp b/cpp/tests/copying/scatter_tests.cpp index b23ecdcee24f..e3f3450e6606 100644 --- a/cpp/tests/copying/scatter_tests.cpp +++ b/cpp/tests/copying/scatter_tests.cpp @@ -220,7 +220,7 @@ TYPED_TEST(ScatterDataTypeTests, EmptyScatterMap) cudf::test::fixed_width_column_wrapper source({1, 2, 3, 4, 5, 6}); cudf::test::fixed_width_column_wrapper target( {10, 20, 30, 40, 50, 60, 70, 80}); - cudf::test::fixed_width_column_wrapper scatter_map({}); + cudf::test::fixed_width_column_wrapper scatter_map{}; auto const source_table = cudf::table_view({source, source}); auto const target_table = cudf::table_view({target, target}); @@ -241,7 +241,7 @@ TYPED_TEST(ScatterDataTypeTests, EmptyScalarScatterMap) cudf::test::fixed_width_column_wrapper target( {10, 20, 30, 40, 50, 60, 70, 80}); - cudf::test::fixed_width_column_wrapper scatter_map({}); + cudf::test::fixed_width_column_wrapper scatter_map{}; auto const target_table = cudf::table_view({target}); diff --git a/cpp/tests/encode/encode_tests.cpp b/cpp/tests/encode/encode_tests.cpp index 25f38fa89b71..246caae0eab7 100644 --- a/cpp/tests/encode/encode_tests.cpp +++ b/cpp/tests/encode/encode_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #include @@ -31,8 +31,8 @@ TYPED_TEST(EncodeNumericTests, SingleNullEncode) TYPED_TEST(EncodeNumericTests, EmptyEncode) { - cudf::test::fixed_width_column_wrapper input({}); - cudf::test::fixed_width_column_wrapper expect({}); + cudf::test::fixed_width_column_wrapper input{}; + cudf::test::fixed_width_column_wrapper expect{}; auto const result = cudf::encode(cudf::table_view({input})); CUDF_TEST_EXPECT_COLUMNS_EQUAL(result.second->view(), expect); diff --git a/cpp/tests/filling/sequence_tests.cpp b/cpp/tests/filling/sequence_tests.cpp index 7ec3188a6ae4..0b115e10513d 100644 --- a/cpp/tests/filling/sequence_tests.cpp +++ b/cpp/tests/filling/sequence_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -62,7 +62,7 @@ TYPED_TEST(SequenceTypedTestFixture, EmptyOutput) cudf::size_type num_els = 0; - cudf::test::fixed_width_column_wrapper expected_w({}); + cudf::test::fixed_width_column_wrapper expected_w{}; auto result = cudf::sequence(num_els, init, step); diff --git a/cpp/tests/interop/dlpack_test.cpp b/cpp/tests/interop/dlpack_test.cpp index a3d0234b7c0d..8a3f06ecdf74 100644 --- a/cpp/tests/interop/dlpack_test.cpp +++ b/cpp/tests/interop/dlpack_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2024, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #include @@ -63,8 +63,8 @@ TEST_F(DLPackUntypedTests, EmptyTableToDlpack) TEST_F(DLPackUntypedTests, EmptyColsToDlpack) { - cudf::test::fixed_width_column_wrapper col1({}); - cudf::test::fixed_width_column_wrapper col2({}); + cudf::test::fixed_width_column_wrapper col1{}; + cudf::test::fixed_width_column_wrapper col2{}; cudf::table_view input({col1, col2}); unique_managed_tensor tensor(cudf::to_dlpack(input)); validate_dtype(tensor->dl_tensor.dtype); diff --git a/cpp/tests/io/cudftable_test.cpp b/cpp/tests/io/cudftable_test.cpp index 63859cb99d30..96ecf94eb707 100644 --- a/cpp/tests/io/cudftable_test.cpp +++ b/cpp/tests/io/cudftable_test.cpp @@ -108,7 +108,7 @@ TEST_F(CudftableTest, MultiColumnFixedWidth) TEST_F(CudftableTest, EmptyColumn) { - cudf::test::fixed_width_column_wrapper empty_col({}); + cudf::test::fixed_width_column_wrapper empty_col{}; auto const expected = cudf::table_view{{empty_col}}; run_test(expected); diff --git a/cpp/tests/partitioning/hash_partition_test.cpp b/cpp/tests/partitioning/hash_partition_test.cpp index 0a9d4f4992fc..45bdf877c43b 100644 --- a/cpp/tests/partitioning/hash_partition_test.cpp +++ b/cpp/tests/partitioning/hash_partition_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #include @@ -90,8 +90,8 @@ TEST_F(HashPartition, ZeroPartitions) TEST_F(HashPartition, ZeroRows) { - fixed_width_column_wrapper floats({}); - fixed_width_column_wrapper integers({}); + fixed_width_column_wrapper floats{}; + fixed_width_column_wrapper integers{}; strings_column_wrapper strings; auto input = cudf::table_view({floats, integers, strings}); diff --git a/cpp/tests/quantiles/quantile_test.cpp b/cpp/tests/quantiles/quantile_test.cpp index 2096fc2e4ce9..21faae40ba7d 100644 --- a/cpp/tests/quantiles/quantile_test.cpp +++ b/cpp/tests/quantiles/quantile_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -413,7 +413,7 @@ TYPED_TEST(QuantileTest, TestInterpolateExtremaLow) TYPED_TEST(QuantileTest, TestEmpty) { - auto input = cudf::test::fixed_width_column_wrapper({}); + auto input = cudf::test::fixed_width_column_wrapper(); auto expected = cudf::test::fixed_width_column_wrapper({0, 0}, {false, false}); auto actual = cudf::quantile(input, {0.5, 0.25}); } @@ -429,7 +429,7 @@ TYPED_TEST_SUITE(QuantileUnsupportedTypesTest, UnsupportedTestTypes); TYPED_TEST(QuantileUnsupportedTypesTest, TestZeroElements) { - cudf::test::fixed_width_column_wrapper input({}); + cudf::test::fixed_width_column_wrapper input{}; EXPECT_THROW(cudf::quantile(input, {0}), cudf::logic_error); } diff --git a/cpp/tests/quantiles/quantiles_test.cpp b/cpp/tests/quantiles/quantiles_test.cpp index 08cba6cf18ce..e8bc44de1fc2 100644 --- a/cpp/tests/quantiles/quantiles_test.cpp +++ b/cpp/tests/quantiles/quantiles_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2024, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -33,7 +33,7 @@ TYPED_TEST(QuantilesTest, TestMultiColumnZeroRows) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper input_a({}); + cudf::test::fixed_width_column_wrapper input_a{}; auto input = cudf::table_view({input_a}); EXPECT_THROW(cudf::quantiles(input, {0.0f}), cudf::logic_error); @@ -56,8 +56,8 @@ TYPED_TEST(QuantilesTest, TestMultiColumnOrderCountMismatch) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper input_a({}); - cudf::test::fixed_width_column_wrapper input_b({}); + cudf::test::fixed_width_column_wrapper input_a{}; + cudf::test::fixed_width_column_wrapper input_b{}; auto input = cudf::table_view({input_a}); EXPECT_THROW(cudf::quantiles(input, @@ -73,8 +73,8 @@ TYPED_TEST(QuantilesTest, TestMultiColumnNullOrderCountMismatch) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper input_a({}); - cudf::test::fixed_width_column_wrapper input_b({}); + cudf::test::fixed_width_column_wrapper input_a{}; + cudf::test::fixed_width_column_wrapper input_b{}; auto input = cudf::table_view({input_a}); EXPECT_THROW(cudf::quantiles(input, @@ -90,8 +90,8 @@ TYPED_TEST(QuantilesTest, TestMultiColumnArithmeticInterpolation) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper input_a({}); - cudf::test::fixed_width_column_wrapper input_b({}); + cudf::test::fixed_width_column_wrapper input_a{}; + cudf::test::fixed_width_column_wrapper input_b{}; auto input = cudf::table_view({input_a}); EXPECT_THROW(cudf::quantiles(input, {0.0f}, cudf::interpolation::LINEAR), std::invalid_argument); diff --git a/cpp/tests/reductions/scan_tests.cpp b/cpp/tests/reductions/scan_tests.cpp index 64493c818f3f..2caf981c7de9 100644 --- a/cpp/tests/reductions/scan_tests.cpp +++ b/cpp/tests/reductions/scan_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -386,8 +386,8 @@ TYPED_TEST_SUITE(ScanEmptyTest, cudf::test::NumericTypes); TYPED_TEST(ScanEmptyTest, MinInclusive) { - cudf::test::fixed_width_column_wrapper col({}); - cudf::test::fixed_width_column_wrapper expected({}); + cudf::test::fixed_width_column_wrapper col{}; + cudf::test::fixed_width_column_wrapper expected{}; auto result = cudf::scan( col, *cudf::make_min_aggregation(), cudf::scan_type::INCLUSIVE); @@ -396,8 +396,8 @@ TYPED_TEST(ScanEmptyTest, MinInclusive) TYPED_TEST(ScanEmptyTest, MinExclusive) { - cudf::test::fixed_width_column_wrapper col({}); - cudf::test::fixed_width_column_wrapper expected({}); + cudf::test::fixed_width_column_wrapper col{}; + cudf::test::fixed_width_column_wrapper expected{}; auto result = cudf::scan( col, *cudf::make_min_aggregation(), cudf::scan_type::EXCLUSIVE); diff --git a/cpp/tests/replace/clamp_test.cpp b/cpp/tests/replace/clamp_test.cpp index 2a198d3b18bb..81c15ad8b360 100644 --- a/cpp/tests/replace/clamp_test.cpp +++ b/cpp/tests/replace/clamp_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -116,7 +116,7 @@ TEST_F(ClampEmptyCaseTest, EmptyInput) auto hi = cudf::make_numeric_scalar(cudf::data_type(cudf::type_id::INT32)); hi->set_valid_async(true); - cudf::test::fixed_width_column_wrapper input({}); + cudf::test::fixed_width_column_wrapper input{}; auto got = cudf::clamp(input, *lo, *hi); diff --git a/cpp/tests/replace/replace_nulls_tests.cpp b/cpp/tests/replace/replace_nulls_tests.cpp index 7f15fef2c270..ead5f233a788 100644 --- a/cpp/tests/replace/replace_nulls_tests.cpp +++ b/cpp/tests/replace/replace_nulls_tests.cpp @@ -1,7 +1,7 @@ /* * SPDX-FileCopyrightText: Copyright 2018 BlazingDB, Inc. * SPDX-FileCopyrightText: Copyright 2018 Alexander Ocsa - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ /* @@ -663,7 +663,7 @@ TEST_F(ReplaceDictionaryTest, ReplaceNullsError) TEST_F(ReplaceDictionaryTest, ReplaceNullsEmpty) { - cudf::test::fixed_width_column_wrapper input_empty_w({}); + cudf::test::fixed_width_column_wrapper input_empty_w{}; auto input_empty = cudf::dictionary::encode(input_empty_w); auto result = cudf::replace_nulls(input_empty->view(), input_empty->view()); CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(result->view(), input_empty->view()); diff --git a/cpp/tests/replace/replace_tests.cpp b/cpp/tests/replace/replace_tests.cpp index 3c0185a46fd1..1ee6d2f006e9 100644 --- a/cpp/tests/replace/replace_tests.cpp +++ b/cpp/tests/replace/replace_tests.cpp @@ -615,7 +615,7 @@ TEST_F(ReplaceDictionaryTest, EmptyReplacement) cudf::test::fixed_width_column_wrapper input_w( {1.0, 2.0, 1.0, 2.0, 0.0, 3.0, 4.0, 4.0, 3.0}, {1, 1, 1, 1, 0, 1, 1, 1, 1}); auto input = cudf::dictionary::encode(input_w); - cudf::test::fixed_width_column_wrapper empty_w({}); + cudf::test::fixed_width_column_wrapper empty_w{}; auto empty = cudf::dictionary::encode(empty_w); auto result = cudf::find_and_replace_all(input->view(), empty->view(), empty->view()); diff --git a/cpp/tests/reshape/interleave_columns_tests.cpp b/cpp/tests/reshape/interleave_columns_tests.cpp index 66dc44a8e790..1b32f8519bc8 100644 --- a/cpp/tests/reshape/interleave_columns_tests.cpp +++ b/cpp/tests/reshape/interleave_columns_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -88,11 +88,11 @@ TYPED_TEST(InterleaveColumnsTest, OneColumnEmpty) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper a({}); + cudf::test::fixed_width_column_wrapper a{}; cudf::table_view in(std::vector{a}); - auto expected = cudf::test::fixed_width_column_wrapper({}); + auto expected = cudf::test::fixed_width_column_wrapper(); auto actual = cudf::interleave_columns(in); CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, actual->view()); @@ -102,13 +102,13 @@ TYPED_TEST(InterleaveColumnsTest, ThreeColumnsEmpty) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper a({}); - cudf::test::fixed_width_column_wrapper b({}); - cudf::test::fixed_width_column_wrapper c({}); + cudf::test::fixed_width_column_wrapper a{}; + cudf::test::fixed_width_column_wrapper b{}; + cudf::test::fixed_width_column_wrapper c{}; cudf::table_view in(std::vector{a, b, c}); - auto expected = cudf::test::fixed_width_column_wrapper({}); + auto expected = cudf::test::fixed_width_column_wrapper(); auto actual = cudf::interleave_columns(in); CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, actual->view()); diff --git a/cpp/tests/reshape/table_to_array_tests.cpp b/cpp/tests/reshape/table_to_array_tests.cpp index 89e7a72334db..9009d36cb560 100644 --- a/cpp/tests/reshape/table_to_array_tests.cpp +++ b/cpp/tests/reshape/table_to_array_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -180,7 +180,7 @@ TEST(TableToDeviceArrayTest, NoRows) { auto stream = cudf::get_default_stream(); - cudf::test::fixed_width_column_wrapper col({}); + cudf::test::fixed_width_column_wrapper col{}; cudf::table_view input_table({col}); rmm::device_buffer output(0, stream); diff --git a/cpp/tests/reshape/tile_tests.cpp b/cpp/tests/reshape/tile_tests.cpp index 50be2837d4c6..63424dc6fda7 100644 --- a/cpp/tests/reshape/tile_tests.cpp +++ b/cpp/tests/reshape/tile_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2024, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -32,7 +32,7 @@ TYPED_TEST(TileTest, NoRows) { using T = TypeParam; - cudf::test::fixed_width_column_wrapper in_a({}); + cudf::test::fixed_width_column_wrapper in_a{}; cudf::table_view in(std::vector{in_a}); auto expected = in; diff --git a/cpp/tests/rolling/grouped_rolling_test.cpp b/cpp/tests/rolling/grouped_rolling_test.cpp index b568a909ff0e..e0bebb6b86ea 100644 --- a/cpp/tests/rolling/grouped_rolling_test.cpp +++ b/cpp/tests/rolling/grouped_rolling_test.cpp @@ -420,7 +420,7 @@ class GroupedRollingTest : public cudf::test::BaseFixture { std::conditional_t, int64_t, T>, false>( input, group_offsets, preceding_window, following_window, min_periods); - default: return cudf::test::fixed_width_column_wrapper({}).release(); + default: return cudf::test::fixed_width_column_wrapper().release(); } } }; @@ -1156,7 +1156,7 @@ class GroupedTimeRangeRollingTest : public cudf::test::BaseFixture { preceding_window, following_window, min_periods); - default: return cudf::test::fixed_width_column_wrapper({}).release(); + default: return cudf::test::fixed_width_column_wrapper().release(); } } }; diff --git a/cpp/tests/rolling/rolling_test.cpp b/cpp/tests/rolling/rolling_test.cpp index a2f178499388..a3a76eacd2ea 100644 --- a/cpp/tests/rolling/rolling_test.cpp +++ b/cpp/tests/rolling/rolling_test.cpp @@ -601,7 +601,7 @@ class RollingTest : public cudf::test::BaseFixture { std::conditional_t(), T, double>, true>( input, preceding_window, following_window, min_periods); - default: return cudf::test::fixed_width_column_wrapper({}).release(); + default: return cudf::test::fixed_width_column_wrapper().release(); } } }; diff --git a/cpp/tests/row_operator/row_operator_tests.cu b/cpp/tests/row_operator/row_operator_tests.cu index 08046c5e3128..89286299ba6e 100644 --- a/cpp/tests/row_operator/row_operator_tests.cu +++ b/cpp/tests/row_operator/row_operator_tests.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -24,7 +24,7 @@ #include template -struct TypedTableViewTest : public cudf::test::BaseFixture {}; +struct TypedTableViewTest : public cudf::test::BaseFixtureWithHarness {}; using NumericTypesNotBool = cudf::test::Concat; @@ -33,66 +33,101 @@ TYPED_TEST_SUITE(TypedTableViewTest, NumericTypesNotBool); template std::unique_ptr self_comparison(cudf::table_view input, std::vector const& column_order, - PhysicalElementComparator comparator); + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr two_table_comparison(cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - PhysicalElementComparator comparator); + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr two_table_equality(cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - PhysicalElementComparator comparator); + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr sorted_order( std::shared_ptr preprocessed_input, cudf::size_type num_rows, bool has_nested, PhysicalElementComparator comparator, - rmm::cuda_stream_view stream); + rmm::cuda_stream_view stream, + cudf::memory_resources mr); TYPED_TEST(TypedTableViewTest, TestLexicographicalComparatorTwoTables) { using T = TypeParam; - auto const col1 = cudf::test::fixed_width_column_wrapper{{1, 2, 3, 4}}; - auto const col2 = cudf::test::fixed_width_column_wrapper{{0, 1, 4, 3}}; + // TODO: lexicographic row operators still allocate from the current device resource. + this->disable_current_device_resource_use(); + + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col1 = cudf::test::fixed_width_column_wrapper{{1, 2, 3, 4}, stream, mr}; + auto const col2 = cudf::test::fixed_width_column_wrapper{{0, 1, 4, 3}, stream, mr}; auto const column_order = std::vector{cudf::order::DESCENDING}; auto const lhs = cudf::table_view{{col1}}; auto const rhs = cudf::table_view{{col2}}; - auto const expected = cudf::test::fixed_width_column_wrapper{{1, 1, 0, 1}}; - auto const got = two_table_comparison( - lhs, rhs, column_order, cudf::detail::row::lexicographic::physical_element_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, got->view()); + auto const expected = cudf::test::fixed_width_column_wrapper{{1, 1, 0, 1}, stream, mr}; + auto const got = + two_table_comparison(lhs, + rhs, + column_order, + cudf::detail::row::lexicographic::physical_element_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); auto const sorting_got = two_table_comparison(lhs, rhs, column_order, - cudf::detail::row::lexicographic::sorting_physical_element_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, sorting_got->view()); + cudf::detail::row::lexicographic::sorting_physical_element_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, sorting_got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TYPED_TEST(TypedTableViewTest, TestLexicographicalComparatorSameTable) { using T = TypeParam; - auto const col1 = cudf::test::fixed_width_column_wrapper{{1, 2, 3, 4}}; + // TODO: lexicographic row operators still allocate from the current device resource. + this->disable_current_device_resource_use(); + + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col1 = cudf::test::fixed_width_column_wrapper{{1, 2, 3, 4}, stream, mr}; auto const column_order = std::vector{cudf::order::DESCENDING}; auto const input_table = cudf::table_view{{col1}}; - auto const expected = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0}}; - auto const got = self_comparison( - input_table, column_order, cudf::detail::row::lexicographic::physical_element_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, got->view()); + auto const expected = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0}, stream, mr}; + auto const got = self_comparison(input_table, + column_order, + cudf::detail::row::lexicographic::physical_element_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); auto const sorting_got = self_comparison(input_table, column_order, - cudf::detail::row::lexicographic::sorting_physical_element_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, sorting_got->view()); + cudf::detail::row::lexicographic::sorting_physical_element_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, sorting_got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TYPED_TEST(TypedTableViewTest, TestSortSameTableFromTwoTables) @@ -100,23 +135,29 @@ TYPED_TEST(TypedTableViewTest, TestSortSameTableFromTwoTables) using data_col = cudf::test::fixed_width_column_wrapper; using int32s_col = cudf::test::fixed_width_column_wrapper; - auto const col1 = data_col{5, 2, 7, 1, 3}; - auto const col2 = data_col{}; // empty + // TODO: lexicographic row operators still allocate from the current device resource. + this->disable_current_device_resource_use(); + + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col1 = data_col{{5, 2, 7, 1, 3}, stream, mr}; + auto const col2 = data_col{stream, mr}; // empty auto const lhs = cudf::table_view{{col1}}; auto const empty_rhs = cudf::table_view{{col2}}; - auto const stream = cudf::get_default_stream(); auto const test_sort = - [stream]( + [stream, mr]( auto const& preprocessed, auto const& input, auto const& comparator, auto const& expected) { auto const order = sorted_order( - preprocessed, input.num_rows(), cudf::has_nested_columns(input), comparator, stream); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, order->view()); + preprocessed, input.num_rows(), cudf::has_nested_columns(input), comparator, stream, mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, order->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); }; auto const test_sort_two_tables = [&](auto const& preprocessed_lhs, auto const& preprocessed_empty_rhs) { - auto const expected_lhs = int32s_col{3, 1, 4, 0, 2}; + auto const expected_lhs = int32s_col{{3, 1, 4, 0, 2}, stream, mr}; test_sort(preprocessed_lhs, lhs, cudf::detail::row::lexicographic::physical_element_comparator{}, @@ -126,7 +167,7 @@ TYPED_TEST(TypedTableViewTest, TestSortSameTableFromTwoTables) cudf::detail::row::lexicographic::sorting_physical_element_comparator{}, expected_lhs); - auto const expected_empty_rhs = int32s_col{}; + auto const expected_empty_rhs = int32s_col{stream, mr}; test_sort(preprocessed_empty_rhs, empty_rhs, cudf::detail::row::lexicographic::physical_element_comparator{}, @@ -161,46 +202,53 @@ TYPED_TEST(TypedTableViewTest, TestSortSameTableFromTwoTablesWithListsOfStructs) using strings_col = cudf::test::strings_column_wrapper; using structs_col = cudf::test::structs_column_wrapper; - auto const col1 = [] { - auto const get_structs = [] { - auto child0 = data_col{0, 3, 0, 2}; - auto child1 = strings_col{"a", "c", "a", "b"}; - return structs_col{{child0, child1}}; + // TODO: lexicographic row operators still allocate from the current device resource. + this->disable_current_device_resource_use(); + + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col1 = [&] { + auto const get_structs = [&] { + auto child0 = data_col{{0, 3, 0, 2}, stream, mr}; + auto child1 = strings_col{{"a", "c", "a", "b"}, stream, mr}; + return structs_col{{child0, child1}, {}, stream, mr}; }; return cudf::make_lists_column( - 2, int32s_col{0, 2, 4}.release(), get_structs().release(), 0, {}); + 2, int32s_col{{0, 2, 4}, stream, mr}.release(), get_structs().release(), 0, {}); }(); - auto const col2 = [] { - auto const get_structs = [] { - auto child0 = data_col{}; - auto child1 = strings_col{}; - return structs_col{{child0, child1}}; + auto const col2 = [&] { + auto const get_structs = [&] { + auto child0 = data_col{stream, mr}; + auto child1 = strings_col{stream, mr}; + return structs_col{{child0, child1}, {}, stream, mr}; }; - return cudf::make_lists_column(0, int32s_col{}.release(), get_structs().release(), 0, {}); + return cudf::make_lists_column( + 0, int32s_col{stream, mr}.release(), get_structs().release(), 0, {}); }(); auto const column_order = std::vector{cudf::order::ASCENDING}; auto const lhs = cudf::table_view{{*col1}}; auto const empty_rhs = cudf::table_view{{*col2}}; - auto const stream = cudf::get_default_stream(); auto const test_sort = - [stream]( + [stream, mr]( auto const& preprocessed, auto const& input, auto const& comparator, auto const& expected) { auto const order = sorted_order( - preprocessed, input.num_rows(), cudf::has_nested_columns(input), comparator, stream); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, order->view()); + preprocessed, input.num_rows(), cudf::has_nested_columns(input), comparator, stream, mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, order->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); }; auto const test_sort_two_tables = [&](auto const& preprocessed_lhs, auto const& preprocessed_empty_rhs) { - auto const expected_lhs = int32s_col{1, 0}; + auto const expected_lhs = int32s_col{{1, 0}, stream, mr}; test_sort(preprocessed_lhs, lhs, cudf::detail::row::lexicographic::sorting_physical_element_comparator{}, expected_lhs); - auto const expected_empty_rhs = int32s_col{}; + auto const expected_empty_rhs = int32s_col{stream, mr}; test_sort(preprocessed_empty_rhs, empty_rhs, cudf::detail::row::lexicographic::sorting_physical_element_comparator{}, @@ -236,7 +284,7 @@ TYPED_TEST(TypedTableViewTest, TestSortSameTableFromTwoTablesWithListsOfStructs) } template -struct NaNTableViewTest : public cudf::test::BaseFixture {}; +struct NaNTableViewTest : public cudf::test::BaseFixtureWithHarness {}; TYPED_TEST_SUITE(NaNTableViewTest, cudf::test::FloatingPointTypes); @@ -244,65 +292,104 @@ TYPED_TEST(NaNTableViewTest, TestLexicographicalComparatorTwoTableNaNCase) { using T = TypeParam; - auto const col1 = cudf::test::fixed_width_column_wrapper{{T(NAN), T(NAN), T(1), T(1)}}; - auto const col2 = cudf::test::fixed_width_column_wrapper{{T(NAN), T(1), T(NAN), T(1)}}; + // TODO: lexicographic row operators still allocate from the current device resource. + this->disable_current_device_resource_use(); + + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col1 = + cudf::test::fixed_width_column_wrapper{{T(NAN), T(NAN), T(1), T(1)}, stream, mr}; + auto const col2 = + cudf::test::fixed_width_column_wrapper{{T(NAN), T(1), T(NAN), T(1)}, stream, mr}; auto const column_order = std::vector{cudf::order::DESCENDING}; auto const lhs = cudf::table_view{{col1}}; auto const rhs = cudf::table_view{{col2}}; - auto const expected = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0}}; - auto const got = two_table_comparison( - lhs, rhs, column_order, cudf::detail::row::lexicographic::physical_element_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, got->view()); - - auto const sorting_expected = cudf::test::fixed_width_column_wrapper{{0, 1, 0, 0}}; + auto const expected = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0}, stream, mr}; + auto const got = + two_table_comparison(lhs, + rhs, + column_order, + cudf::detail::row::lexicographic::physical_element_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); + + auto const sorting_expected = + cudf::test::fixed_width_column_wrapper{{0, 1, 0, 0}, stream, mr}; auto const sorting_got = two_table_comparison(lhs, rhs, column_order, - cudf::detail::row::lexicographic::sorting_physical_element_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(sorting_expected, sorting_got->view()); + cudf::detail::row::lexicographic::sorting_physical_element_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + sorting_expected, sorting_got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TYPED_TEST(NaNTableViewTest, TestEqualityComparatorTwoTableNaNCase) { using T = TypeParam; - auto const col1 = cudf::test::fixed_width_column_wrapper{{T(NAN), T(NAN), T(1), T(1)}}; - auto const col2 = cudf::test::fixed_width_column_wrapper{{T(NAN), T(1), T(NAN), T(1)}}; + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col1 = + cudf::test::fixed_width_column_wrapper{{T(NAN), T(NAN), T(1), T(1)}, stream, mr}; + auto const col2 = + cudf::test::fixed_width_column_wrapper{{T(NAN), T(1), T(NAN), T(1)}, stream, mr}; auto const column_order = std::vector{cudf::order::DESCENDING}; auto const lhs = cudf::table_view{{col1}}; auto const rhs = cudf::table_view{{col2}}; - auto const expected = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 1}}; - auto const got = two_table_equality( - lhs, rhs, column_order, cudf::detail::row::equality::physical_equality_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, got->view()); - - auto const nan_equal_expected = cudf::test::fixed_width_column_wrapper{{1, 0, 0, 1}}; - auto const nan_equal_got = two_table_equality( - lhs, rhs, column_order, cudf::detail::row::equality::nan_equal_physical_equality_comparator{}); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(nan_equal_expected, nan_equal_got->view()); + auto const expected = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 1}, stream, mr}; + auto const got = two_table_equality(lhs, + rhs, + column_order, + cudf::detail::row::equality::physical_equality_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + expected, got->view(), cudf::test::debug_output_level::FIRST_ERROR, stream, mr); + + auto const nan_equal_expected = + cudf::test::fixed_width_column_wrapper{{1, 0, 0, 1}, stream, mr}; + auto const nan_equal_got = + two_table_equality(lhs, + rhs, + column_order, + cudf::detail::row::equality::nan_equal_physical_equality_comparator{}, + stream, + mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL(nan_equal_expected, + nan_equal_got->view(), + cudf::test::debug_output_level::FIRST_ERROR, + stream, + mr); } -struct RowOperatorTest : public cudf::test::BaseFixture {}; +struct RowOperatorTest : public cudf::test::BaseFixtureWithHarness {}; TEST_F(RowOperatorTest, TestTwoTableComparatorColumnCountCheck) { - rmm::cuda_stream_view stream{cudf::get_default_stream()}; + auto const stream = this->stream(); + auto const mr = this->resources(); - auto left_col1 = cudf::test::fixed_width_column_wrapper{{1, 2}}; - auto left_col2 = cudf::test::fixed_width_column_wrapper{{3, 4}}; + auto left_col1 = cudf::test::fixed_width_column_wrapper{{1, 2}, stream, mr}; + auto left_col2 = cudf::test::fixed_width_column_wrapper{{3, 4}, stream, mr}; auto const left_table = cudf::table_view{{left_col1, left_col2}}; - auto right_col = cudf::test::fixed_width_column_wrapper{{1, 2}}; + auto right_col = cudf::test::fixed_width_column_wrapper{{1, 2}, stream, mr}; auto const right_table = cudf::table_view{{right_col}}; auto left_preprocessed = - cudf::detail::row::equality::preprocessed_table::create(left_table, stream); + cudf::detail::row::equality::preprocessed_table::create(left_table, stream, mr); auto right_preprocessed = - cudf::detail::row::equality::preprocessed_table::create(right_table, stream); + cudf::detail::row::equality::preprocessed_table::create(right_table, stream, mr); EXPECT_THROW( cudf::detail::row::equality::two_table_comparator(left_preprocessed, right_preprocessed), @@ -311,48 +398,53 @@ TEST_F(RowOperatorTest, TestTwoTableComparatorColumnCountCheck) TEST_F(RowOperatorTest, TestCheckShapeCompatibility) { - rmm::cuda_stream_view stream{cudf::get_default_stream()}; + auto const stream = this->stream(); + auto const mr = this->resources(); - auto left_col1_2 = cudf::test::fixed_width_column_wrapper{{1, 2}}; - auto left_col2_2 = cudf::test::fixed_width_column_wrapper{{3, 4}}; + auto left_col1_2 = cudf::test::fixed_width_column_wrapper{{1, 2}, stream, mr}; + auto left_col2_2 = cudf::test::fixed_width_column_wrapper{{3, 4}, stream, mr}; auto const left_table = cudf::table_view{{left_col1_2, left_col2_2}}; - auto right_col_2 = cudf::test::fixed_width_column_wrapper{{1, 2}}; + auto right_col_2 = cudf::test::fixed_width_column_wrapper{{1, 2}, stream, mr}; auto const right_table = cudf::table_view{{right_col_2}}; - EXPECT_THROW(cudf::detail::row::equality::two_table_comparator(left_table, right_table, stream), - std::invalid_argument); + EXPECT_THROW( + cudf::detail::row::equality::two_table_comparator(left_table, right_table, stream, mr), + std::invalid_argument); - auto int_col = cudf::test::fixed_width_column_wrapper{{1, 2}}; + auto int_col = cudf::test::fixed_width_column_wrapper{{1, 2}, stream, mr}; auto const int_table = cudf::table_view{{int_col}}; - auto float_col = cudf::test::fixed_width_column_wrapper{{1.0f, 2.0f}}; + auto float_col = cudf::test::fixed_width_column_wrapper{{1.0f, 2.0f}, stream, mr}; auto const float_table = cudf::table_view{{float_col}}; - EXPECT_THROW(cudf::detail::row::equality::two_table_comparator(int_table, float_table, stream), - std::invalid_argument); + EXPECT_THROW( + cudf::detail::row::equality::two_table_comparator(int_table, float_table, stream, mr), + std::invalid_argument); - auto str_col = cudf::test::strings_column_wrapper({"hello", "world"}); + auto str_col = cudf::test::strings_column_wrapper({"hello", "world"}, stream, mr); auto const string_table = cudf::table_view{{str_col}}; - auto num_col = cudf::test::fixed_width_column_wrapper({1, 2}); + auto num_col = cudf::test::fixed_width_column_wrapper({1, 2}, stream, mr); auto const numeric_table = cudf::table_view{{num_col}}; EXPECT_THROW( - cudf::detail::row::equality::two_table_comparator(string_table, numeric_table, stream), + cudf::detail::row::equality::two_table_comparator(string_table, numeric_table, stream, mr), std::invalid_argument); } TEST_F(RowOperatorTest, TestRowHasher64BitHash) { - auto const col = cudf::test::fixed_width_column_wrapper{{0, 42, 123456789}}; + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col = cudf::test::fixed_width_column_wrapper{{0, 42, 123456789}, stream, mr}; auto const input = cudf::table_view{{col}}; - auto const stream = cudf::get_default_stream(); - auto const preprocessed = cudf::detail::row::hash::preprocessed_table::create(input, stream); + auto const preprocessed = cudf::detail::row::hash::preprocessed_table::create(input, stream, mr); auto const row_hasher = cudf::detail::row::hash::row_hasher{preprocessed}; auto const hasher = row_hasher.device_hasher(cudf::nullate::DYNAMIC{false}); - auto results = cudf::test::fixed_width_column_wrapper{{0, 0, 0}}; - thrust::transform(rmm::exec_policy_nosync(stream), + auto results = cudf::test::fixed_width_column_wrapper{{0, 0, 0}, stream, mr}; + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{3}, cudf::mutable_column_view{results}.begin(), @@ -361,24 +453,27 @@ TEST_F(RowOperatorTest, TestRowHasher64BitHash) // Expected values match cuCollections xxhash_64 reference implementation // https://github.com/NVIDIA/cuCollections/blob/4f03dcccb3a944594c693aa8cebc89302bbd8e20/tests/utility/hash_test.cu#L134-L137 auto const expected = cudf::test::fixed_width_column_wrapper{ - {4246796580750024372ul, 15516826743637085169ul, 9462334144942111946ul}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results, expected); + {4246796580750024372ul, 15516826743637085169ul, 9462334144942111946ul}, stream, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results, expected, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TEST_F(RowOperatorTest, TestPrimitiveRowHasher64BitHash) { - auto const col = cudf::test::fixed_width_column_wrapper{{0, 42, 123456789}}; + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const col = cudf::test::fixed_width_column_wrapper{{0, 42, 123456789}, stream, mr}; auto const input = cudf::table_view{{col}}; - auto const stream = cudf::get_default_stream(); - auto const d_input = cudf::table_device_view::create(input, stream); + auto const d_input = cudf::table_device_view::create(input, stream, mr.get_temporary_mr()); auto const hasher = cudf::detail::row::primitive::row_hasher( cudf::nullate::DYNAMIC{false}, *d_input, static_cast(cudf::DEFAULT_HASH_SEED)); - auto results = cudf::test::fixed_width_column_wrapper{{0, 0, 0}}; + auto results = cudf::test::fixed_width_column_wrapper{{0, 0, 0}, stream, mr}; - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{3}, cudf::mutable_column_view{results}.begin(), @@ -387,77 +482,89 @@ TEST_F(RowOperatorTest, TestPrimitiveRowHasher64BitHash) // Expected values match cuCollections xxhash_64 reference implementation // https://github.com/NVIDIA/cuCollections/blob/4f03dcccb3a944594c693aa8cebc89302bbd8e20/tests/utility/hash_test.cu#L134-L137 auto const expected = cudf::test::fixed_width_column_wrapper{ - {4246796580750024372ul, 15516826743637085169ul, 9462334144942111946ul}}; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(results, expected); + {4246796580750024372ul, 15516826743637085169ul, 9462334144942111946ul}, stream, mr}; + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + results, expected, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TEST_F(RowOperatorTest, TestRowHasherDictionaryColumn) { + auto const stream = this->stream(); + auto const mr = this->resources(); + // Dictionary and equivalent string column should produce identical hashes. // This also verifies same logical values get same hashes (e.g., "baz" at rows 0 and 2). - auto const dict_col = - cudf::test::dictionary_column_wrapper({"baz", "foo", "baz", "bar", "foo"}); - auto const str_col = cudf::test::strings_column_wrapper({"baz", "foo", "baz", "bar", "foo"}); + auto const dict_col = cudf::test::dictionary_column_wrapper( + {"baz", "foo", "baz", "bar", "foo"}, stream, mr); + auto const str_col = + cudf::test::strings_column_wrapper({"baz", "foo", "baz", "bar", "foo"}, stream, mr); - auto const stream = cudf::get_default_stream(); auto const dict_row_hasher = - cudf::detail::row::hash::row_hasher(cudf::table_view{{dict_col}}, stream); + cudf::detail::row::hash::row_hasher(cudf::table_view{{dict_col}}, stream, mr); auto const str_row_hasher = - cudf::detail::row::hash::row_hasher(cudf::table_view{{str_col}}, stream); + cudf::detail::row::hash::row_hasher(cudf::table_view{{str_col}}, stream, mr); auto const dict_hasher = dict_row_hasher.device_hasher(cudf::nullate::DYNAMIC{false}); auto const str_hasher = str_row_hasher.device_hasher(cudf::nullate::DYNAMIC{false}); - auto dict_results = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}}; - auto str_results = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}}; + auto dict_results = + cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}, stream, mr}; + auto str_results = + cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}, stream, mr}; - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{5}, cudf::mutable_column_view{dict_results}.begin(), dict_hasher); - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{5}, cudf::mutable_column_view{str_results}.begin(), str_hasher); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(dict_results, str_results); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + dict_results, str_results, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TEST_F(RowOperatorTest, TestRowHasherDictionaryColumnWithNulls) { - auto const dict_col = - cudf::test::dictionary_column_wrapper({100, 200, 300, 100, 200}, {1, 0, 1, 0, 1}); - auto const int_col = - cudf::test::fixed_width_column_wrapper({100, 200, 300, 100, 200}, {1, 0, 1, 0, 1}); + auto const stream = this->stream(); + auto const mr = this->resources(); + + auto const dict_col = cudf::test::dictionary_column_wrapper( + {100, 200, 300, 100, 200}, {1, 0, 1, 0, 1}, stream, mr); + auto const int_col = cudf::test::fixed_width_column_wrapper( + {100, 200, 300, 100, 200}, {1, 0, 1, 0, 1}, stream, mr); - auto const stream = cudf::get_default_stream(); auto const dict_row_hasher = - cudf::detail::row::hash::row_hasher(cudf::table_view{{dict_col}}, stream); + cudf::detail::row::hash::row_hasher(cudf::table_view{{dict_col}}, stream, mr); auto const int_row_hasher = - cudf::detail::row::hash::row_hasher(cudf::table_view{{int_col}}, stream); + cudf::detail::row::hash::row_hasher(cudf::table_view{{int_col}}, stream, mr); auto const dict_hasher = dict_row_hasher.device_hasher(cudf::nullate::DYNAMIC{true}); auto const int_hasher = int_row_hasher.device_hasher(cudf::nullate::DYNAMIC{true}); - auto dict_results = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}}; - auto int_results = cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}}; + auto dict_results = + cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}, stream, mr}; + auto int_results = + cudf::test::fixed_width_column_wrapper{{0, 0, 0, 0, 0}, stream, mr}; - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{5}, cudf::mutable_column_view{dict_results}.begin(), dict_hasher); - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{5}, cudf::mutable_column_view{int_results}.begin(), int_hasher); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(dict_results, int_results); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + dict_results, int_results, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } diff --git a/cpp/tests/row_operator/row_operator_tests_utilities.hpp b/cpp/tests/row_operator/row_operator_tests_utilities.hpp index 3841187d14d2..5b8f35558b40 100644 --- a/cpp/tests/row_operator/row_operator_tests_utilities.hpp +++ b/cpp/tests/row_operator/row_operator_tests_utilities.hpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2023-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ #pragma once @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -20,21 +21,28 @@ using nan_equality_t = cudf::detail::row::equality::nan_equal_physical_eq template std::unique_ptr self_comparison(cudf::table_view input, std::vector const& column_order, - PhysicalElementComparator comparator); + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr two_table_comparison(cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - PhysicalElementComparator comparator); + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr two_table_equality(cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - PhysicalElementComparator comparator); + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr sorted_order( std::shared_ptr preprocessed_input, cudf::size_type num_rows, bool has_nested, PhysicalElementComparator comparator, - rmm::cuda_stream_view stream); + rmm::cuda_stream_view stream, + cudf::memory_resources mr); diff --git a/cpp/tests/row_operator/self_comparison_utilities.cu b/cpp/tests/row_operator/self_comparison_utilities.cu index 6e43af6dc7bd..898601ef62ea 100644 --- a/cpp/tests/row_operator/self_comparison_utilities.cu +++ b/cpp/tests/row_operator/self_comparison_utilities.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -20,25 +20,28 @@ template std::unique_ptr self_comparison(cudf::table_view input, std::vector const& column_order, - PhysicalElementComparator comparator) + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { - rmm::cuda_stream_view stream{cudf::get_default_stream()}; - auto const table_comparator = cudf::detail::row::lexicographic::self_comparator{input, column_order, {}, stream}; - auto output = cudf::make_numeric_column( - cudf::data_type(cudf::type_id::BOOL8), input.num_rows(), cudf::mask_state::UNALLOCATED); + auto output = cudf::make_numeric_column(cudf::data_type(cudf::type_id::BOOL8), + input.num_rows(), + cudf::mask_state::UNALLOCATED, + stream, + mr.get_output_mr()); if (cudf::has_nested_columns(input)) { - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{input.num_rows()}, cuda::counting_iterator{0}, output->mutable_view().data(), table_comparator.less(cudf::nullate::NO{}, comparator)); } else { - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), cuda::counting_iterator{0}, cuda::counting_iterator{input.num_rows()}, cuda::counting_iterator{0}, @@ -51,8 +54,12 @@ std::unique_ptr self_comparison(cudf::table_view input, template std::unique_ptr self_comparison( cudf::table_view input, std::vector const& column_order, - physical_comparator_t comparator); + physical_comparator_t comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr self_comparison( cudf::table_view input, std::vector const& column_order, - sorting_comparator_t comparator); + sorting_comparator_t comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); diff --git a/cpp/tests/row_operator/two_table_comparison_utilities.cu b/cpp/tests/row_operator/two_table_comparison_utilities.cu index f42bec2a4f9a..55eb526eb809 100644 --- a/cpp/tests/row_operator/two_table_comparison_utilities.cu +++ b/cpp/tests/row_operator/two_table_comparison_utilities.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -21,27 +21,31 @@ template std::unique_ptr two_table_comparison(cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - PhysicalElementComparator comparator) + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { - rmm::cuda_stream_view stream{cudf::get_default_stream()}; - + // TODO: lexicographic::two_table_comparator still allocates from the current device resource. auto const table_comparator = cudf::detail::row::lexicographic::two_table_comparator{lhs, rhs, column_order, {}, stream}; auto const lhs_it = cudf::detail::row::lhs_iterator(0); auto const rhs_it = cudf::detail::row::rhs_iterator(0); - auto output = cudf::make_numeric_column( - cudf::data_type(cudf::type_id::BOOL8), lhs.num_rows(), cudf::mask_state::UNALLOCATED); + auto output = cudf::make_numeric_column(cudf::data_type(cudf::type_id::BOOL8), + lhs.num_rows(), + cudf::mask_state::UNALLOCATED, + stream, + mr.get_output_mr()); if (cudf::has_nested_columns(lhs) || cudf::has_nested_columns(rhs)) { - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), lhs_it, lhs_it + lhs.num_rows(), rhs_it, output->mutable_view().data(), table_comparator.less(cudf::nullate::NO{}, comparator)); } else { - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), lhs_it, lhs_it + lhs.num_rows(), rhs_it, @@ -55,12 +59,16 @@ template std::unique_ptr two_table_comparison const& column_order, - physical_comparator_t comparator); + physical_comparator_t comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr two_table_comparison( cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - sorting_comparator_t comparator); + sorting_comparator_t comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr sorted_order( @@ -68,23 +76,32 @@ std::unique_ptr sorted_order( cudf::size_type num_rows, bool has_nested, PhysicalElementComparator comparator, - rmm::cuda_stream_view stream) + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { auto output = cudf::make_numeric_column(cudf::data_type(cudf::type_to_id()), num_rows, cudf::mask_state::UNALLOCATED, - stream); + stream, + mr.get_output_mr()); auto const out_begin = output->mutable_view().begin(); - thrust::sequence(rmm::exec_policy_nosync(stream), out_begin, out_begin + num_rows, 0); + thrust::sequence( + rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), out_begin, out_begin + num_rows, 0); auto const table_comparator = cudf::detail::row::lexicographic::self_comparator{preprocessed_input}; if (has_nested) { auto const comp = table_comparator.less(cudf::nullate::NO{}, comparator); - thrust::stable_sort(rmm::exec_policy_nosync(stream), out_begin, out_begin + num_rows, comp); + thrust::stable_sort(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), + out_begin, + out_begin + num_rows, + comp); } else { auto const comp = table_comparator.less(cudf::nullate::NO{}, comparator); - thrust::stable_sort(rmm::exec_policy_nosync(stream), out_begin, out_begin + num_rows, comp); + thrust::stable_sort(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), + out_begin, + out_begin + num_rows, + comp); } return output; @@ -95,10 +112,12 @@ template std::unique_ptr sorted_order( cudf::size_type num_rows, bool has_nested, physical_comparator_t comparator, - rmm::cuda_stream_view stream); + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr sorted_order( std::shared_ptr preprocessed_input, cudf::size_type num_rows, bool has_nested, sorting_comparator_t comparator, - rmm::cuda_stream_view stream); + rmm::cuda_stream_view stream, + cudf::memory_resources mr); diff --git a/cpp/tests/row_operator/two_table_equality_utilities.cu b/cpp/tests/row_operator/two_table_equality_utilities.cu index 4d167f911b0d..38e548b0943b 100644 --- a/cpp/tests/row_operator/two_table_equality_utilities.cu +++ b/cpp/tests/row_operator/two_table_equality_utilities.cu @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -17,23 +17,27 @@ template std::unique_ptr two_table_equality(cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - PhysicalElementComparator comparator) + PhysicalElementComparator comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr) { - rmm::cuda_stream_view stream{cudf::get_default_stream()}; - - auto const table_comparator = cudf::detail::row::equality::two_table_comparator{lhs, rhs, stream}; + auto const table_comparator = + cudf::detail::row::equality::two_table_comparator{lhs, rhs, stream, mr}; auto const lhs_it = cudf::detail::row::lhs_iterator(0); auto const rhs_it = cudf::detail::row::rhs_iterator(0); - auto output = cudf::make_numeric_column( - cudf::data_type(cudf::type_id::BOOL8), lhs.num_rows(), cudf::mask_state::UNALLOCATED); + auto output = cudf::make_numeric_column(cudf::data_type(cudf::type_id::BOOL8), + lhs.num_rows(), + cudf::mask_state::UNALLOCATED, + stream, + mr.get_output_mr()); if (cudf::has_nested_columns(lhs) or cudf::has_nested_columns(rhs)) { auto const equal_comparator = table_comparator.equal_to(cudf::nullate::NO{}, cudf::null_equality::EQUAL, comparator); - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), lhs_it, lhs_it + lhs.num_rows(), rhs_it, @@ -43,7 +47,7 @@ std::unique_ptr two_table_equality(cudf::table_view lhs, auto const equal_comparator = table_comparator.equal_to(cudf::nullate::NO{}, cudf::null_equality::EQUAL, comparator); - thrust::transform(rmm::exec_policy_nosync(stream), + thrust::transform(rmm::exec_policy_nosync(stream, mr.get_temporary_mr()), lhs_it, lhs_it + lhs.num_rows(), rhs_it, @@ -57,9 +61,13 @@ template std::unique_ptr two_table_equality( cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - physical_equality_t comparator); + physical_equality_t comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); template std::unique_ptr two_table_equality( cudf::table_view lhs, cudf::table_view rhs, std::vector const& column_order, - nan_equality_t comparator); + nan_equality_t comparator, + rmm::cuda_stream_view stream, + cudf::memory_resources mr); diff --git a/cpp/tests/sort/top_k_tests.cpp b/cpp/tests/sort/top_k_tests.cpp index d761c6e30125..abf2258fc5f4 100644 --- a/cpp/tests/sort/top_k_tests.cpp +++ b/cpp/tests/sort/top_k_tests.cpp @@ -424,7 +424,7 @@ TEST_F(TopK, Errors) auto offsets = cudf::test::fixed_width_column_wrapper({0, 15, 20, 23, 40, 42}); EXPECT_THROW(cudf::segmented_top_k(input, offsets, -1), std::invalid_argument); EXPECT_THROW(cudf::segmented_top_k_order(input, offsets, -1), std::invalid_argument); - offsets = cudf::test::fixed_width_column_wrapper({}); + offsets = cudf::test::fixed_width_column_wrapper(); EXPECT_THROW(cudf::segmented_top_k(input, offsets, 10), std::invalid_argument); EXPECT_THROW(cudf::segmented_top_k_order(input, offsets, 10), std::invalid_argument); offsets = cudf::test::fixed_width_column_wrapper({0, 15}, {1, 0}); diff --git a/cpp/tests/streams/interop_test.cpp b/cpp/tests/streams/interop_test.cpp index 484c288e8a21..bc944922ba9f 100644 --- a/cpp/tests/streams/interop_test.cpp +++ b/cpp/tests/streams/interop_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -30,8 +30,8 @@ TEST_F(DLPackTest, ToDLPack) TEST_F(DLPackTest, FromDLPack) { using unique_managed_tensor = std::unique_ptr; - cudf::test::fixed_width_column_wrapper col1({}); - cudf::test::fixed_width_column_wrapper col2({}); + cudf::test::fixed_width_column_wrapper col1{}; + cudf::test::fixed_width_column_wrapper col2{}; cudf::table_view input({col1, col2}); unique_managed_tensor tensor(cudf::to_dlpack(input, cudf::test::get_default_stream())); auto result = cudf::from_dlpack(tensor.get(), cudf::test::get_default_stream()); diff --git a/cpp/tests/streams/quantile_test.cpp b/cpp/tests/streams/quantile_test.cpp index 98e188a679b9..554b28738801 100644 --- a/cpp/tests/streams/quantile_test.cpp +++ b/cpp/tests/streams/quantile_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2024-2025, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2024-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -42,7 +42,7 @@ TEST_F(QuantileTest, TestMultiColumnUnsorted) TEST_F(QuantileTest, TestEmpty) { - auto input = cudf::test::fixed_width_column_wrapper({}); + auto input = cudf::test::fixed_width_column_wrapper(); cudf::quantile( input, {0.5, 0.25}, cudf::interpolation::LINEAR, {}, true, cudf::test::get_default_stream()); } diff --git a/cpp/tests/transform/integration/unary_transform_test.cpp b/cpp/tests/transform/integration/unary_transform_test.cpp index 528ef661cda6..c358f3ef1322 100644 --- a/cpp/tests/transform/integration/unary_transform_test.cpp +++ b/cpp/tests/transform/integration/unary_transform_test.cpp @@ -674,7 +674,7 @@ __device__ inline void decode(float * output, float input){ // empty column { - auto a_empty = cudf::test::fixed_width_column_wrapper({}).release(); + auto a_empty = cudf::test::fixed_width_column_wrapper().release(); auto a_encoded = cudf::dictionary::encode(a_empty->view()); cudf::transform_input inputs[] = {*a_encoded}; diff --git a/cpp/tests/transform/mask_to_bools_test.cpp b/cpp/tests/transform/mask_to_bools_test.cpp index 047b53beee62..686b02f90061 100644 --- a/cpp/tests/transform/mask_to_bools_test.cpp +++ b/cpp/tests/transform/mask_to_bools_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2020-2023, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2020-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -17,7 +17,7 @@ struct MaskToBools : public cudf::test::BaseFixture {}; TEST_F(MaskToBools, NullDataWithZeroLength) { - auto expected = cudf::test::fixed_width_column_wrapper({}); + auto expected = cudf::test::fixed_width_column_wrapper(); auto out = cudf::mask_to_bools(nullptr, 0, 0); CUDF_TEST_EXPECT_COLUMNS_EQUAL(expected, out->view()); @@ -25,14 +25,14 @@ TEST_F(MaskToBools, NullDataWithZeroLength) TEST_F(MaskToBools, NullDataWithNonZeroLength) { - auto expected = cudf::test::fixed_width_column_wrapper({}); + auto expected = cudf::test::fixed_width_column_wrapper(); EXPECT_THROW(cudf::mask_to_bools(nullptr, 0, 2), cudf::logic_error); } TEST_F(MaskToBools, ImproperBitRange) { - auto expected = cudf::test::fixed_width_column_wrapper({}); + auto expected = cudf::test::fixed_width_column_wrapper(); EXPECT_THROW(cudf::mask_to_bools(nullptr, 2, 1), cudf::logic_error); } diff --git a/cpp/tests/transform/nans_to_null_test.cpp b/cpp/tests/transform/nans_to_null_test.cpp index f9d6c6aca573..a1c3652fe7f8 100644 --- a/cpp/tests/transform/nans_to_null_test.cpp +++ b/cpp/tests/transform/nans_to_null_test.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -116,7 +116,7 @@ TYPED_TEST(NaNsToNullTest, EmptyColumn) { using T = TypeParam; - auto input_column = cudf::test::fixed_width_column_wrapper({}); + auto input_column = cudf::test::fixed_width_column_wrapper(); this->run_test(input_column, input_column); } @@ -141,6 +141,6 @@ TEST_F(NaNsToNullFailTest, IntegerType) TEST_F(NaNsToNullFailTest, EmptyColumn) { - auto input_column = cudf::test::fixed_width_column_wrapper({}); + auto input_column = cudf::test::fixed_width_column_wrapper(); EXPECT_THROW(cudf::column_nans_to_nulls(input_column), std::invalid_argument); } diff --git a/cpp/tests/utilities/column_utilities.cu b/cpp/tests/utilities/column_utilities.cu index 48d664272d16..69f9a7e53fc5 100644 --- a/cpp/tests/utilities/column_utilities.cu +++ b/cpp/tests/utilities/column_utilities.cu @@ -489,8 +489,9 @@ std::string stringify_column_differences(cudf::device_span difference buffer << depth_str << "differences:" << std::endl; auto source_table = cudf::table_view({lhs, rhs}); - auto diff_column = - fixed_width_column_wrapper(h_differences.begin(), h_differences.end()); + // Intermediate gather indices — allocate on temporary, not output. + auto diff_column = fixed_width_column_wrapper( + h_differences.begin(), h_differences.end(), stream, mr.get_temporary_mr()); auto diff_table = cudf::gather(source_table, diff_column, cudf::out_of_bounds_policy::DONT_CHECK, @@ -542,7 +543,7 @@ struct column_comparator_impl { auto rhs_tview = table_view{{rhs}}; auto const comparator = - cudf::detail::row::equality::two_table_comparator{lhs_tview, rhs_tview, stream}; + cudf::detail::row::equality::two_table_comparator{lhs_tview, rhs_tview, stream, mr}; auto const has_nulls = cudf::has_nulls(lhs_tview) or cudf::has_nulls(rhs_tview); auto const device_comparator = comparator.equal_to(cudf::nullate::DYNAMIC{has_nulls}); @@ -884,6 +885,9 @@ bool expect_columns_equal(cudf::column_view const& lhs, rmm::cuda_stream_view stream, cudf::memory_resources mr) { + // TODO: equality row preprocessing (two_table_comparator / preprocessed_table::create) still + // allocates from the current device resource; pass `mr` through once that path accepts + // memory_resources so callers need not disable failing current-resource scopes. check_non_empty_nulls(lhs, rhs, stream); auto lhs_indices = generate_all_row_indices(lhs.size(), stream, mr); auto rhs_indices = generate_all_row_indices(rhs.size(), stream, mr); diff --git a/cpp/tests/utilities/memory_resource_utilities.cpp b/cpp/tests/utilities/memory_resource_utilities.cpp index 117758d670d3..010afc351595 100644 --- a/cpp/tests/utilities/memory_resource_utilities.cpp +++ b/cpp/tests/utilities/memory_resource_utilities.cpp @@ -22,9 +22,30 @@ scoped_current_device_resource::scoped_current_device_resource( { } -scoped_current_device_resource::~scoped_current_device_resource() +scoped_current_device_resource::scoped_current_device_resource( + scoped_current_device_resource&& other) noexcept + : _previous{std::exchange(other._previous, std::nullopt)} +{ +} + +scoped_current_device_resource& scoped_current_device_resource::operator=( + scoped_current_device_resource&& other) noexcept +{ + if (this != &other) { + restore(); + _previous = std::exchange(other._previous, std::nullopt); + } + return *this; +} + +scoped_current_device_resource::~scoped_current_device_resource() { restore(); } + +void scoped_current_device_resource::restore() noexcept { - std::ignore = cudf::set_current_device_resource(std::move(_previous)); + if (_previous.has_value()) { + std::ignore = cudf::set_current_device_resource(std::move(*_previous)); + _previous.reset(); + } } memory_resource_test_harness::memory_resource_test_harness(rmm::device_async_resource_ref upstream) diff --git a/cpp/tests/utilities_tests/column_utilities_tests.cpp b/cpp/tests/utilities_tests/column_utilities_tests.cpp index aa8f988b591f..ae55a56948bc 100644 --- a/cpp/tests/utilities_tests/column_utilities_tests.cpp +++ b/cpp/tests/utilities_tests/column_utilities_tests.cpp @@ -48,21 +48,27 @@ TYPED_TEST_SUITE(ColumnUtilitiesTestFixedPoint, cudf::test::FixedPointTypes); TYPED_TEST(ColumnUtilitiesTest, NonNullableToHost) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + auto sequence = cudf::detail::make_counting_transform_iterator( 0, [](auto i) { return cudf::test::make_type_param_scalar(i); }); auto size = this->size(); std::vector data(sequence, sequence + size); - cudf::test::fixed_width_column_wrapper col(data.begin(), data.end()); + cudf::test::fixed_width_column_wrapper col(data.begin(), data.end(), stream, mr); - auto host_data = cudf::test::to_host(col); + auto host_data = cudf::test::to_host(col, stream, mr); EXPECT_TRUE(std::equal(data.begin(), data.end(), host_data.first.begin())); } TYPED_TEST(ColumnUtilitiesTest, NonNullableToHostWithOffset) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + auto sequence = cudf::detail::make_counting_transform_iterator( 0, [](auto i) { return cudf::test::make_type_param_scalar(i); }); @@ -71,18 +77,22 @@ TYPED_TEST(ColumnUtilitiesTest, NonNullableToHostWithOffset) auto data = std::vector(sequence, sequence + size); auto expected_data = std::vector(sequence + split, sequence + size); - auto col = cudf::test::fixed_width_column_wrapper(data.begin(), data.end()); + auto col = + cudf::test::fixed_width_column_wrapper(data.begin(), data.end(), stream, mr); auto const splits = std::vector{split}; - auto result = cudf::split(col, splits); + auto result = cudf::split(col, splits, stream); - auto host_data = cudf::test::to_host(result.back()); + auto host_data = cudf::test::to_host(result.back(), stream, mr); EXPECT_TRUE(std::equal(expected_data.begin(), expected_data.end(), host_data.first.begin())); } TYPED_TEST(ColumnUtilitiesTest, NullableToHostWithOffset) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + auto sequence = cudf::detail::make_counting_transform_iterator( 0, [](auto i) { return cudf::test::make_type_param_scalar(i); }); @@ -92,12 +102,13 @@ TYPED_TEST(ColumnUtilitiesTest, NullableToHostWithOffset) 0, [&split](auto i) { return i <= 10 and i > split; }); std::vector data(sequence, sequence + size); std::vector expected_data(sequence + split, sequence + size); - cudf::test::fixed_width_column_wrapper col(data.begin(), data.end(), valid); + cudf::test::fixed_width_column_wrapper col( + data.begin(), data.end(), valid, stream, mr); std::vector splits{split}; - std::vector result = cudf::split(col, splits); + std::vector result = cudf::split(col, splits, stream); - auto host_data = cudf::test::to_host(result.back()); + auto host_data = cudf::test::to_host(result.back(), stream, mr); EXPECT_TRUE(std::equal(expected_data.begin(), expected_data.end(), host_data.first.begin())); @@ -108,6 +119,9 @@ TYPED_TEST(ColumnUtilitiesTest, NullableToHostWithOffset) TYPED_TEST(ColumnUtilitiesTest, NullableToHostAllValid) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + auto sequence = cudf::detail::make_counting_transform_iterator( 0, [](auto i) { return cudf::test::make_type_param_scalar(i); }); @@ -116,9 +130,10 @@ TYPED_TEST(ColumnUtilitiesTest, NullableToHostAllValid) auto size = this->size(); std::vector data(sequence, sequence + size); - cudf::test::fixed_width_column_wrapper col(data.begin(), data.end(), all_valid); + cudf::test::fixed_width_column_wrapper col( + data.begin(), data.end(), all_valid, stream, mr); - auto host_data = cudf::test::to_host(col); + auto host_data = cudf::test::to_host(col, stream, mr); EXPECT_TRUE(std::equal(data.begin(), data.end(), host_data.first.begin())); @@ -131,19 +146,28 @@ struct ColumnUtilitiesEquivalenceTest : public cudf::test::BaseFixture {}; TEST_F(ColumnUtilitiesEquivalenceTest, DoubleTest) { - cudf::test::fixed_width_column_wrapper col1{10. / 3, 22. / 7}; - cudf::test::fixed_width_column_wrapper col2{31. / 3 - 21. / 3, 19. / 7 + 3. / 7}; + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + + cudf::test::fixed_width_column_wrapper col1({10. / 3, 22. / 7}, stream, mr); + cudf::test::fixed_width_column_wrapper col2( + {31. / 3 - 21. / 3, 19. / 7 + 3. / 7}, stream, mr); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(col1, col2); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT( + col1, col2, cudf::test::debug_output_level::FIRST_ERROR, cudf::test::default_ulp, stream, mr); } TEST_F(ColumnUtilitiesEquivalenceTest, NullabilityTest) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + auto all_valid = cudf::test::iterators::no_nulls(); - cudf::test::fixed_width_column_wrapper col1{1, 2, 3}; - cudf::test::fixed_width_column_wrapper col2({1, 2, 3}, all_valid); + cudf::test::fixed_width_column_wrapper col1({1, 2, 3}, stream, mr); + cudf::test::fixed_width_column_wrapper col2({1, 2, 3}, all_valid, stream, mr); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(col1, col2); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT( + col1, col2, cudf::test::debug_output_level::FIRST_ERROR, cudf::test::default_ulp, stream, mr); } TEST_F(ColumnUtilitiesEquivalenceTest, DistinctMemoryResources) @@ -202,12 +226,17 @@ struct ColumnUtilitiesStringsTest : public cudf::test::BaseFixture {}; TEST_F(ColumnUtilitiesStringsTest, StringsToHost) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + std::vector h_strings{"eee", "bb", nullptr, "", "aa", "bbb", "ééé"}; cudf::test::strings_column_wrapper strings( h_strings.begin(), h_strings.end(), - thrust::make_transform_iterator(h_strings.begin(), [](auto str) { return str != nullptr; })); - auto host_data = cudf::test::to_host(strings); + thrust::make_transform_iterator(h_strings.begin(), [](auto str) { return str != nullptr; }), + stream, + mr); + auto host_data = cudf::test::to_host(strings, stream, mr); auto result_itr = host_data.first.begin(); for (auto itr = h_strings.begin(); itr != h_strings.end(); ++itr, ++result_itr) { if (*itr) { EXPECT_TRUE((*result_itr) == (*itr)); } @@ -216,12 +245,17 @@ TEST_F(ColumnUtilitiesStringsTest, StringsToHost) TEST_F(ColumnUtilitiesStringsTest, StringsToHostAllNulls) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + std::vector h_strings{nullptr, nullptr, nullptr}; cudf::test::strings_column_wrapper strings( h_strings.begin(), h_strings.end(), - thrust::make_transform_iterator(h_strings.begin(), [](auto str) { return str != nullptr; })); - auto host_data = cudf::test::to_host(strings); + thrust::make_transform_iterator(h_strings.begin(), [](auto str) { return str != nullptr; }), + stream, + mr); + auto host_data = cudf::test::to_host(strings, stream, mr); auto results = host_data.first; EXPECT_EQ(std::size_t{3}, host_data.first.size()); EXPECT_TRUE(std::all_of(results.begin(), results.end(), [](auto s) { return s.empty(); })); @@ -229,6 +263,9 @@ TEST_F(ColumnUtilitiesStringsTest, StringsToHostAllNulls) TYPED_TEST(ColumnUtilitiesTestFixedPoint, NonNullableToHost) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + using namespace numeric; using decimalXX = TypeParam; using rep = cudf::device_storage_type_t; @@ -239,16 +276,20 @@ TYPED_TEST(ColumnUtilitiesTestFixedPoint, NonNullableToHost) auto fps = cudf::detail::make_counting_transform_iterator(0, to_fp); auto reps = cudf::detail::make_counting_transform_iterator(0, to_rep); - auto const size = 1000; - auto const expected = std::vector(fps, fps + size); - auto const col = cudf::test::fixed_point_column_wrapper(reps, reps + size, scale); - auto const host_data = cudf::test::to_host(col); + auto const size = 1000; + auto const expected = std::vector(fps, fps + size); + auto const col = + cudf::test::fixed_point_column_wrapper(reps, reps + size, scale, stream, mr); + auto const host_data = cudf::test::to_host(col, stream, mr); EXPECT_TRUE(std::equal(expected.begin(), expected.end(), host_data.first.begin())); } TYPED_TEST(ColumnUtilitiesTestFixedPoint, NonNullableToHostWithOffset) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + using namespace numeric; using decimalXX = TypeParam; using rep = cudf::device_storage_type_t; @@ -263,11 +304,12 @@ TYPED_TEST(ColumnUtilitiesTestFixedPoint, NonNullableToHostWithOffset) auto const split = cudf::size_type{2}; auto const expected = std::vector(fps + split, fps + size); - auto const col = cudf::test::fixed_point_column_wrapper(reps, reps + size, scale); - auto const splits = std::vector{split}; - auto result = cudf::split(col, splits); + auto const col = + cudf::test::fixed_point_column_wrapper(reps, reps + size, scale, stream, mr); + auto const splits = std::vector{split}; + auto result = cudf::split(col, splits, stream); - auto host_data = cudf::test::to_host(result.back()); + auto host_data = cudf::test::to_host(result.back(), stream, mr); EXPECT_TRUE(std::equal(expected.begin(), expected.end(), host_data.first.begin())); } @@ -276,65 +318,82 @@ struct ColumnUtilitiesListsTest : public cudf::test::BaseFixture {}; TEST_F(ColumnUtilitiesListsTest, Equivalence) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + // list, nullable vs. non-nullable { auto all_valid = cudf::test::iterators::no_nulls(); - cudf::test::lists_column_wrapper a{{1, 2, 3}, {5, 6}, {8, 9}, {10}, {14, 15}}; - cudf::test::lists_column_wrapper b{{{1, 2, 3}, {5, 6}, {8, 9}, {10}, {14, 15}}, all_valid}; + cudf::test::lists_column_wrapper a( + {{1, 2, 3}, {5, 6}, {8, 9}, {10}, {14, 15}}, stream, mr); + cudf::test::lists_column_wrapper b( + {{1, 2, 3}, {5, 6}, {8, 9}, {10}, {14, 15}}, all_valid, stream, mr); // properties - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUIVALENT(a, b); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUIVALENT( + a, b, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); EXPECT_FALSE(cudf::test::detail::expect_column_properties_equal( - a, b, cudf::test::debug_output_level::QUIET)); + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); // values - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(a, b); - EXPECT_FALSE( - cudf::test::detail::expect_columns_equal(a, b, cudf::test::debug_output_level::QUIET)); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT( + a, b, cudf::test::debug_output_level::FIRST_ERROR, cudf::test::default_ulp, stream, mr); + EXPECT_FALSE(cudf::test::detail::expect_columns_equal( + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); } // list>, nullable vs. non-nullable { auto all_valid = cudf::test::iterators::no_nulls(); - cudf::test::lists_column_wrapper a{{{1, 2, 3}, {5, 6}}, {{8, 9}, {10}}, {{14, 15}}}; - cudf::test::lists_column_wrapper b{{{{1, 2, 3}, {5, 6}}, {{8, 9}, {10}}, {{14, 15}}}, - all_valid}; + cudf::test::lists_column_wrapper a( + {{{1, 2, 3}, {5, 6}}, {{8, 9}, {10}}, {{14, 15}}}, stream, mr); + cudf::test::lists_column_wrapper b( + {{{1, 2, 3}, {5, 6}}, {{8, 9}, {10}}, {{14, 15}}}, all_valid, stream, mr); // properties - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUIVALENT(a, b); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUIVALENT( + a, b, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); EXPECT_FALSE(cudf::test::detail::expect_column_properties_equal( - a, b, cudf::test::debug_output_level::QUIET)); + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(a, b); - EXPECT_FALSE( - cudf::test::detail::expect_columns_equal(a, b, cudf::test::debug_output_level::QUIET)); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT( + a, b, cudf::test::debug_output_level::FIRST_ERROR, cudf::test::default_ulp, stream, mr); + EXPECT_FALSE(cudf::test::detail::expect_columns_equal( + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); } } TEST_F(ColumnUtilitiesListsTest, DifferingRowCounts) { - cudf::test::fixed_width_column_wrapper a{1, 1, 1, 1}; - cudf::test::fixed_width_column_wrapper b{1, 1, 1, 1, 1}; + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + + cudf::test::fixed_width_column_wrapper a({1, 1, 1, 1}, stream, mr); + cudf::test::fixed_width_column_wrapper b({1, 1, 1, 1, 1}, stream, mr); - EXPECT_FALSE( - cudf::test::detail::expect_columns_equal(a, b, cudf::test::debug_output_level::QUIET)); + EXPECT_FALSE(cudf::test::detail::expect_columns_equal( + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); EXPECT_FALSE(cudf::test::detail::expect_column_properties_equal( - a, b, cudf::test::debug_output_level::QUIET)); - EXPECT_FALSE( - cudf::test::detail::expect_columns_equivalent(a, b, cudf::test::debug_output_level::QUIET)); + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); + EXPECT_FALSE(cudf::test::detail::expect_columns_equivalent( + a, b, cudf::test::debug_output_level::QUIET, cudf::test::default_ulp, stream, mr)); EXPECT_FALSE(cudf::test::detail::expect_column_properties_equivalent( - a, b, cudf::test::debug_output_level::QUIET)); + a, b, cudf::test::debug_output_level::QUIET, stream, mr)); } TEST_F(ColumnUtilitiesListsTest, DifferentPhysicalStructureBeforeConstruction) { + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + // list { std::vector valids = {0, 0, 1, 0, 1, 0, 0}; - cudf::test::fixed_width_column_wrapper c0_offsets{0, 3, 6, 8, 11, 14, 16, 19}; - cudf::test::fixed_width_column_wrapper c0_data{ - 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7}; + cudf::test::fixed_width_column_wrapper c0_offsets( + {0, 3, 6, 8, 11, 14, 16, 19}, stream, mr); + cudf::test::fixed_width_column_wrapper c0_data( + {1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 7}, stream, mr); auto [null_mask, null_count] = cudf::test::detail::make_null_mask(valids.begin(), valids.end()); @@ -344,8 +403,8 @@ TEST_F(ColumnUtilitiesListsTest, DifferentPhysicalStructureBeforeConstruction) return cudf::purge_nonempty_nulls(tmp->view()); }(); - cudf::test::fixed_width_column_wrapper c1_offsets{0, 0, 0, 2, 2, 5, 5, 5}; - cudf::test::fixed_width_column_wrapper c1_data{3, 3, 5, 5, 5}; + cudf::test::fixed_width_column_wrapper c1_offsets({0, 0, 0, 2, 2, 5, 5, 5}, stream, mr); + cudf::test::fixed_width_column_wrapper c1_data({3, 3, 5, 5, 5}, stream, mr); auto c1 = [&] { auto tmp = make_lists_column( 7, @@ -357,23 +416,26 @@ TEST_F(ColumnUtilitiesListsTest, DifferentPhysicalStructureBeforeConstruction) }(); // properties - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL(*c0, *c1); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL( + *c0, *c1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); // values - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*c0, *c1); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *c0, *c1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } // list>> { std::vector level1_valids = {0, 0, 1, 0, 1, 0, 0}; - cudf::test::fixed_width_column_wrapper c0_l1_offsets{0, 1, 2, 4, 4, 7, 7, 7}; - cudf::test::fixed_width_column_wrapper c0_l2_offsets{0, 1, 2, 5, 6, 7, 10, 14}; - cudf::test::fixed_width_column_wrapper c0_l3_ints{ - 1, 1, -1, -2, -3, 1, 1, -4, -5, -6, -7, -8, -9, -10}; - cudf::test::fixed_width_column_wrapper c0_l3_floats{ - 1, 1, 10, 20, 30, 1, 1, 40, 50, 60, 70, 80, 90, 100}; - cudf::test::structs_column_wrapper c0_l2_data({c0_l3_ints, c0_l3_floats}); + cudf::test::fixed_width_column_wrapper c0_l1_offsets({0, 1, 2, 4, 4, 7, 7, 7}, stream, mr); + cudf::test::fixed_width_column_wrapper c0_l2_offsets( + {0, 1, 2, 5, 6, 7, 10, 14}, stream, mr); + cudf::test::fixed_width_column_wrapper c0_l3_ints( + {1, 1, -1, -2, -3, 1, 1, -4, -5, -6, -7, -8, -9, -10}, stream, mr); + cudf::test::fixed_width_column_wrapper c0_l3_floats( + {1, 1, 10, 20, 30, 1, 1, 40, 50, 60, 70, 80, 90, 100}, stream, mr); + cudf::test::structs_column_wrapper c0_l2_data({c0_l3_ints, c0_l3_floats}, {}, stream, mr); std::vector c0_l2_valids = {1, 1, 1, 0, 0, 1, 1}; auto [null_mask, null_count] = @@ -392,12 +454,13 @@ TEST_F(ColumnUtilitiesListsTest, DifferentPhysicalStructureBeforeConstruction) return cudf::purge_nonempty_nulls(tmp->view()); }(); - cudf::test::fixed_width_column_wrapper c1_l1_offsets{0, 0, 0, 2, 2, 5, 5, 5}; - cudf::test::fixed_width_column_wrapper c1_l2_offsets{0, 3, 3, 3, 6, 10}; - cudf::test::fixed_width_column_wrapper c1_l3_ints{-1, -2, -3, -4, -5, -6, -7, -8, -9, -10}; - cudf::test::fixed_width_column_wrapper c1_l3_floats{ - 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; - cudf::test::structs_column_wrapper c1_l2_data({c1_l3_ints, c1_l3_floats}); + cudf::test::fixed_width_column_wrapper c1_l1_offsets({0, 0, 0, 2, 2, 5, 5, 5}, stream, mr); + cudf::test::fixed_width_column_wrapper c1_l2_offsets({0, 3, 3, 3, 6, 10}, stream, mr); + cudf::test::fixed_width_column_wrapper c1_l3_ints( + {-1, -2, -3, -4, -5, -6, -7, -8, -9, -10}, stream, mr); + cudf::test::fixed_width_column_wrapper c1_l3_floats( + {10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, stream, mr); + cudf::test::structs_column_wrapper c1_l2_data({c1_l3_ints, c1_l3_floats}, {}, stream, mr); std::vector c1_l2_valids = {1, 0, 0, 1, 1}; std::tie(null_mask, null_count) = @@ -417,10 +480,12 @@ TEST_F(ColumnUtilitiesListsTest, DifferentPhysicalStructureBeforeConstruction) }(); // properties - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL(*c0, *c1); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL( + *c0, *c1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); // values - CUDF_TEST_EXPECT_COLUMNS_EQUAL(*c0, *c1); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + *c0, *c1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } } @@ -428,62 +493,80 @@ struct ColumnUtilitiesStructsTest : public cudf::test::BaseFixture {}; TEST_F(ColumnUtilitiesStructsTest, Properties) { - cudf::test::strings_column_wrapper s0_scol0{"mno", "jkl", "ghi", "def", "abc"}; - cudf::test::fixed_width_column_wrapper s0_scol1{5, 4, 3, 2, 1}; - cudf::test::strings_column_wrapper s0_sscol0{"5555", "4444", "333", "22", "1"}; - cudf::test::fixed_width_column_wrapper s0_sscol1{50, 40, 30, 20, 10}; - cudf::test::lists_column_wrapper s0_sscol2{{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}; - cudf::test::structs_column_wrapper s0_scol2({s0_sscol0, s0_sscol1, s0_sscol2}); - cudf::test::structs_column_wrapper s_col0({s0_scol0, s0_scol1, s0_scol2}); + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + + cudf::test::strings_column_wrapper s0_scol0({"mno", "jkl", "ghi", "def", "abc"}, stream, mr); + cudf::test::fixed_width_column_wrapper s0_scol1({5, 4, 3, 2, 1}, stream, mr); + cudf::test::strings_column_wrapper s0_sscol0({"5555", "4444", "333", "22", "1"}, stream, mr); + cudf::test::fixed_width_column_wrapper s0_sscol1({50, 40, 30, 20, 10}, stream, mr); + cudf::test::lists_column_wrapper s0_sscol2( + {{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}, stream, mr); + cudf::test::structs_column_wrapper s0_scol2({s0_sscol0, s0_sscol1, s0_sscol2}, {}, stream, mr); + cudf::test::structs_column_wrapper s_col0({s0_scol0, s0_scol1, s0_scol2}, {}, stream, mr); auto all_valid = cuda::make_constant_iterator(true); - cudf::test::strings_column_wrapper s1_scol0{"mno", "jkl", "ghi", "def", "abc"}; - cudf::test::fixed_width_column_wrapper s1_scol1{5, 4, 3, 2, 1}; - cudf::test::strings_column_wrapper s1_sscol0{"5555", "4444", "333", "22", "1"}; - cudf::test::fixed_width_column_wrapper s1_sscol1{50, 40, 30, 20, 10}; - cudf::test::lists_column_wrapper s1_sscol2{{{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}, - all_valid}; - cudf::test::structs_column_wrapper s1_scol2({s1_sscol0, s1_sscol1, s1_sscol2}); - cudf::test::structs_column_wrapper s_col1({s1_scol0, s1_scol1, s1_scol2}); + cudf::test::strings_column_wrapper s1_scol0({"mno", "jkl", "ghi", "def", "abc"}, stream, mr); + cudf::test::fixed_width_column_wrapper s1_scol1({5, 4, 3, 2, 1}, stream, mr); + cudf::test::strings_column_wrapper s1_sscol0({"5555", "4444", "333", "22", "1"}, stream, mr); + cudf::test::fixed_width_column_wrapper s1_sscol1({50, 40, 30, 20, 10}, stream, mr); + cudf::test::lists_column_wrapper s1_sscol2( + {{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}, all_valid, stream, mr); + cudf::test::structs_column_wrapper s1_scol2({s1_sscol0, s1_sscol1, s1_sscol2}, {}, stream, mr); + cudf::test::structs_column_wrapper s_col1({s1_scol0, s1_scol1, s1_scol2}, {}, stream, mr); // equivalent, but not equal - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUIVALENT(s_col0, s_col1); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUIVALENT( + s_col0, s_col1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); EXPECT_FALSE(cudf::test::detail::expect_column_properties_equal( - s_col0, s_col1, cudf::test::debug_output_level::QUIET)); + s_col0, s_col1, cudf::test::debug_output_level::QUIET, stream, mr)); - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL(s_col0, s_col0); - CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL(s_col1, s_col1); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL( + s_col0, s_col0, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); + CUDF_TEST_EXPECT_COLUMN_PROPERTIES_EQUAL( + s_col1, s_col1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } TEST_F(ColumnUtilitiesStructsTest, Values) { - cudf::test::strings_column_wrapper s0_scol0{"mno", "jkl", "ghi", "def", "abc"}; - cudf::test::fixed_width_column_wrapper s0_scol1{5, 4, 3, 2, 1}; - cudf::test::strings_column_wrapper s0_sscol0{"5555", "4444", "333", "22", "1"}; - cudf::test::fixed_width_column_wrapper s0_sscol1{50, 40, 30, 20, 10}; - cudf::test::lists_column_wrapper s0_sscol2{{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}; - cudf::test::structs_column_wrapper s0_scol2({s0_sscol0, s0_sscol1, s0_sscol2}); - cudf::test::structs_column_wrapper s_col0({s0_scol0, s0_scol1, s0_scol2}); + auto stream = cudf::test::get_default_stream(); + auto mr = this->mr(); + + cudf::test::strings_column_wrapper s0_scol0({"mno", "jkl", "ghi", "def", "abc"}, stream, mr); + cudf::test::fixed_width_column_wrapper s0_scol1({5, 4, 3, 2, 1}, stream, mr); + cudf::test::strings_column_wrapper s0_sscol0({"5555", "4444", "333", "22", "1"}, stream, mr); + cudf::test::fixed_width_column_wrapper s0_sscol1({50, 40, 30, 20, 10}, stream, mr); + cudf::test::lists_column_wrapper s0_sscol2( + {{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}, stream, mr); + cudf::test::structs_column_wrapper s0_scol2({s0_sscol0, s0_sscol1, s0_sscol2}, {}, stream, mr); + cudf::test::structs_column_wrapper s_col0({s0_scol0, s0_scol1, s0_scol2}, {}, stream, mr); auto all_valid = cuda::make_constant_iterator(true); - cudf::test::strings_column_wrapper s1_scol0{"mno", "jkl", "ghi", "def", "abc"}; - cudf::test::fixed_width_column_wrapper s1_scol1{5, 4, 3, 2, 1}; - cudf::test::strings_column_wrapper s1_sscol0{"5555", "4444", "333", "22", "1"}; - cudf::test::fixed_width_column_wrapper s1_sscol1{50, 40, 30, 20, 10}; - cudf::test::lists_column_wrapper s1_sscol2{{{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}, - all_valid}; - cudf::test::structs_column_wrapper s1_scol2({s1_sscol0, s1_sscol1, s1_sscol2}); - cudf::test::structs_column_wrapper s_col1({s1_scol0, s1_scol1, s1_scol2}); + cudf::test::strings_column_wrapper s1_scol0({"mno", "jkl", "ghi", "def", "abc"}, stream, mr); + cudf::test::fixed_width_column_wrapper s1_scol1({5, 4, 3, 2, 1}, stream, mr); + cudf::test::strings_column_wrapper s1_sscol0({"5555", "4444", "333", "22", "1"}, stream, mr); + cudf::test::fixed_width_column_wrapper s1_sscol1({50, 40, 30, 20, 10}, stream, mr); + cudf::test::lists_column_wrapper s1_sscol2( + {{1, 2}, {3, 4}, {5}, {6, 7, 8}, {12, 12}}, all_valid, stream, mr); + cudf::test::structs_column_wrapper s1_scol2({s1_sscol0, s1_sscol1, s1_sscol2}, {}, stream, mr); + cudf::test::structs_column_wrapper s_col1({s1_scol0, s1_scol1, s1_scol2}, {}, stream, mr); // equivalent, but not equal - CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(s_col0, s_col1); + CUDF_TEST_EXPECT_COLUMNS_EQUIVALENT(s_col0, + s_col1, + cudf::test::debug_output_level::FIRST_ERROR, + cudf::test::default_ulp, + stream, + mr); EXPECT_FALSE(cudf::test::detail::expect_columns_equal( - s_col0, s_col1, cudf::test::debug_output_level::QUIET)); + s_col0, s_col1, cudf::test::debug_output_level::QUIET, stream, mr)); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(s_col0, s_col0); - CUDF_TEST_EXPECT_COLUMNS_EQUAL(s_col1, s_col1); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + s_col0, s_col0, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); + CUDF_TEST_EXPECT_COLUMNS_EQUAL( + s_col1, s_col1, cudf::test::debug_output_level::FIRST_ERROR, stream, mr); } CUDF_TEST_PROGRAM_MAIN() diff --git a/cpp/tests/utilities_tests/column_wrapper_tests.cpp b/cpp/tests/utilities_tests/column_wrapper_tests.cpp index 34a58ec6184c..67da303b8610 100644 --- a/cpp/tests/utilities_tests/column_wrapper_tests.cpp +++ b/cpp/tests/utilities_tests/column_wrapper_tests.cpp @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION. + * SPDX-FileCopyrightText: Copyright (c) 2019-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. * SPDX-License-Identifier: Apache-2.0 */ @@ -7,15 +7,220 @@ #include #include #include +#include #include #include #include +#include #include +using cudf::test::expect_output_uses_distinct_resources; +using cudf::test::temporary_allocation_expectation; + +namespace { +auto const uses_temporary = cudf::test::memory_resource_expectations{ + cudf::test::output_allocation_expectation::EXACT, temporary_allocation_expectation::SOME}; +} // namespace + +TEST(FixedPointColumnWrapperMemoryResourceTest, DistinctOutputAndTemporaryResources) +{ + auto stream = cudf::test::get_default_stream(); + auto const elements = std::vector{1, 2, 3, 4}; + auto const validity = std::vector{true, false, true, false}; + auto const scale = numeric::scale_type{-2}; + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::fixed_point_column_wrapper( + elements.begin(), elements.end(), scale, stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::fixed_point_column_wrapper( + {1, 2, 3, 4}, scale, stream, mr.get_output_mr()); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::fixed_point_column_wrapper( + elements.begin(), elements.end(), validity.begin(), scale, stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::fixed_point_column_wrapper( + {1, 2, 3, 4}, {true, false, true, false}, scale, stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::fixed_point_column_wrapper( + {1, 2, 3, 4}, validity.begin(), scale, stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::fixed_point_column_wrapper( + elements.begin(), elements.end(), {true, false, true, false}, scale, stream, mr); + }); +} + +TEST(StringsColumnWrapperMemoryResourceTest, DistinctOutputAndTemporaryResources) +{ + auto stream = cudf::test::get_default_stream(); + auto const strings = std::vector{"", "alpha", "beta", "gamma"}; + auto const validity = std::vector{true, false, true, false}; + + expect_output_uses_distinct_resources( + [&](auto mr) { return cudf::test::strings_column_wrapper(stream, mr); }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::strings_column_wrapper(strings.begin(), strings.end(), stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::strings_column_wrapper( + {"", "alpha", "beta", "gamma"}, stream, mr.get_output_mr()); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::strings_column_wrapper( + strings.begin(), strings.end(), validity.begin(), stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::strings_column_wrapper( + {"", "alpha", "beta", "gamma"}, validity.begin(), stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::strings_column_wrapper( + {"", "alpha", "beta", "gamma"}, {true, false, true, false}, stream, mr); + }); + + expect_output_uses_distinct_resources([&](auto mr) { + using pair_type = std::pair; + return cudf::test::strings_column_wrapper( + {pair_type{"", true}, pair_type{"alpha", false}, pair_type{"beta", true}}, stream, mr); + }); +} + +TEST(DictionaryColumnWrapperMemoryResourceTest, FixedWidthDistinctOutputAndTemporaryResources) +{ + auto stream = cudf::test::get_default_stream(); + auto const elements = std::vector{3, 1, 3, 2}; + auto const validity = std::vector{true, false, true, true}; + + // Intermediate fixed-width column is allocated on temporary_mr before encode. + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + elements.begin(), elements.end(), stream, mr); + }, + uses_temporary); + + // Single-ref overload: temporaries go to the current resource, not the harness temporary. + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::dictionary_column_wrapper({3, 1, 3, 2}, stream, mr.get_output_mr()); + }); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + elements.begin(), elements.end(), validity.begin(), stream, mr); + }, + uses_temporary); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + {3, 1, 3, 2}, validity.begin(), stream, mr); + }, + uses_temporary); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + {3, 1, 3, 2}, {true, false, true, true}, stream, mr); + }, + uses_temporary); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + elements.begin(), elements.end(), {true, false, true, true}, stream, mr); + }, + uses_temporary); +} + +TEST(DictionaryColumnWrapperMemoryResourceTest, EmptyStringDictionaryPreservesChildTypes) +{ + expect_output_uses_distinct_resources([&](auto mr) { + auto wrapper = + cudf::test::dictionary_column_wrapper(cudf::test::get_default_stream(), mr); + auto dictionary = cudf::dictionary_column_view{static_cast(wrapper)}; + + EXPECT_EQ(0, static_cast(wrapper).size()); + EXPECT_EQ(cudf::type_id::STRING, dictionary.keys().type().id()); + EXPECT_EQ(cudf::type_id::INT32, dictionary.indices().type().id()); + return wrapper; + }); +} + +TEST(DictionaryColumnWrapperMemoryResourceTest, StringDistinctOutputAndTemporaryResources) +{ + auto stream = cudf::test::get_default_stream(); + auto const strings = std::vector{"gamma", "alpha", "gamma", "beta"}; + auto const validity = std::vector{true, false, true, true}; + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + strings.begin(), strings.end(), stream, mr); + }, + uses_temporary); + + // Single-ref overload: temporaries go to the current resource, not the harness temporary. + expect_output_uses_distinct_resources([&](auto mr) { + return cudf::test::dictionary_column_wrapper( + {"gamma", "alpha", "gamma", "beta"}, stream, mr.get_output_mr()); + }); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + strings.begin(), strings.end(), validity.begin(), stream, mr); + }, + uses_temporary); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + {"gamma", "alpha", "gamma", "beta"}, validity.begin(), stream, mr); + }, + uses_temporary); + + expect_output_uses_distinct_resources( + [&](auto mr) { + return cudf::test::dictionary_column_wrapper( + {"gamma", "alpha", "gamma", "beta"}, {true, false, true, true}, stream, mr); + }, + uses_temporary); +} + +struct ColumnWrapperTestWithHarness : public cudf::test::BaseFixtureWithHarness { + /** + * @brief Validate that the harness owns the given result. + * + * Assert that the harness output resource holds bytes equal to `col->alloc_size()` and that no + * temporary allocations remain live. `col` is destroyed on return, so `TearDown` can additionally + * confirm that the output bytes were released. + */ + void validate_with_harness(std::unique_ptr col) + { + _harness.expect_resource_usage(col->alloc_size(), {}, this->stream()); + } +}; + template -struct FixedWidthColumnWrapperTest : public cudf::test::BaseFixture, +struct FixedWidthColumnWrapperTest : public ColumnWrapperTestWithHarness, cudf::test::UniformRandomGenerator { FixedWidthColumnWrapperTest() : cudf::test::UniformRandomGenerator{1000, 5000} {} @@ -30,7 +235,7 @@ TYPED_TEST(FixedWidthColumnWrapperTest, EmptyIterator) { auto sequence = cuda::counting_iterator{0}; cudf::test::fixed_width_column_wrapper col( - sequence, sequence); + sequence, sequence, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 0); EXPECT_EQ(view.head(), nullptr); @@ -38,10 +243,12 @@ TYPED_TEST(FixedWidthColumnWrapperTest, EmptyIterator) EXPECT_FALSE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, EmptyList) { - cudf::test::fixed_width_column_wrapper col{}; + cudf::test::fixed_width_column_wrapper col(this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 0); EXPECT_EQ(view.head(), nullptr); @@ -49,6 +256,8 @@ TYPED_TEST(FixedWidthColumnWrapperTest, EmptyList) EXPECT_FALSE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NonNullableIteratorConstructor) @@ -58,7 +267,7 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NonNullableIteratorConstructor) auto size = this->size(); cudf::test::fixed_width_column_wrapper col( - sequence, sequence + size); + sequence, sequence + size, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), size); EXPECT_NE(nullptr, view.head()); @@ -66,11 +275,14 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NonNullableIteratorConstructor) EXPECT_FALSE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NonNullableListConstructor) { - cudf::test::fixed_width_column_wrapper col({1, 2, 3, 4, 5}); + cudf::test::fixed_width_column_wrapper col( + {1, 2, 3, 4, 5}, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 5); @@ -79,6 +291,8 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NonNullableListConstructor) EXPECT_FALSE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NullableIteratorConstructorAllValid) @@ -90,7 +304,7 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullableIteratorConstructorAllValid) auto size = this->size(); cudf::test::fixed_width_column_wrapper col( - sequence, sequence + size, all_valid); + sequence, sequence + size, all_valid, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), size); EXPECT_NE(nullptr, view.head()); @@ -98,13 +312,16 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullableIteratorConstructorAllValid) EXPECT_TRUE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NullableListConstructorAllValid) { auto all_valid = cudf::test::iterators::no_nulls(); - cudf::test::fixed_width_column_wrapper col({1, 2, 3, 4, 5}, all_valid); + cudf::test::fixed_width_column_wrapper col( + {1, 2, 3, 4, 5}, all_valid, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 5); EXPECT_NE(nullptr, view.head()); @@ -112,6 +329,8 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullableListConstructorAllValid) EXPECT_TRUE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NullableIteratorConstructorAllNull) @@ -123,7 +342,7 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullableIteratorConstructorAllNull) auto size = this->size(); cudf::test::fixed_width_column_wrapper col( - sequence, sequence + size, all_null); + sequence, sequence + size, all_null, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), size); EXPECT_NE(nullptr, view.head()); @@ -132,13 +351,16 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullableIteratorConstructorAllNull) EXPECT_TRUE(view.has_nulls()); EXPECT_EQ(view.null_count(), size); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NullableListConstructorAllNull) { auto all_null = cudf::test::iterators::all_nulls(); - cudf::test::fixed_width_column_wrapper col({1, 2, 3, 4, 5}, all_null); + cudf::test::fixed_width_column_wrapper col( + {1, 2, 3, 4, 5}, all_null, this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 5); EXPECT_NE(nullptr, view.head()); @@ -147,13 +369,17 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullableListConstructorAllNull) EXPECT_TRUE(view.has_nulls()); EXPECT_EQ(view.null_count(), 5); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NullablePairListConstructorAllNull) { using p = std::pair; cudf::test::fixed_width_column_wrapper col( - {p{1, false}, p{2, false}, p{3, false}, p{4, false}, p{5, false}}); + {p{1, false}, p{2, false}, p{3, false}, p{4, false}, p{5, false}}, + this->stream(), + this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 5); @@ -163,13 +389,16 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullablePairListConstructorAllNull) EXPECT_TRUE(view.has_nulls()); EXPECT_EQ(view.null_count(), 5); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(FixedWidthColumnWrapperTest, NullablePairListConstructorAllNullMatch) { auto odd_valid = cudf::test::iterators::nulls_at_multiples_of(2); - cudf::test::fixed_width_column_wrapper match_col({1, 2, 3, 4, 5}, odd_valid); + cudf::test::fixed_width_column_wrapper match_col( + {1, 2, 3, 4, 5}, odd_valid, this->stream(), this->resources()); cudf::column_view match_view = match_col; using p = std::pair; @@ -177,17 +406,24 @@ TYPED_TEST(FixedWidthColumnWrapperTest, NullablePairListConstructorAllNullMatch) p{2, odd_valid[1]}, p{3, odd_valid[2]}, p{4, odd_valid[3]}, - p{5, odd_valid[4]}}); + p{5, odd_valid[4]}}, + this->stream(), + this->resources()); cudf::column_view view = col; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(view, match_view); + CUDF_TEST_EXPECT_COLUMNS_EQUAL(view, + match_view, + cudf::test::debug_output_level::FIRST_ERROR, + this->stream(), + this->resources()); } TYPED_TEST(FixedWidthColumnWrapperTest, ReleaseWrapperAllValid) { auto all_valid = cudf::test::iterators::no_nulls(); - cudf::test::fixed_width_column_wrapper col({1, 2, 3, 4, 5}, all_valid); + cudf::test::fixed_width_column_wrapper col( + {1, 2, 3, 4, 5}, all_valid, this->stream(), this->resources()); auto colPtr = col.release(); cudf::column_view view = *colPtr; EXPECT_EQ(view.size(), 5); @@ -196,13 +432,16 @@ TYPED_TEST(FixedWidthColumnWrapperTest, ReleaseWrapperAllValid) EXPECT_TRUE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(std::move(colPtr)); } TYPED_TEST(FixedWidthColumnWrapperTest, ReleaseWrapperAllNull) { auto all_null = cudf::test::iterators::all_nulls(); - cudf::test::fixed_width_column_wrapper col({1, 2, 3, 4, 5}, all_null); + cudf::test::fixed_width_column_wrapper col( + {1, 2, 3, 4, 5}, all_null, this->stream(), this->resources()); auto colPtr = col.release(); cudf::column_view view = *colPtr; EXPECT_EQ(view.size(), 5); @@ -212,11 +451,12 @@ TYPED_TEST(FixedWidthColumnWrapperTest, ReleaseWrapperAllNull) EXPECT_TRUE(view.has_nulls()); EXPECT_EQ(view.null_count(), 5); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(std::move(colPtr)); } template -struct StringsColumnWrapperTest : public cudf::test::BaseFixture, - cudf::test::UniformRandomGenerator { +struct StringsColumnWrapperTest : public ColumnWrapperTestWithHarness { auto data_type() { return cudf::data_type{cudf::type_to_id()}; } }; @@ -224,7 +464,7 @@ TYPED_TEST_SUITE(StringsColumnWrapperTest, cudf::test::StringTypes); TYPED_TEST(StringsColumnWrapperTest, EmptyList) { - cudf::test::strings_column_wrapper col; + cudf::test::strings_column_wrapper col(this->stream(), this->resources()); cudf::column_view view = col; EXPECT_EQ(view.size(), 0); EXPECT_EQ(view.head(), nullptr); @@ -232,13 +472,17 @@ TYPED_TEST(StringsColumnWrapperTest, EmptyList) EXPECT_FALSE(view.nullable()); EXPECT_FALSE(view.has_nulls()); EXPECT_EQ(view.offset(), 0); + + this->validate_with_harness(col.release()); } TYPED_TEST(StringsColumnWrapperTest, NullablePairListConstructorAllNull) { using p = std::pair; cudf::test::strings_column_wrapper col( - {p{"a", false}, p{"string", false}, p{"test", false}, p{"for", false}, p{"nulls", false}}); + {p{"a", false}, p{"string", false}, p{"test", false}, p{"for", false}, p{"nulls", false}}, + this->stream(), + this->resources()); cudf::strings_column_view view = cudf::column_view(col); constexpr auto count = 5; @@ -249,14 +493,16 @@ TYPED_TEST(StringsColumnWrapperTest, NullablePairListConstructorAllNull) EXPECT_NE(nullptr, view.offsets().head()); EXPECT_TRUE(view.has_nulls()); EXPECT_EQ(view.null_count(), 5); + + this->validate_with_harness(col.release()); } TYPED_TEST(StringsColumnWrapperTest, NullablePairListConstructorAllNullMatch) { auto odd_valid = cudf::test::iterators::nulls_at_multiples_of(2); - cudf::test::strings_column_wrapper match_col({"a", "string", "", "test", "for", "nulls"}, - odd_valid); + cudf::test::strings_column_wrapper match_col( + {"a", "string", "", "test", "for", "nulls"}, odd_valid, this->stream(), this->resources()); cudf::column_view match_view = match_col; using p = std::pair; @@ -265,8 +511,14 @@ TYPED_TEST(StringsColumnWrapperTest, NullablePairListConstructorAllNullMatch) p{"", odd_valid[2]}, p{"test", odd_valid[3]}, p{"for", odd_valid[4]}, - p{"nulls", odd_valid[5]}}); + p{"nulls", odd_valid[5]}}, + this->stream(), + this->resources()); cudf::column_view view = col; - CUDF_TEST_EXPECT_COLUMNS_EQUAL(view, match_view); + CUDF_TEST_EXPECT_COLUMNS_EQUAL(view, + match_view, + cudf::test::debug_output_level::FIRST_ERROR, + this->stream(), + this->resources()); } diff --git a/cpp/tests/wrappers/timestamps_test.cu b/cpp/tests/wrappers/timestamps_test.cu index e3af3a50ff54..b91444b6f614 100644 --- a/cpp/tests/wrappers/timestamps_test.cu +++ b/cpp/tests/wrappers/timestamps_test.cu @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,27 @@ struct compare_chrono_elements_to_primitive_representation { }; } // namespace +template +void expect_timestamp_output_uses_resource() +{ + using namespace cuda::std::chrono; + + cudf::test::expect_output_uses_distinct_resources([](auto resources) { + return cudf::test::generate_timestamps( + 100, + cudf::test::time_point_ms{milliseconds{-1000}}, + cudf::test::time_point_ms{milliseconds{1000}}, + cudf::test::get_default_stream(), + resources); + }); +} + +TEST(TimestampGeneratorMemoryResourceTest, DistinctOutputAndTemporaryResources) +{ + expect_timestamp_output_uses_resource(); + expect_timestamp_output_uses_resource(); +} + TYPED_TEST_SUITE(ChronoColumnTest, cudf::test::ChronoTypes); TYPED_TEST(ChronoColumnTest, ChronoDurationsMatchPrimitiveRepresentation)