diff --git a/cpp/include/cudf/column/column_view.hpp b/cpp/include/cudf/column/column_view.hpp index 325f023f283..ba15e37f9ea 100644 --- a/cpp/include/cudf/column/column_view.hpp +++ b/cpp/include/cudf/column/column_view.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019-2021, NVIDIA CORPORATION. + * Copyright (c) 2019-2022, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,8 +16,13 @@ #pragma once #include +#include +#include #include +#include +#include +#include #include /** @@ -375,6 +380,43 @@ class column_view : public detail::column_view_base { */ auto child_end() const noexcept { return _children.cend(); } + /** + * @brief Construct a column view from a device_span. + * + * Only numeric and chrono types are supported. + * + * @tparam T The device span type. Must be const and match the column view's type. + * @param data A typed device span containing the column view's data. + */ + template () or cudf::is_chrono())> + column_view(device_span data) + : column_view( + cudf::data_type{cudf::type_to_id()}, data.size(), data.data(), nullptr, 0, 0, {}) + { + CUDF_EXPECTS(data.size() < std::numeric_limits::max(), + "Data exceeds the maximum size of a column view."); + } + + /** + * @brief Converts a column view into a device span. + * + * Only numeric and chrono data types are supported. The column view must not + * be nullable. + * + * @tparam T The device span type. Must be const and match the column view's type. + * @throws cudf::logic_error if the column view type does not match the span type. + * @throws cudf::logic_error if the column view is nullable. + * @return A typed device span of the column view's data. + */ + template () or cudf::is_chrono())> + [[nodiscard]] operator device_span() const + { + CUDF_EXPECTS(type() == cudf::data_type{cudf::type_to_id()}, + "Device span type must match column view type."); + CUDF_EXPECTS(!nullable(), "A nullable column view cannot be converted to a device span."); + return device_span(data(), size()); + } + private: friend column_view bit_cast(column_view const& input, data_type type); diff --git a/cpp/include/cudf/utilities/span.hpp b/cpp/include/cudf/utilities/span.hpp index 0ac41b2c4a1..bfaf4694693 100644 --- a/cpp/include/cudf/utilities/span.hpp +++ b/cpp/include/cudf/utilities/span.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020-2021, NVIDIA CORPORATION. + * Copyright (c) 2020-2022, NVIDIA CORPORATION. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index 27dd472b3f5..a633fb74a72 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -41,8 +41,13 @@ endfunction() # ################################################################################################## # * column tests ---------------------------------------------------------------------------------- ConfigureTest( - COLUMN_TEST column/bit_cast_test.cpp column/column_view_shallow_test.cpp column/column_test.cu - column/column_device_view_test.cu column/compound_test.cu + COLUMN_TEST + column/bit_cast_test.cpp + column/column_device_view_test.cu + column/column_test.cu + column/column_view_device_span_test.cpp + column/column_view_shallow_test.cpp + column/compound_test.cu ) # ################################################################################################## diff --git a/cpp/tests/column/column_view_device_span_test.cpp b/cpp/tests/column/column_view_device_span_test.cpp new file mode 100644 index 00000000000..2b7ea3b3650 --- /dev/null +++ b/cpp/tests/column/column_view_device_span_test.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022, NVIDIA CORPORATION. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +template () or cudf::is_chrono())> +std::unique_ptr example_column() +{ + auto begin = thrust::make_counting_iterator(1); + auto end = thrust::make_counting_iterator(16); + return cudf::test::fixed_width_column_wrapper(begin, end).release(); +} + +template +struct ColumnViewDeviceSpanTests : public cudf::test::BaseFixture { +}; + +using DeviceSpanTypes = cudf::test::FixedWidthTypesWithoutFixedPoint; +TYPED_TEST_SUITE(ColumnViewDeviceSpanTests, DeviceSpanTypes); + +TYPED_TEST(ColumnViewDeviceSpanTests, conversion_round_trip) +{ + auto col = example_column(); + auto col_view = cudf::column_view{*col}; + + // Test implicit conversion, round trip + cudf::device_span device_span_from_col_view = col_view; + cudf::column_view col_view_from_device_span = device_span_from_col_view; + CUDF_TEST_EXPECT_COLUMNS_EQUAL(col_view, col_view_from_device_span); +} + +struct ColumnViewDeviceSpanErrorTests : public cudf::test::BaseFixture { +}; + +TEST_F(ColumnViewDeviceSpanErrorTests, type_mismatch) +{ + auto col = example_column(); + auto col_view = cudf::column_view{*col}; + EXPECT_THROW((void)cudf::device_span{col_view}, cudf::logic_error); +} + +TEST_F(ColumnViewDeviceSpanErrorTests, nullable_column) +{ + auto col = example_column(); + col->set_null_mask(cudf::create_null_mask(col->size(), cudf::mask_state::ALL_NULL), col->size()); + auto col_view = cudf::column_view{*col}; + EXPECT_THROW((void)cudf::device_span{col_view}, cudf::logic_error); +}