From 12eed7715e852059e9690db2e7ec1f9daaf3ac5d Mon Sep 17 00:00:00 2001 From: Lawrence Mitchell Date: Wed, 10 Jul 2024 13:18:43 +0000 Subject: [PATCH 1/4] Expose reflection to check if casting between two types is supported --- cpp/include/cudf/detail/unary.hpp | 5 +++++ cpp/include/cudf/unary.hpp | 10 ++++++++++ cpp/src/unary/cast_ops.cu | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/cpp/include/cudf/detail/unary.hpp b/cpp/include/cudf/detail/unary.hpp index 5245cfdf079..31111bec113 100644 --- a/cpp/include/cudf/detail/unary.hpp +++ b/cpp/include/cudf/detail/unary.hpp @@ -86,6 +86,11 @@ std::unique_ptr cast(column_view const& input, rmm::cuda_stream_view stream, rmm::device_async_resource_ref mr); +/** + * @copydoc cudf::is_supported_cast + */ +bool is_supported_cast(data_type from, data_type to) noexcept; + /** * @copydoc cudf::is_nan */ diff --git a/cpp/include/cudf/unary.hpp b/cpp/include/cudf/unary.hpp index 74c8bc67d3a..a1825ffccfe 100644 --- a/cpp/include/cudf/unary.hpp +++ b/cpp/include/cudf/unary.hpp @@ -202,6 +202,16 @@ std::unique_ptr cast( rmm::cuda_stream_view stream = cudf::get_default_stream(), rmm::device_async_resource_ref mr = rmm::mr::get_current_device_resource()); +/** + * @brief Check if a cast between two datatypes is supported. + * + * @param from source type + * @param to target type + * + * @returns true if the cast is supported. + */ +bool is_supported_cast(data_type from, data_type to) noexcept; + /** * @brief Creates a column of `type_id::BOOL8` elements indicating the presence of `NaN` values * in a column of floating point values. diff --git a/cpp/src/unary/cast_ops.cu b/cpp/src/unary/cast_ops.cu index 64427326d87..0ddf805a260 100644 --- a/cpp/src/unary/cast_ops.cu +++ b/cpp/src/unary/cast_ops.cu @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -459,6 +460,19 @@ std::unique_ptr cast(column_view const& input, return type_dispatcher(input.type(), detail::dispatch_unary_cast_from{input}, type, stream, mr); } +struct is_supported_cast_impl { + template + bool operator()() const + { + return is_supported_cast(); + } +}; + +bool is_supported_cast(data_type from, data_type to) noexcept +{ + return double_type_dispatcher(from, to, is_supported_cast_impl{}); +} + } // namespace detail std::unique_ptr cast(column_view const& input, @@ -470,4 +484,10 @@ std::unique_ptr cast(column_view const& input, return detail::cast(input, type, stream, mr); } +bool is_supported_cast(data_type from, data_type to) noexcept +{ + CUDF_FUNC_RANGE(); + return detail::is_supported_cast(from, to); +} + } // namespace cudf From 2ef12eb5d6cbdd59d98944dc83e5703a831264aa Mon Sep 17 00:00:00 2001 From: Lawrence Mitchell Date: Wed, 10 Jul 2024 13:23:40 +0000 Subject: [PATCH 2/4] Expose new is_supported_cast in pylibcudf --- .../cudf/_lib/pylibcudf/libcudf/unary.pxd | 1 + python/cudf/cudf/_lib/pylibcudf/unary.pyx | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd b/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd index 7f8ae2b7617..f092ddeca89 100644 --- a/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd +++ b/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd @@ -43,5 +43,6 @@ cdef extern from "cudf/unary.hpp" namespace "cudf" nogil: cdef extern unique_ptr[column] cast( column_view input, data_type out_type) except + + cdef extern bool is_supported_cast(data_type from_, data_type to) noexcept cdef extern unique_ptr[column] is_nan(column_view input) except + cdef extern unique_ptr[column] is_not_nan(column_view input) except + diff --git a/python/cudf/cudf/_lib/pylibcudf/unary.pyx b/python/cudf/cudf/_lib/pylibcudf/unary.pyx index 0879b501a49..b5c57d761b6 100644 --- a/python/cudf/cudf/_lib/pylibcudf/unary.pyx +++ b/python/cudf/cudf/_lib/pylibcudf/unary.pyx @@ -154,3 +154,23 @@ cpdef Column is_not_nan(Column input): result = move(cpp_unary.is_not_nan(input.view())) return Column.from_libcudf(move(result)) + +cpdef bool is_supported_cast(DataType from_, DataType to): + """Check if a cast between datatypes is supported. + + For details, see :cpp:func:`is_supported_cast`. + + Parameters + ---------- + from_ + The source datatype + to + The target datatype + + Returns + ------- + bool + True if the cast is supported. + """ + with nogil: + return cpp_unary.is_supported_cast(from_, to) From 5bbd380e7ee55a9fef7b67c57c5aed36e4c5752b Mon Sep 17 00:00:00 2001 From: Lawrence Mitchell Date: Wed, 10 Jul 2024 15:28:30 +0000 Subject: [PATCH 3/4] Add pylibcudf tests and fix bugs --- .../cudf/_lib/pylibcudf/libcudf/unary.pxd | 1 + python/cudf/cudf/_lib/pylibcudf/unary.pxd | 4 ++++ python/cudf/cudf/_lib/pylibcudf/unary.pyx | 3 ++- .../cudf/cudf/pylibcudf_tests/test_unary.py | 19 +++++++++++++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 python/cudf/cudf/pylibcudf_tests/test_unary.py diff --git a/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd b/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd index f092ddeca89..2a1b189af51 100644 --- a/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd +++ b/python/cudf/cudf/_lib/pylibcudf/libcudf/unary.pxd @@ -1,6 +1,7 @@ # Copyright (c) 2020-2024, NVIDIA CORPORATION. from libc.stdint cimport int32_t +from libcpp cimport bool from libcpp.memory cimport unique_ptr from cudf._lib.pylibcudf.libcudf.column.column cimport column diff --git a/python/cudf/cudf/_lib/pylibcudf/unary.pxd b/python/cudf/cudf/_lib/pylibcudf/unary.pxd index 4aa4543bb80..d07df838172 100644 --- a/python/cudf/cudf/_lib/pylibcudf/unary.pxd +++ b/python/cudf/cudf/_lib/pylibcudf/unary.pxd @@ -1,5 +1,7 @@ # Copyright (c) 2024, NVIDIA CORPORATION. +from libcpp cimport bool + from cudf._lib.pylibcudf.libcudf.unary cimport unary_operator from .column cimport Column @@ -17,3 +19,5 @@ cpdef Column cast(Column input, DataType data_type) cpdef Column is_nan(Column input) cpdef Column is_not_nan(Column input) + +cpdef bool is_supported_cast(DataType from_, DataType to) diff --git a/python/cudf/cudf/_lib/pylibcudf/unary.pyx b/python/cudf/cudf/_lib/pylibcudf/unary.pyx index b5c57d761b6..8da46f0a832 100644 --- a/python/cudf/cudf/_lib/pylibcudf/unary.pyx +++ b/python/cudf/cudf/_lib/pylibcudf/unary.pyx @@ -1,5 +1,6 @@ # Copyright (c) 2024, NVIDIA CORPORATION. +from libcpp cimport bool from libcpp.memory cimport unique_ptr from libcpp.utility cimport move @@ -173,4 +174,4 @@ cpdef bool is_supported_cast(DataType from_, DataType to): True if the cast is supported. """ with nogil: - return cpp_unary.is_supported_cast(from_, to) + return cpp_unary.is_supported_cast(from_.c_obj, to.c_obj) diff --git a/python/cudf/cudf/pylibcudf_tests/test_unary.py b/python/cudf/cudf/pylibcudf_tests/test_unary.py new file mode 100644 index 00000000000..b5e4f0cb0e8 --- /dev/null +++ b/python/cudf/cudf/pylibcudf_tests/test_unary.py @@ -0,0 +1,19 @@ +# Copyright (c) 2024, NVIDIA CORPORATION. + +from cudf._lib import pylibcudf as plc + + +def test_is_supported_cast(): + assert plc.unary.is_supported_cast( + plc.DataType(plc.TypeId.INT8), plc.DataType(plc.TypeId.UINT64) + ) + assert plc.unary.is_supported_cast( + plc.DataType(plc.TypeId.DURATION_MILLISECONDS), + plc.DataType(plc.TypeId.UINT64), + ) + assert not plc.unary.is_supported_cast( + plc.DataType(plc.TypeId.INT32), plc.DataType(plc.TypeId.TIMESTAMP_DAYS) + ) + assert not plc.unary.is_supported_cast( + plc.DataType(plc.TypeId.INT32), plc.DataType(plc.TypeId.STRING) + ) From f36e3bc308268e4ac483ac02b8674a5cde71e5b2 Mon Sep 17 00:00:00 2001 From: Lawrence Mitchell Date: Thu, 11 Jul 2024 07:51:01 +0000 Subject: [PATCH 4/4] Remove detail/public split and nvtx range --- cpp/include/cudf/detail/unary.hpp | 5 ----- cpp/src/unary/cast_ops.cu | 10 +++------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/cpp/include/cudf/detail/unary.hpp b/cpp/include/cudf/detail/unary.hpp index 31111bec113..5245cfdf079 100644 --- a/cpp/include/cudf/detail/unary.hpp +++ b/cpp/include/cudf/detail/unary.hpp @@ -86,11 +86,6 @@ std::unique_ptr cast(column_view const& input, rmm::cuda_stream_view stream, rmm::device_async_resource_ref mr); -/** - * @copydoc cudf::is_supported_cast - */ -bool is_supported_cast(data_type from, data_type to) noexcept; - /** * @copydoc cudf::is_nan */ diff --git a/cpp/src/unary/cast_ops.cu b/cpp/src/unary/cast_ops.cu index 0ddf805a260..ec21813705a 100644 --- a/cpp/src/unary/cast_ops.cu +++ b/cpp/src/unary/cast_ops.cu @@ -468,11 +468,6 @@ struct is_supported_cast_impl { } }; -bool is_supported_cast(data_type from, data_type to) noexcept -{ - return double_type_dispatcher(from, to, is_supported_cast_impl{}); -} - } // namespace detail std::unique_ptr cast(column_view const& input, @@ -486,8 +481,9 @@ std::unique_ptr cast(column_view const& input, bool is_supported_cast(data_type from, data_type to) noexcept { - CUDF_FUNC_RANGE(); - return detail::is_supported_cast(from, to); + // No matching detail API call/nvtx annotation, since this doesn't + // launch a kernel. + return double_type_dispatcher(from, to, detail::is_supported_cast_impl{}); } } // namespace cudf