Skip to content

Commit

Permalink
Make more constexpr available on device for cuIO (#17746)
Browse files Browse the repository at this point in the history
Contributes to #7795

This PR addressed most of the relaxed constexpr in cuIO.

Authors:
  - Yunsong Wang (https://github.com/PointKernel)

Approvers:
  - Basit Ayantunde (https://github.com/lamarrr)
  - Vukasin Milovanovic (https://github.com/vuule)

URL: #17746
  • Loading branch information
PointKernel authored Jan 26, 2025
1 parent 133e0c8 commit 551e452
Show file tree
Hide file tree
Showing 30 changed files with 245 additions and 162 deletions.
18 changes: 10 additions & 8 deletions cpp/include/cudf/detail/utilities/integer_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ CUDF_HOST_DEVICE constexpr S round_up_safe(S number_to_round, S modulus)
* `modulus` is positive and does not check for overflow.
*/
template <typename S>
constexpr S round_down_safe(S number_to_round, S modulus) noexcept
CUDF_HOST_DEVICE constexpr S round_down_safe(S number_to_round, S modulus) noexcept
{
auto remainder = number_to_round % modulus;
auto rounded_down = number_to_round - remainder;
Expand Down Expand Up @@ -113,24 +113,26 @@ CUDF_HOST_DEVICE constexpr S round_up_unsafe(S number_to_round, S modulus) noexc
* the result will be incorrect
*/
template <typename S, typename T>
constexpr S div_rounding_up_unsafe(S const& dividend, T const& divisor) noexcept
CUDF_HOST_DEVICE constexpr S div_rounding_up_unsafe(S const& dividend, T const& divisor) noexcept
{
return (dividend + divisor - 1) / divisor;
}

namespace detail {
template <typename I>
constexpr I div_rounding_up_safe(std::integral_constant<bool, false>,
I dividend,
I divisor) noexcept
CUDF_HOST_DEVICE constexpr I div_rounding_up_safe(cuda::std::integral_constant<bool, false>,
I dividend,
I divisor) noexcept
{
// TODO: This could probably be implemented faster
return (dividend > divisor) ? 1 + div_rounding_up_unsafe(dividend - divisor, divisor)
: (dividend > 0);
}

template <typename I>
constexpr I div_rounding_up_safe(std::integral_constant<bool, true>, I dividend, I divisor) noexcept
CUDF_HOST_DEVICE constexpr I div_rounding_up_safe(cuda::std::integral_constant<bool, true>,
I dividend,
I divisor) noexcept
{
auto quotient = dividend / divisor;
auto remainder = dividend % divisor;
Expand All @@ -156,9 +158,9 @@ constexpr I div_rounding_up_safe(std::integral_constant<bool, true>, I dividend,
* the non-integral division `dividend/divisor`
*/
template <typename I>
constexpr I div_rounding_up_safe(I dividend, I divisor) noexcept
CUDF_HOST_DEVICE constexpr I div_rounding_up_safe(I dividend, I divisor) noexcept
{
using i_is_a_signed_type = std::integral_constant<bool, std::is_signed_v<I>>;
using i_is_a_signed_type = cuda::std::integral_constant<bool, cuda::std::is_signed_v<I>>;
return detail::div_rounding_up_safe(i_is_a_signed_type{}, dividend, divisor);
}

Expand Down
6 changes: 3 additions & 3 deletions cpp/include/cudf/fixed_point/temporary.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
* Copyright (c) 2021-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -54,7 +54,7 @@ auto to_string(T value) -> std::string
}

template <typename T>
constexpr auto abs(T value)
CUDF_HOST_DEVICE constexpr auto abs(T value)
{
return value >= 0 ? value : -value;
}
Expand All @@ -72,7 +72,7 @@ CUDF_HOST_DEVICE inline auto max(T lhs, T rhs)
}

template <typename BaseType>
constexpr auto exp10(int32_t exponent)
CUDF_HOST_DEVICE constexpr auto exp10(int32_t exponent)
{
BaseType value = 1;
while (exponent > 0)
Expand Down
16 changes: 9 additions & 7 deletions cpp/include/cudf/io/text/detail/multistate.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
* Copyright (c) 2021-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,6 +18,8 @@

#include <cudf/utilities/export.hpp>

#include <cuda/functional>

#include <cstdint>

namespace CUDF_EXPORT cudf {
Expand Down Expand Up @@ -45,7 +47,7 @@ struct multistate {
*
* @note: The behavior of this function is undefined if size() => max_segment_count
*/
constexpr void enqueue(uint8_t head, uint8_t tail)
CUDF_HOST_DEVICE constexpr void enqueue(uint8_t head, uint8_t tail)
{
_heads |= (head & 0xFu) << (_size * 4);
_tails |= (tail & 0xFu) << (_size * 4);
Expand All @@ -55,17 +57,17 @@ struct multistate {
/**
* @brief get's the number of segments this multistate represents
*/
[[nodiscard]] constexpr uint8_t size() const { return _size; }
[[nodiscard]] CUDF_HOST_DEVICE constexpr uint8_t size() const { return _size; }

/**
* @brief get's the highest (____, tail] value this multistate represents
*/
[[nodiscard]] constexpr uint8_t max_tail() const
[[nodiscard]] CUDF_HOST_DEVICE constexpr uint8_t max_tail() const
{
uint8_t maximum = 0;

for (uint8_t i = 0; i < _size; i++) {
maximum = std::max(maximum, get_tail(i));
maximum = cuda::std::max(maximum, get_tail(i));
}

return maximum;
Expand All @@ -74,15 +76,15 @@ struct multistate {
/**
* @brief get's the Nth (head, ____] value state this multistate represents
*/
[[nodiscard]] constexpr uint8_t get_head(uint8_t idx) const
[[nodiscard]] CUDF_HOST_DEVICE constexpr uint8_t get_head(uint8_t idx) const
{
return (_heads >> (idx * 4)) & 0xFu;
}

/**
* @brief get's the Nth (____, tail] value state this multistate represents
*/
[[nodiscard]] constexpr uint8_t get_tail(uint8_t idx) const
[[nodiscard]] CUDF_HOST_DEVICE constexpr uint8_t get_tail(uint8_t idx) const
{
return (_tails >> (idx * 4)) & 0xFu;
}
Expand Down
8 changes: 5 additions & 3 deletions cpp/include/cudf/strings/detail/convert/fixed_point.cuh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2024, NVIDIA CORPORATION.
* Copyright (c) 2021-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@

#include <cudf/fixed_point/temporary.hpp>

#include <cuda/std/limits>
#include <cuda/std/optional>
#include <cuda/std/type_traits>
#include <thrust/pair.h>
Expand Down Expand Up @@ -46,7 +47,7 @@ __device__ inline thrust::pair<UnsignedDecimalType, int32_t> parse_integer(
// highest value where another decimal digit cannot be appended without an overflow;
// this preserves the most digits when scaling the final result for this type
constexpr UnsignedDecimalType decimal_max =
(std::numeric_limits<UnsignedDecimalType>::max() - 9L) / 10L;
(cuda::std::numeric_limits<UnsignedDecimalType>::max() - 9L) / 10L;

__uint128_t value = 0; // for checking overflow
int32_t exp_offset = 0;
Expand Down Expand Up @@ -90,7 +91,8 @@ __device__ inline thrust::pair<UnsignedDecimalType, int32_t> parse_integer(
template <bool check_only = false>
__device__ cuda::std::optional<int32_t> parse_exponent(char const* iter, char const* iter_end)
{
constexpr uint32_t exponent_max = static_cast<uint32_t>(std::numeric_limits<int32_t>::max());
constexpr uint32_t exponent_max =
static_cast<uint32_t>(cuda::std::numeric_limits<int32_t>::max());

// get optional exponent sign
int32_t const exp_sign = [&iter] {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023, NVIDIA CORPORATION.
* Copyright (c) 2023-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,8 @@

#include <cudf/strings/detail/convert/int_to_string.cuh>

#include <cuda/std/functional>

namespace cudf::strings::detail {

/**
Expand All @@ -33,7 +35,7 @@ __device__ inline int32_t fixed_point_string_size(__int128_t const& value, int32
auto const abs_value = numeric::detail::abs(value);
auto const exp_ten = numeric::detail::exp10<__int128_t>(-scale);
auto const fraction = count_digits(abs_value % exp_ten);
auto const num_zeros = std::max(0, (-scale - fraction));
auto const num_zeros = cuda::std::max(0, (-scale - fraction));
return static_cast<int32_t>(value < 0) + // sign if negative
count_digits(abs_value / exp_ten) + // integer
1 + // decimal point
Expand Down Expand Up @@ -66,7 +68,7 @@ __device__ inline void fixed_point_to_string(__int128_t const& value, int32_t sc
if (value < 0) *out_ptr++ = '-'; // add sign
auto const abs_value = numeric::detail::abs(value);
auto const exp_ten = numeric::detail::exp10<__int128_t>(-scale);
auto const num_zeros = std::max(0, (-scale - count_digits(abs_value % exp_ten)));
auto const num_zeros = cuda::std::max(0, (-scale - count_digits(abs_value % exp_ten)));

out_ptr += integer_to_string(abs_value / exp_ten, out_ptr); // add the integer part
*out_ptr++ = '.'; // add decimal point
Expand Down
4 changes: 2 additions & 2 deletions cpp/include/cudf/strings/detail/convert/int_to_string.cuh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021-2022, NVIDIA CORPORATION.
* Copyright (c) 2021-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -67,7 +67,7 @@ __device__ inline size_type integer_to_string(IntegerType value, char* d_buffer)
* @return size_type number of digits in input value
*/
template <typename IntegerType>
constexpr size_type count_digits(IntegerType value)
__device__ constexpr size_type count_digits(IntegerType value)
{
if (value == 0) return 1;
bool const is_negative = cuda::std::is_signed<IntegerType>() ? (value < 0) : false;
Expand Down
24 changes: 18 additions & 6 deletions cpp/include/cudf/strings/detail/strings_children.cuh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2024, NVIDIA CORPORATION.
* Copyright (c) 2019-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -41,6 +41,21 @@ namespace cudf {
namespace strings {
namespace detail {

template <typename Iter>
struct string_offsets_fn {
Iter _begin;
size_type _strings_count;
constexpr string_offsets_fn(Iter begin, size_type strings_count)
: _begin{begin}, _strings_count{strings_count}
{
}

__device__ constexpr size_type operator()(size_type idx) const noexcept
{
return idx < _strings_count ? static_cast<size_type>(_begin[idx]) : size_type{0};
};
};

/**
* @brief Gather characters to create a strings column using the given string-index pair iterator
*
Expand Down Expand Up @@ -133,11 +148,8 @@ std::pair<std::unique_ptr<column>, int64_t> make_offsets_child_column(
// using exclusive-scan technically requires strings_count+1 input values even though
// the final input value is never used.
// The input iterator is wrapped here to allow the 'last value' to be safely read.
auto map_fn = cuda::proclaim_return_type<size_type>(
[begin, strings_count] __device__(size_type idx) -> size_type {
return idx < strings_count ? static_cast<size_type>(begin[idx]) : size_type{0};
});
auto input_itr = cudf::detail::make_counting_transform_iterator(0, map_fn);
auto input_itr =
cudf::detail::make_counting_transform_iterator(0, string_offsets_fn{begin, strings_count});
// Use the sizes-to-offsets iterator to compute the total number of elements
auto const total_bytes =
cudf::detail::sizes_to_offsets(input_itr, input_itr + strings_count + 1, d_offsets, stream);
Expand Down
4 changes: 2 additions & 2 deletions cpp/src/io/csv/datetime.cuh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2024, NVIDIA CORPORATION.
* Copyright (c) 2019-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -197,7 +197,7 @@ __inline__ __device__ cuda::std::chrono::hh_mm_ss<duration_ms> extract_time_of_d
/**
* @brief Checks whether `c` is decimal digit
*/
constexpr bool is_digit(char c) { return c >= '0' and c <= '9'; }
__device__ constexpr bool is_digit(char c) { return c >= '0' and c <= '9'; }

/**
* @brief Parses a datetime string and computes the corresponding timestamp.
Expand Down
70 changes: 51 additions & 19 deletions cpp/src/io/json/write_json.cu
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024, NVIDIA CORPORATION.
* Copyright (c) 2023-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -376,6 +376,48 @@ std::unique_ptr<column> struct_to_strings(table_view const& strings_columns,
{});
}

struct scatter_fn {
column_device_view _col;
size_type* _d_strview_offsets;
string_view* _d_strviews;
size_type const* _labels;
size_type const* _list_offsets;
column_device_view _d_strings_children;
string_view _element_seperator;
string_view _element_narep;

scatter_fn(column_device_view col,
size_type* d_strview_offsets,
string_view* d_strviews,
size_type const* labels,
size_type const* list_offsets,
column_device_view d_strings_children,
string_view const element_separator,
string_view const element_narep) noexcept
: _col{col},
_d_strview_offsets{d_strview_offsets},
_d_strviews{d_strviews},
_labels{labels},
_list_offsets{list_offsets},
_d_strings_children{d_strings_children},
_element_seperator{element_separator},
_element_narep{element_narep}
{
}

__device__ void operator()(size_type idx) const
{
auto const label = _labels[idx];
auto const sublist_index = idx - _list_offsets[label];
auto const strview_index = _d_strview_offsets[label] + sublist_index * 2 + 1;
// value or na_rep
auto const strview = _d_strings_children.element<cudf::string_view>(idx);
_d_strviews[strview_index] = _d_strings_children.is_null(idx) ? _element_narep : strview;
// separator
if (sublist_index != 0) { _d_strviews[strview_index - 1] = _element_seperator; }
}
};

/**
* @brief Concatenates a list of strings columns into a single strings column.
*
Expand Down Expand Up @@ -461,24 +503,14 @@ std::unique_ptr<column> join_list_of_strings(lists_column_view const& lists_stri
thrust::for_each(rmm::exec_policy_nosync(stream),
thrust::make_counting_iterator<size_type>(0),
thrust::make_counting_iterator<size_type>(num_strings),
[col = *col_device_view,
d_strview_offsets = d_strview_offsets.begin(),
d_strviews = d_strviews.begin(),
labels = labels->view().begin<size_type>(),
list_offsets = offsets.begin<size_type>(),
d_strings_children = *d_strings_children,
element_separator,
element_narep] __device__(auto idx) {
auto const label = labels[idx];
auto const sublist_index = idx - list_offsets[label];
auto const strview_index = d_strview_offsets[label] + sublist_index * 2 + 1;
// value or na_rep
auto const strview = d_strings_children.element<cudf::string_view>(idx);
d_strviews[strview_index] =
d_strings_children.is_null(idx) ? element_narep : strview;
// separator
if (sublist_index != 0) { d_strviews[strview_index - 1] = element_separator; }
});
scatter_fn{*col_device_view,
d_strview_offsets.data(),
d_strviews.data(),
labels->view().data<size_type>(),
offsets.data<size_type>(),
*d_strings_children,
element_separator,
element_narep});

auto joined_col = make_strings_column(d_strviews, string_view{nullptr, 0}, stream, mr);

Expand Down
4 changes: 2 additions & 2 deletions cpp/src/io/orc/orc.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019-2024, NVIDIA CORPORATION.
* Copyright (c) 2019-2025, NVIDIA CORPORATION.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -707,7 +707,7 @@ struct orc_column_device_view : public column_device_view {
struct rowgroup_rows {
size_type begin;
size_type end;
[[nodiscard]] constexpr auto size() const noexcept { return end - begin; }
[[nodiscard]] CUDF_HOST_DEVICE constexpr auto size() const noexcept { return end - begin; }
};

} // namespace orc
Expand Down
Loading

0 comments on commit 551e452

Please sign in to comment.