Skip to content

Commit ccc6b63

Browse files
authored
Add cuda::std::span operator to cudf::column_view (#20541)
Adds a `cuda::std::span` operator to the `cudf::column_view` class to allow passing a column view instance directly to a span parameter or variable. Authors: - David Wendt (https://github.com/davidwendt) Approvers: - Karthikeyan (https://github.com/karthikeyann) - Bradley Dice (https://github.com/bdice) URL: #20541
1 parent d62b0ac commit ccc6b63

File tree

2 files changed

+85
-7
lines changed

2 files changed

+85
-7
lines changed

cpp/include/cudf/column/column_view.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <cudf/utilities/traits.hpp>
1212
#include <cudf/utilities/type_dispatcher.hpp>
1313

14+
#include <cuda/std/span>
15+
1416
#include <limits>
1517
#include <type_traits>
1618
#include <vector>
@@ -450,6 +452,26 @@ class column_view : public detail::column_view_base {
450452
return device_span<T const>(data<T>(), size());
451453
}
452454

455+
/**
456+
* @brief Converts a column view into a cuda::std::span.
457+
*
458+
* Only numeric and chrono data types are supported. The column view must not
459+
* be nullable.
460+
*
461+
* @tparam T The device span type. Must be const and match the column view's type.
462+
* @throws cudf::logic_error if the column view type does not match the span type.
463+
* @throws cudf::logic_error if the column view is nullable.
464+
* @return A span of the column view's data
465+
*/
466+
template <typename T, CUDF_ENABLE_IF(cudf::is_numeric<T>() or cudf::is_chrono<T>())>
467+
[[nodiscard]] operator cuda::std::span<T const>() const
468+
{
469+
CUDF_EXPECTS(type() == cudf::data_type{cudf::type_to_id<T>()},
470+
"Span type must match column view type");
471+
CUDF_EXPECTS(!nullable(), "A nullable column view cannot be converted to a span.");
472+
return cuda::std::span<T const>(data<T>(), size());
473+
}
474+
453475
protected:
454476
/**
455477
* @brief Returns pointer to the base device memory allocation.

cpp/tests/column/column_view_device_span_test.cpp

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION.
2+
* SPDX-FileCopyrightText: Copyright (c) 2022-2025, NVIDIA CORPORATION.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

@@ -14,6 +14,7 @@
1414
#include <cudf/utilities/span.hpp>
1515
#include <cudf/utilities/traits.hpp>
1616

17+
#include <cuda/std/span>
1718
#include <thrust/iterator/counting_iterator.h>
1819

1920
#include <memory>
@@ -27,12 +28,12 @@ std::unique_ptr<cudf::column> example_column()
2728
}
2829

2930
template <typename T>
30-
struct ColumnViewDeviceSpanTests : public cudf::test::BaseFixture {};
31+
struct ColumnViewSpanTests : public cudf::test::BaseFixture {};
3132

3233
using DeviceSpanTypes = cudf::test::FixedWidthTypesWithoutFixedPoint;
33-
TYPED_TEST_SUITE(ColumnViewDeviceSpanTests, DeviceSpanTypes);
34+
TYPED_TEST_SUITE(ColumnViewSpanTests, DeviceSpanTypes);
3435

35-
TYPED_TEST(ColumnViewDeviceSpanTests, conversion_round_trip)
36+
TYPED_TEST(ColumnViewSpanTests, device_span_conversion_round_trip)
3637
{
3738
auto col = example_column<TypeParam>();
3839
auto col_view = cudf::column_view{*col};
@@ -43,19 +44,74 @@ TYPED_TEST(ColumnViewDeviceSpanTests, conversion_round_trip)
4344
CUDF_TEST_EXPECT_COLUMNS_EQUAL(col_view, col_view_from_device_span);
4445
}
4546

46-
struct ColumnViewDeviceSpanErrorTests : public cudf::test::BaseFixture {};
47+
struct ColumnViewSpanErrorTests : public cudf::test::BaseFixture {};
4748

48-
TEST_F(ColumnViewDeviceSpanErrorTests, type_mismatch)
49+
TEST_F(ColumnViewSpanErrorTests, device_span_type_mismatch)
4950
{
5051
auto col = example_column<int32_t>();
5152
auto col_view = cudf::column_view{*col};
5253
EXPECT_THROW((void)cudf::device_span<float const>{col_view}, cudf::logic_error);
5354
}
5455

55-
TEST_F(ColumnViewDeviceSpanErrorTests, nullable_column)
56+
TEST_F(ColumnViewSpanErrorTests, device_span_nullable_column)
5657
{
5758
auto col = example_column<int32_t>();
5859
col->set_null_mask(cudf::create_null_mask(col->size(), cudf::mask_state::ALL_NULL), col->size());
5960
auto col_view = cudf::column_view{*col};
6061
EXPECT_THROW((void)cudf::device_span<int32_t const>{col_view}, cudf::logic_error);
6162
}
63+
64+
TYPED_TEST(ColumnViewSpanTests, std_span_conversion_to_span)
65+
{
66+
auto col = example_column<TypeParam>();
67+
auto col_view = cudf::column_view{*col};
68+
69+
// Test implicit conversion to cuda::std::span
70+
cuda::std::span<TypeParam const> cuda_span_from_col_view = col_view;
71+
72+
// Verify span properties match column view
73+
EXPECT_EQ(cuda_span_from_col_view.size(), static_cast<std::size_t>(col_view.size()));
74+
EXPECT_EQ(cuda_span_from_col_view.data(), col_view.data<TypeParam>());
75+
EXPECT_FALSE(cuda_span_from_col_view.empty());
76+
}
77+
78+
TYPED_TEST(ColumnViewSpanTests, std_span_explicit_conversion_to_span)
79+
{
80+
auto col = example_column<TypeParam>();
81+
auto col_view = cudf::column_view{*col};
82+
83+
// Test explicit conversion to cuda::std::span
84+
auto cuda_span_from_col_view = static_cast<cuda::std::span<TypeParam const>>(col_view);
85+
86+
// Verify span properties match column view
87+
EXPECT_EQ(cuda_span_from_col_view.size(), static_cast<std::size_t>(col_view.size()));
88+
EXPECT_EQ(cuda_span_from_col_view.data(), col_view.data<TypeParam>());
89+
}
90+
91+
TYPED_TEST(ColumnViewSpanTests, std_span_empty_column_to_span)
92+
{
93+
cudf::test::fixed_width_column_wrapper<TypeParam> empty_col{};
94+
auto col_view = cudf::column_view{empty_col};
95+
96+
// Test conversion of empty column to cuda::std::span
97+
cuda::std::span<TypeParam const> cuda_span_from_col_view = col_view;
98+
99+
// Verify span properties for empty column
100+
EXPECT_EQ(cuda_span_from_col_view.size(), 0u);
101+
EXPECT_TRUE(cuda_span_from_col_view.empty());
102+
}
103+
104+
TEST_F(ColumnViewSpanErrorTests, std_span_type_mismatch)
105+
{
106+
auto col = example_column<int32_t>();
107+
auto col_view = cudf::column_view{*col};
108+
EXPECT_THROW((void)cuda::std::span<float const>{col_view}, cudf::logic_error);
109+
}
110+
111+
TEST_F(ColumnViewSpanErrorTests, std_span_nullable_column)
112+
{
113+
auto col = example_column<int32_t>();
114+
col->set_null_mask(cudf::create_null_mask(col->size(), cudf::mask_state::ALL_NULL), col->size());
115+
auto col_view = cudf::column_view{*col};
116+
EXPECT_THROW((void)cuda::std::span<int32_t const>{col_view}, cudf::logic_error);
117+
}

0 commit comments

Comments
 (0)