Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport bit manipulation facility from C++20 standard library header <bit> #4577

Merged
merged 3 commits into from
Feb 22, 2023

Conversation

dalg24
Copy link
Member

@dalg24 dalg24 commented Dec 2, 2021

Fix #3828

See documentation in kokkos/kokkos-core-wiki#300

  • Deprecate Kokkos::log2(unsigned) -> int done in Deprecate log2(unsigned) -> int #4595
  • Provide alternative Impl::bit_log2(UnsignedInteger) -> UnsignedInteger for internal use only withdrawn (might come back with it in a follow up PR)
  • Backport bit manipulation facility from C++20 https://eel.is/c++draft/bit
  • Remove Impl::bit_count(unsigned int) in favor of Experimental::popcount(UnsignedInteger) -> UnsignedInteger withdrawn (will propose in a follow up PR)

NOTES

  • I have already implemented [bit.rot] and I intend to remove Impl::rotate_right(unsigned, int) -> unsigned in the Bitset implementation but I was planing to do that in a follow-up PR
  • I intend to incrementally replace everything in <impl/Kokkos_BitOps.hpp> until we can get rid of the header
  • I will also attempt to replace the integral_power_of_two* facility in impl/Kokkos_Traits.hpp but I would rather deal with it later
  • I only used GCC built-in functions on the host-side for Experimental::*_builtin function templates. We can specialize further and add Intel intrinsics and such later.

@dalg24 dalg24 force-pushed the bit_manip branch 3 times, most recently from 4d4be48 to e914ebf Compare February 21, 2023 16:11
Copy link
Contributor

