Update Kokkos library in LAMMPS to v3.6.1

This commit is contained in:
Stan Gerald Moore
2022-07-01 13:17:50 -06:00
parent 0ae6f1c30e
commit 2bfbd6fba1
37 changed files with 363 additions and 163 deletions

View File

@ -422,54 +422,34 @@ class BinSort {
template <class KeyViewType>
struct BinOp1D {
int max_bins_;
double mul_;
typename KeyViewType::const_value_type range_;
typename KeyViewType::const_value_type min_;
int max_bins_ = {};
double mul_ = {};
double min_ = {};
BinOp1D()
: max_bins_(0),
mul_(0.0),
range_(typename KeyViewType::const_value_type()),
min_(typename KeyViewType::const_value_type()) {}
BinOp1D() = default;
// Construct BinOp with number of bins, minimum value and maxuimum value
BinOp1D(int max_bins__, typename KeyViewType::const_value_type min,
typename KeyViewType::const_value_type max)
: max_bins_(max_bins__ + 1),
// Cast to int64_t to avoid possible overflow when using integer
mul_(std::is_integral<typename KeyViewType::const_value_type>::value
? 1.0 * max_bins__ / (int64_t(max) - int64_t(min))
: 1.0 * max_bins__ / (max - min)),
range_(max - min),
min_(min) {
// Cast to double to avoid possible overflow when using integer
mul_(static_cast<double>(max_bins__) /
(static_cast<double>(max) - static_cast<double>(min))),
min_(static_cast<double>(min)) {
// For integral types the number of bins may be larger than the range
// in which case we can exactly have one unique value per bin
// and then don't need to sort bins.
if (std::is_integral<typename KeyViewType::const_value_type>::value &&
static_cast<uint64_t>(range_) <= static_cast<uint64_t>(max_bins__)) {
(static_cast<double>(max) - static_cast<double>(min)) <=
static_cast<double>(max_bins__)) {
mul_ = 1.;
}
}
// Determine bin index from key value
template <
class ViewType,
std::enable_if_t<!std::is_integral<typename ViewType::value_type>::value,
bool> = true>
template <class ViewType>
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
return int(mul_ * (keys(i) - min_));
}
// Determine bin index from key value
template <
class ViewType,
std::enable_if_t<std::is_integral<typename ViewType::value_type>::value,
bool> = true>
KOKKOS_INLINE_FUNCTION int bin(ViewType& keys, const int& i) const {
// The cast to int64_t is necessary because otherwise HIP returns the wrong
// result.
return int(mul_ * (int64_t(keys(i)) - int64_t(min_)));
return static_cast<int>(mul_ * (static_cast<double>(keys(i)) - min_));
}
// Return maximum bin index + 1
@ -486,10 +466,9 @@ struct BinOp1D {
template <class KeyViewType>
struct BinOp3D {
int max_bins_[3];
double mul_[3];
typename KeyViewType::non_const_value_type range_[3];
typename KeyViewType::non_const_value_type min_[3];
int max_bins_[3] = {};
double mul_[3] = {};
double min_[3] = {};
BinOp3D() = default;
@ -498,15 +477,15 @@ struct BinOp3D {
max_bins_[0] = max_bins__[0];
max_bins_[1] = max_bins__[1];
max_bins_[2] = max_bins__[2];
mul_[0] = 1.0 * max_bins__[0] / (max[0] - min[0]);
mul_[1] = 1.0 * max_bins__[1] / (max[1] - min[1]);
mul_[2] = 1.0 * max_bins__[2] / (max[2] - min[2]);
range_[0] = max[0] - min[0];
range_[1] = max[1] - min[1];
range_[2] = max[2] - min[2];
min_[0] = min[0];
min_[1] = min[1];
min_[2] = min[2];
mul_[0] = static_cast<double>(max_bins__[0]) /
(static_cast<double>(max[0]) - static_cast<double>(min[0]));
mul_[1] = static_cast<double>(max_bins__[1]) /
(static_cast<double>(max[1]) - static_cast<double>(min[1]));
mul_[2] = static_cast<double>(max_bins__[2]) /
(static_cast<double>(max[2]) - static_cast<double>(min[2]));
min_[0] = static_cast<double>(min[0]);
min_[1] = static_cast<double>(min[1]);
min_[2] = static_cast<double>(min[2]);
}
template <class ViewType>
@ -596,9 +575,9 @@ std::enable_if_t<Kokkos::is_execution_space<ExecutionSpace>::value> sort(
// TODO: figure out better max_bins then this ...
int64_t max_bins = view.extent(0) / 2;
if (std::is_integral<typename ViewType::non_const_value_type>::value) {
// Cast to int64_t to avoid possible overflow when using integer
int64_t const max_val = result.max_val;
int64_t const min_val = result.min_val;
// Cast to double to avoid possible overflow when using integer
auto const max_val = static_cast<double>(result.max_val);
auto const min_val = static_cast<double>(result.min_val);
// using 10M as the cutoff for special behavior (roughly 40MB for the count
// array)
if ((max_val - min_val) < 10000000) {
@ -606,6 +585,10 @@ std::enable_if_t<Kokkos::is_execution_space<ExecutionSpace>::value> sort(
sort_in_bins = false;
}
}
if (std::is_floating_point<typename ViewType::non_const_value_type>::value) {
KOKKOS_ASSERT(std::isfinite(static_cast<double>(result.max_val) -
static_cast<double>(result.min_val)));
}
BinSort<ViewType, CompType> bin_sort(
view, CompType(max_bins, result.min_val, result.max_val), sort_in_bins);

View File

@ -353,6 +353,55 @@ void test_issue_1160_impl() {
}
}
template <class ExecutionSpace>
void test_issue_4978_impl() {
Kokkos::View<long long*, ExecutionSpace> element_("element", 9);
auto h_element = Kokkos::create_mirror_view(element_);
h_element(0) = LLONG_MIN;
h_element(1) = 0;
h_element(2) = 3;
h_element(3) = 2;
h_element(4) = 1;
h_element(5) = 3;
h_element(6) = 6;
h_element(7) = 4;
h_element(8) = 3;
ExecutionSpace exec;
Kokkos::deep_copy(exec, element_, h_element);
Kokkos::sort(exec, element_);
Kokkos::deep_copy(exec, h_element, element_);
exec.fence();
ASSERT_EQ(h_element(0), LLONG_MIN);
ASSERT_EQ(h_element(1), 0);
ASSERT_EQ(h_element(2), 1);
ASSERT_EQ(h_element(3), 2);
ASSERT_EQ(h_element(4), 3);
ASSERT_EQ(h_element(5), 3);
ASSERT_EQ(h_element(6), 3);
ASSERT_EQ(h_element(7), 4);
ASSERT_EQ(h_element(8), 6);
}
template <class ExecutionSpace, class T>
void test_sort_integer_overflow() {
// array with two extrema in reverse order to expose integer overflow bug in
// bin calculation
T a[2] = {Kokkos::Experimental::finite_max<T>::value,
Kokkos::Experimental::finite_min<T>::value};
auto vd = Kokkos::create_mirror_view_and_copy(
ExecutionSpace(), Kokkos::View<T[2], Kokkos::HostSpace>(a));
Kokkos::sort(vd, /*force using Kokkos bin sort*/ true);
auto vh = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), vd);
EXPECT_TRUE(std::is_sorted(vh.data(), vh.data() + 2))
<< "view (" << vh[0] << ", " << vh[1] << ") is not sorted";
}
//----------------------------------------------------------------------------
template <class ExecutionSpace, typename KeyType>
@ -376,6 +425,11 @@ void test_issue_1160_sort() {
test_issue_1160_impl<ExecutionSpace>();
}
template <class ExecutionSpace>
void test_issue_4978_sort() {
test_issue_4978_impl<ExecutionSpace>();
}
template <class ExecutionSpace, typename KeyType>
void test_sort(unsigned int N) {
test_1D_sort<ExecutionSpace, KeyType>(N);
@ -385,6 +439,10 @@ void test_sort(unsigned int N) {
test_dynamic_view_sort<ExecutionSpace, KeyType>(N);
#endif
test_issue_1160_sort<ExecutionSpace>();
test_issue_4978_sort<ExecutionSpace>();
test_sort_integer_overflow<ExecutionSpace, long long>();
test_sort_integer_overflow<ExecutionSpace, unsigned long long>();
test_sort_integer_overflow<ExecutionSpace, int>();
}
} // namespace Impl
} // namespace Test