Skip to content

Commit

Permalink
Add support for decimal128 (#9483)
Browse files Browse the repository at this point in the history
Fixes #9597
Fixes #9565

Previously, `fixed_point` along with `decimal32` and `decimal64` were added to support DecimalType (see #3556 for a list of major and minor PRs). With [support for `__int128_t` now in CUDA 11.5](https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-general-new-features), we can support `decimal128.` This PR enables `decimal128`.

Authors:
  - Conor Hoekstra (https://github.com/codereport)

Approvers:
  - Robert (Bobby) Evans (https://github.com/revans2)
  - Mark Harris (https://github.com/harrism)
  - AJ Schmidt (https://github.com/ajschmidt8)
  - Jake Hemstad (https://github.com/jrhemstad)
  • Loading branch information
codereport authored Nov 16, 2021
1 parent 0da63f0 commit c1f20c7
Show file tree
Hide file tree
Showing 78 changed files with 1,481 additions and 892 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ The following instructions are for developers and contributors to cuDF OSS devel
Compilers:

* `gcc` version 9.3+
* `nvcc` version 11.0+
* `nvcc` version 11.5+
* `cmake` version 3.20.1+

CUDA/GPU:

* CUDA 11.0+
* CUDA 11.5+
* NVIDIA driver 450.80.02+
* Pascal architecture or better

Expand Down
1 change: 1 addition & 0 deletions conda/recipes/libcudf/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ test:
- test -f $PREFIX/include/cudf/dictionary/update_keys.hpp
- test -f $PREFIX/include/cudf/filling.hpp
- test -f $PREFIX/include/cudf/fixed_point/fixed_point.hpp
- test -f $PREFIX/include/cudf/fixed_point/temporary.hpp
- test -f $PREFIX/include/cudf/groupby.hpp
- test -f $PREFIX/include/cudf/hashing.hpp
- test -f $PREFIX/include/cudf/interop.hpp
Expand Down
27 changes: 5 additions & 22 deletions cpp/include/cudf/column/column_device_view.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -421,39 +421,22 @@ class alignas(16) column_device_view : public detail::column_device_view_base {
}

/**
* @brief Returns a `numeric::decimal32` element at the specified index for a `fixed_point`
* @brief Returns a `numeric::fixed_point` element at the specified index for a `fixed_point`
* column.
*
* If the element at the specified index is NULL, i.e., `is_null(element_index) == true`,
* then any attempt to use the result will lead to undefined behavior.
*
* @param element_index Position of the desired element
* @return numeric::decimal32 representing the element at this index
* @return numeric::fixed_point representing the element at this index
*/
template <typename T, CUDF_ENABLE_IF(std::is_same_v<T, numeric::decimal32>)>
template <typename T, CUDF_ENABLE_IF(cudf::is_fixed_point<T>())>
__device__ T element(size_type element_index) const noexcept
{
using namespace numeric;
using rep = typename T::rep;
auto const scale = scale_type{_type.scale()};
return decimal32{scaled_integer<int32_t>{data<int32_t>()[element_index], scale}};
}

/**
* @brief Returns a `numeric::decimal64` element at the specified index for a `fixed_point`
* column.
*
* If the element at the specified index is NULL, i.e., `is_null(element_index) == true`,
* then any attempt to use the result will lead to undefined behavior.
*
* @param element_index Position of the desired element
* @return numeric::decimal64 representing the element at this index
*/
template <typename T, CUDF_ENABLE_IF(std::is_same_v<T, numeric::decimal64>)>
__device__ T element(size_type element_index) const noexcept
{
using namespace numeric;
auto const scale = scale_type{_type.scale()};
return decimal64{scaled_integer<int64_t>{data<int64_t>()[element_index], scale}};
return T{scaled_integer<rep>{data<rep>()[element_index], scale}};
}

/**
Expand Down
70 changes: 43 additions & 27 deletions cpp/include/cudf/detail/aggregation/aggregation.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <cudf/detail/utilities/device_atomics.cuh>
#include <cudf/dictionary/dictionary_column_view.hpp>
#include <cudf/table/table_device_view.cuh>
#include <cudf/utilities/traits.cuh>

#include <rmm/cuda_stream_view.hpp>
#include <rmm/exec_policy.hpp>
Expand Down Expand Up @@ -131,7 +132,8 @@ struct update_target_element<
aggregation::MIN,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_width<Source>() && !is_fixed_point<Source>()>> {
std::enable_if_t<is_fixed_width<Source>() && cudf::has_atomic_support<Source>() &&
!is_fixed_point<Source>()>> {
__device__ void operator()(mutable_column_device_view target,
size_type target_index,
column_device_view source,
Expand All @@ -148,11 +150,13 @@ struct update_target_element<
};

template <typename Source, bool target_has_nulls, bool source_has_nulls>
struct update_target_element<Source,
aggregation::MIN,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_point<Source>()>> {
struct update_target_element<
Source,
aggregation::MIN,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_point<Source>() &&
cudf::has_atomic_support<device_storage_type_t<Source>>()>> {
__device__ void operator()(mutable_column_device_view target,
size_type target_index,
column_device_view source,
Expand All @@ -177,7 +181,8 @@ struct update_target_element<
aggregation::MAX,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_width<Source>() && !is_fixed_point<Source>()>> {
std::enable_if_t<is_fixed_width<Source>() && cudf::has_atomic_support<Source>() &&
!is_fixed_point<Source>()>> {
__device__ void operator()(mutable_column_device_view target,
size_type target_index,
column_device_view source,
Expand All @@ -194,11 +199,13 @@ struct update_target_element<
};

template <typename Source, bool target_has_nulls, bool source_has_nulls>
struct update_target_element<Source,
aggregation::MAX,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_point<Source>()>> {
struct update_target_element<
Source,
aggregation::MAX,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_point<Source>() &&
cudf::has_atomic_support<device_storage_type_t<Source>>()>> {
__device__ void operator()(mutable_column_device_view target,
size_type target_index,
column_device_view source,
Expand All @@ -223,7 +230,8 @@ struct update_target_element<
aggregation::SUM,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_width<Source>() && !is_fixed_point<Source>()>> {
std::enable_if_t<is_fixed_width<Source>() && cudf::has_atomic_support<Source>() &&
!is_fixed_point<Source>()>> {
__device__ void operator()(mutable_column_device_view target,
size_type target_index,
column_device_view source,
Expand All @@ -240,11 +248,13 @@ struct update_target_element<
};

template <typename Source, bool target_has_nulls, bool source_has_nulls>
struct update_target_element<Source,
aggregation::SUM,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_point<Source>()>> {
struct update_target_element<
Source,
aggregation::SUM,
target_has_nulls,
source_has_nulls,
std::enable_if_t<is_fixed_point<Source>() &&
cudf::has_atomic_support<device_storage_type_t<Source>>()>> {
__device__ void operator()(mutable_column_device_view target,
size_type target_index,
column_device_view source,
Expand All @@ -267,7 +277,8 @@ struct update_target_element<Source,
* @brief Function object to update a single element in a target column using
* the dictionary key addressed by the specific index.
*
* SFINAE is used to prevent recursion for dictionary type. Dictionary keys cannot be a dictionary.
* SFINAE is used to prevent recursion for dictionary type. Dictionary keys cannot be a
* dictionary.
*
*/
template <bool target_has_nulls = true>
Expand Down Expand Up @@ -581,9 +592,7 @@ struct identity_initializer {
template <typename T, aggregation::Kind k>
static constexpr bool is_supported()
{
// Note: !is_fixed_point<T>() means that aggregations for fixed_point should happen on the
// underlying type (see device_storage_type_t), not that fixed_point is not supported
return cudf::is_fixed_width<T>() && !is_fixed_point<T>() and
return cudf::is_fixed_width<T>() and
(k == aggregation::SUM or k == aggregation::MIN or k == aggregation::MAX or
k == aggregation::COUNT_VALID or k == aggregation::COUNT_ALL or
k == aggregation::ARGMAX or k == aggregation::ARGMIN or
Expand All @@ -596,7 +605,8 @@ struct identity_initializer {
std::enable_if_t<not std::is_same<corresponding_operator_t<k>, void>::value, T>
identity_from_operator()
{
return corresponding_operator_t<k>::template identity<T>();
using DeviceType = device_storage_type_t<T>;
return corresponding_operator_t<k>::template identity<DeviceType>();
}

template <typename T, aggregation::Kind k>
Expand All @@ -613,9 +623,11 @@ struct identity_initializer {
if constexpr (cudf::is_timestamp<T>())
return k == aggregation::ARGMAX ? T{typename T::duration(ARGMAX_SENTINEL)}
: T{typename T::duration(ARGMIN_SENTINEL)};
else
return k == aggregation::ARGMAX ? static_cast<T>(ARGMAX_SENTINEL)
: static_cast<T>(ARGMIN_SENTINEL);
else {
using DeviceType = device_storage_type_t<T>;
return k == aggregation::ARGMAX ? static_cast<DeviceType>(ARGMAX_SENTINEL)
: static_cast<DeviceType>(ARGMIN_SENTINEL);
}
}
return identity_from_operator<T, k>();
}
Expand All @@ -625,7 +637,11 @@ struct identity_initializer {
std::enable_if_t<is_supported<T, k>(), void> operator()(mutable_column_view const& col,
rmm::cuda_stream_view stream)
{
thrust::fill(rmm::exec_policy(stream), col.begin<T>(), col.end<T>(), get_identity<T, k>());
using DeviceType = device_storage_type_t<T>;
thrust::fill(rmm::exec_policy(stream),
col.begin<DeviceType>(),
col.end<DeviceType>(),
get_identity<DeviceType, k>());
}

template <typename T, aggregation::Kind k>
Expand Down
15 changes: 8 additions & 7 deletions cpp/include/cudf/detail/aggregation/aggregation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1085,8 +1085,8 @@ template <typename Source, aggregation::Kind k>
struct target_type_impl<
Source,
k,
std::enable_if_t<is_fixed_width<Source>() && not is_chrono<Source>() &&
not is_fixed_point<Source>() && (k == aggregation::MEAN)>> {
std::enable_if_t<is_fixed_width<Source>() and not is_chrono<Source>() and
not is_fixed_point<Source>() and (k == aggregation::MEAN)>> {
using type = double;
};

Expand All @@ -1113,12 +1113,13 @@ struct target_type_impl<
using type = int64_t;
};

// Summing fixed_point numbers, always use the decimal64 accumulator
// Summing fixed_point numbers
template <typename Source, aggregation::Kind k>
struct target_type_impl<Source,
k,
std::enable_if_t<is_fixed_point<Source>() && (k == aggregation::SUM)>> {
using type = numeric::decimal64;
struct target_type_impl<
Source,
k,
std::enable_if_t<cudf::is_fixed_point<Source>() && (k == aggregation::SUM)>> {
using type = Source;
};

// Summing/Multiplying float/doubles, use same type accumulator
Expand Down
7 changes: 1 addition & 6 deletions cpp/include/cudf/detail/copy_if.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,7 @@ struct DeviceType<T, std::enable_if_t<cudf::is_timestamp<T>()>> {
};

template <typename T>
struct DeviceType<T, std::enable_if_t<std::is_same_v<numeric::decimal32, T>>> {
using type = typename cudf::device_storage_type_t<T>;
};

template <typename T>
struct DeviceType<T, std::enable_if_t<std::is_same_v<numeric::decimal64, T>>> {
struct DeviceType<T, std::enable_if_t<cudf::is_fixed_point<T>()>> {
using type = typename cudf::device_storage_type_t<T>;
};

Expand Down
3 changes: 1 addition & 2 deletions cpp/include/cudf/detail/iterator.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@ struct null_replaced_value_accessor {
bool has_nulls = true)
: col{col}, null_replacement{null_val}, has_nulls{has_nulls}
{
CUDF_EXPECTS(type_to_id<Element>() == device_storage_type_id(col.type().id()),
CUDF_EXPECTS(type_id_matches_device_storage_type<Element>(col.type().id()),
"the data type mismatch");
// verify validity bitmask is non-null, otherwise, is_null_nocheck() will crash
if (has_nulls) CUDF_EXPECTS(col.nullable(), "column with nulls must have a validity bitmask");
}

Expand Down
15 changes: 9 additions & 6 deletions cpp/include/cudf/detail/utilities/device_operators.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/

#include <cudf/fixed_point/fixed_point.hpp>
#include <cudf/fixed_point/temporary.hpp>
#include <cudf/scalar/scalar.hpp>
#include <cudf/strings/string_view.cuh>
#include <cudf/types.hpp>
Expand Down Expand Up @@ -119,7 +120,7 @@ struct DeviceMin {
CUDA_HOST_DEVICE_CALLABLE auto operator()(const T& lhs, const T& rhs)
-> decltype(cudf::detail::min(lhs, rhs))
{
return cudf::detail::min(lhs, rhs);
return numeric::detail::min(lhs, rhs);
}

template <
Expand All @@ -128,14 +129,15 @@ struct DeviceMin {
!cudf::is_fixed_point<T>()>* = nullptr>
static constexpr T identity()
{
return std::numeric_limits<T>::max();
if constexpr (cudf::is_chrono<T>()) return T::max();
return cuda::std::numeric_limits<T>::max();
}

template <typename T, typename std::enable_if_t<cudf::is_fixed_point<T>()>* = nullptr>
static constexpr T identity()
{
CUDF_FAIL("fixed_point does not yet support DeviceMin identity");
return std::numeric_limits<T>::max();
return cuda::std::numeric_limits<T>::max();
}

// @brief identity specialized for string_view
Expand All @@ -160,7 +162,7 @@ struct DeviceMax {
CUDA_HOST_DEVICE_CALLABLE auto operator()(const T& lhs, const T& rhs)
-> decltype(cudf::detail::max(lhs, rhs))
{
return cudf::detail::max(lhs, rhs);
return numeric::detail::max(lhs, rhs);
}

template <
Expand All @@ -169,14 +171,15 @@ struct DeviceMax {
!cudf::is_fixed_point<T>()>* = nullptr>
static constexpr T identity()
{
return std::numeric_limits<T>::lowest();
if constexpr (cudf::is_chrono<T>()) return T::min();
return cuda::std::numeric_limits<T>::lowest();
}

template <typename T, typename std::enable_if_t<cudf::is_fixed_point<T>()>* = nullptr>
static constexpr T identity()
{
CUDF_FAIL("fixed_point does not yet support DeviceMax identity");
return std::numeric_limits<T>::lowest();
return cuda::std::numeric_limits<T>::lowest();
}

template <typename T, typename std::enable_if_t<std::is_same_v<T, cudf::string_view>>* = nullptr>
Expand Down
14 changes: 14 additions & 0 deletions cpp/include/cudf/detail/utilities/hash_functions.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ MurmurHash3_32<numeric::decimal64>::operator()(numeric::decimal64 const& key) co
return this->compute(key.value());
}

template <>
hash_value_type CUDA_DEVICE_CALLABLE
MurmurHash3_32<numeric::decimal128>::operator()(numeric::decimal128 const& key) const
{
return this->compute(key.value());
}

template <>
hash_value_type CUDA_DEVICE_CALLABLE
MurmurHash3_32<cudf::list_view>::operator()(cudf::list_view const& key) const
Expand Down Expand Up @@ -419,6 +426,13 @@ SparkMurmurHash3_32<numeric::decimal64>::operator()(numeric::decimal64 const& ke
return this->compute<uint64_t>(key.value());
}

template <>
hash_value_type CUDA_DEVICE_CALLABLE
SparkMurmurHash3_32<numeric::decimal128>::operator()(numeric::decimal128 const& key) const
{
return this->compute<__int128_t>(key.value());
}

template <>
hash_value_type CUDA_DEVICE_CALLABLE
SparkMurmurHash3_32<cudf::list_view>::operator()(cudf::list_view const& key) const
Expand Down
12 changes: 4 additions & 8 deletions cpp/include/cudf/detail/utilities/integer_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
* @file Utility code involving integer arithmetic
*/

#include <cudf/fixed_point/temporary.hpp>

#include <cmath>
#include <cstdlib>
#include <stdexcept>
Expand Down Expand Up @@ -151,17 +153,11 @@ constexpr inline bool is_a_power_of_two(I val) noexcept
* @return Absolute value if value type is signed.
*/
template <typename T>
std::enable_if_t<std::is_signed<T>::value, T> constexpr inline absolute_value(T value)
{
return std::abs(value);
}
// Unsigned type just returns itself.
template <typename T>
std::enable_if_t<!std::is_signed<T>::value, T> constexpr inline absolute_value(T value)
constexpr inline auto absolute_value(T value) -> T
{
if constexpr (cuda::std::is_signed<T>()) return numeric::detail::abs(value);
return value;
}

} // namespace util

} // namespace cudf
Loading

0 comments on commit c1f20c7

Please sign in to comment.