@ajpowelsnl ajpowelsnl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR generally looks good, and there's no reason to think it shouldn't be merged. But I do have a basic question (perhaps I should know the answer, but I don't), why does Kokkos need to manipulate at the bit level? To deal with various proclivities and folkways of different compilers and backends?

@PhilMiller
Copy link
Contributor

This is part of a broader theme of Kokkos broadly mimicking C++ standard library functionality with __host__ __device__ annotations (or their moral equivalent) so that applications can use them on GPUs. See also Kokkos::pair, Kokkos::complex, Kokkos::array, math routines (pow, sqrt, etc), and much more.

core/src/Kokkos_BitManipulation.hpp Show resolved Hide resolved

namespace Kokkos::Impl {

#if defined(KOKKOS_COMPILER_CLANG) || defined(KOKKOS_COMPILER_GCC)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IntelLLVM would probably also define it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer fiddling with more compiler and other intrinsics later.

countl_zero(T x) noexcept {
using ::Kokkos::Experimental::digits_v;
if (x == 0) return digits_v<T>;
// TODO use compiler intrinsics when available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// TODO use compiler intrinsics when available
// TODO use constexpr compiler intrinsics when available

@masterleinad
Copy link
Contributor

The PR generally looks good, and there's no reason to think it shouldn't be merged. But I do have a basic question (perhaps I should know the answer, but I don't), why does Kokkos need to manipulate at the bit level? To deal with various proclivities and folkways of different compilers and backends?

We already have a much of places where we would use these functions in the library.

Copy link
Contributor

@masterleinad masterleinad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK to me.

@dalg24
Copy link
Member Author

dalg24 commented Feb 22, 2023

(I figured out the failure with NVCC. It was a few stray constexpr qualifiers on builtin device side function templates.)

@dalg24
Copy link
Member Author

dalg24 commented Feb 22, 2023

Retest this please

1 similar comment
@dalg24
Copy link
Member Author

dalg24 commented Feb 22, 2023

Retest this please

@dalg24 dalg24 force-pushed the bit_manip branch 2 times, most recently from 320378a to 9823ec8 Compare February 22, 2023 13:01
}

TEST(TEST_CATEGORY, bit_manip_countr_zero) {
test_bit_manip_countr_zero<unsigned char>();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue with SYCL

4: value at 1 which is 248 was expected to be 0
4: value at 2 which is 249 was expected to be 1
4: value at 3 which is 248 was expected to be 0
4: value at 4 which is 250 was expected to be 2
4: value at 5 which is 248 was expected to be 0
4: value at 6 which is 249 was expected to be 1
4: value at 7 which is 248 was expected to be 0
4: value at 8 which is 251 was expected to be 3
4: value at 9 which is 248 was expected to be 0
4: value at 7e which is 249 was expected to be 1
4: value at 7f which is 248 was expected to be 0
4: value at 80 which is 255 was expected to be 7
4: value at 81 which is 248 was expected to be 0
4: value at 82 which is 249 was expected to be 1
4: value at 7f which is 248 was expected to be 0
4: /var/jenkins/workspace/Kokkos/core/unit_test/TestBitManipulationBuiltins.hpp:67: Failure
4: Expected equality of these values:
4:   errors
4:     Which is: 15
4:   0
4: Failed check no error for countr_zero(unsigned char)
4: [  FAILED  ] sycl.bit_manip_countr_zero (9 ms)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Daniel reported it works on Intel GPUs. I disabled on NVIDIA.

}

TEST(TEST_CATEGORY, bit_manip_countr_one) {
test_bit_manip_countr_one<unsigned char>();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4: [ RUN      ] sycl.bit_manip_countr_one
4: value at 0 which is 248 was expected to be 0
4: value at 1 which is 249 was expected to be 1
4: value at 2 which is 248 was expected to be 0
4: value at 3 which is 250 was expected to be 2
4: value at 4 which is 248 was expected to be 0
4: value at 5 which is 249 was expected to be 1
4: value at 6 which is 248 was expected to be 0
4: value at 7 which is 251 was expected to be 3
4: value at 8 which is 248 was expected to be 0
4: value at 9 which is 249 was expected to be 1
4: value at 7e which is 248 was expected to be 0
4: value at 7f which is 255 was expected to be 7
4: value at 80 which is 248 was expected to be 0
4: value at 7e which is 248 was expected to be 0
4: value at 7f which is 255 was expected to be 7
4: /var/jenkins/workspace/Kokkos/core/unit_test/TestBitManipulationBuiltins.hpp:67: Failure
4: Expected equality of these values:
4:   errors
4:     Which is: 15
4:   0
4: Failed check no error for countr_one(unsigned char)

@dalg24
Copy link
Member Author

dalg24 commented Feb 22, 2023

SYCL build passed with the last commit. HIP failure is unrelated.

static_assert(std::is_same_v<decltype(countl_zero_builtin(UInt())), int>);
constexpr auto max =
Kokkos::Experimental::finite_max_v<std::make_signed_t<UInt>>;
// ^^^^^^^^^^^^^^^^^^
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't mean to keep that change...

Copy link
Contributor

@nmm0 nmm0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me, we just need to file an issue for the eventual merging of these paths

countl_zero(T x) noexcept {
using ::Kokkos::Experimental::digits_v;
if (x == 0) return digits_v<T>;
// TODO use compiler intrinsics when available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should file a new issue to avoid TODOs otherwise these will be forgotten, especially since we can't do this properly until C++20 support

countr_zero(T x) noexcept {
using ::Kokkos::Experimental::digits_v;
if (x == 0) return digits_v<T>;
// TODO use compiler intrinsics when available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

Impl::is_standard_unsigned_integer_type_v<T>, int>
popcount(T x) noexcept {
if (x == 0) return 0;
// TODO use compiler intrinsics when available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

@nmm0
Copy link
Contributor

nmm0 commented Feb 22, 2023

I promised to myself that when I would review I would ask for docs/changelog entry. You already have the docs, so I guess we should add to the changelog of whatever this is targeting.

@dalg24 dalg24 mentioned this pull request Feb 22, 2023
@dalg24
Copy link
Member Author

dalg24 commented Feb 22, 2023

Ignoring HIP failure

@dalg24 dalg24 merged commit fb3d754 into kokkos:develop Feb 22, 2023
@dalg24 dalg24 deleted the bit_manip branch February 22, 2023 18:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Refactor Tidying up: make code code, cleaner, simpler, understandable and robust
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants