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

Add SHA-1 and SHA-2 hash functions. #9215

Closed
wants to merge 119 commits into from
Closed
Show file tree
Hide file tree
Changes from 89 commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
436e652
Initial SHA structure.
rwlee Aug 18, 2020
7c1b661
First pass of SHA1 implementation.
rwlee Aug 19, 2020
aac184b
Apply clang-format.
bdice Sep 3, 2021
ade59b7
Update comments and docstrings, enable SHA-1.
bdice Sep 7, 2021
ec4673e
Add test values for SHA-1.
bdice Sep 7, 2021
2596297
Remove unused seed value from MD5Hash.
bdice Sep 7, 2021
f775bbc
Use std::memcpy, add comments.
bdice Sep 7, 2021
955dadf
Use __byte_perm to swap endianness.
bdice Sep 8, 2021
7dd9a9e
Update comments.
bdice Sep 8, 2021
77136bc
Update for changes to cudf::make_strings_column API.
bdice Sep 8, 2021
4f7e0d4
Make rotl32 a CUDA_DEVICE_CALLABLE, use __funnelshift_l intrinsic.
bdice Sep 8, 2021
e42b5a2
Add comments.
bdice Sep 8, 2021
070ee5f
Move MD5 and SHA functions to the only .cu file that uses them.
bdice Sep 8, 2021
252147e
Use named constant for MD5 chunk size.
bdice Sep 9, 2021
d998656
Fix issue by using named temp variables.
bdice Sep 9, 2021
f535d27
Use intrinsic for swapping endianness.
bdice Sep 9, 2021
9d096f3
Fix bug in message length. Must be stored as a big-endian 64-bit value.
bdice Sep 9, 2021
a7a8e6e
Improve comments.
bdice Sep 9, 2021
dfb1c99
Expand anonymous namespace.
bdice Sep 9, 2021
9735b2f
Clean up SHA implementation and expand tests.
bdice Sep 9, 2021
4a7d8d2
Enable all tests.
bdice Sep 9, 2021
585bea4
Revert changes to MD5 (separated into #9212).
bdice Sep 10, 2021
9ce6f17
Move endian swaps into functions.
bdice Sep 10, 2021
516b857
Draft of unified SHA functions - issues runtime error because it uses…
bdice Sep 13, 2021
f4e8c70
Use CRTP design. Also add back missing code to write the output.
bdice Sep 14, 2021
67bf9af
Use generic sha_hash function for SHA-1 (can be reused for SHA-256, S…
bdice Sep 14, 2021
ead336e
Intermediate work on SHA-256.
bdice Sep 15, 2021
5867ebf
Fix bugs in SHA-256 implementation (uninitialized hash constants, inc…
bdice Sep 15, 2021
c94dc8c
Add SHA-256 tests.
bdice Sep 15, 2021
33878d1
Add SHA-512 draft (one failing test).
bdice Sep 15, 2021
7abc5ac
Fix bug in message finalization.
bdice Sep 16, 2021
a89f34c
Draft of SHA-224, SHA-384.
bdice Sep 16, 2021
d9ecdfa
Use explicit SHA word types, add implementations of SHA-224 and SHA-384.
bdice Sep 16, 2021
cc683fc
Enable SHA-224, SHA-384.
bdice Sep 16, 2021
ad65b49
Add tests for SHA-224, SHA-384.
bdice Sep 16, 2021
f338217
Use rmm::cuda_stream_view.
bdice Sep 16, 2021
c46965e
Small refactorings.
bdice Sep 20, 2021
540f983
Use process_key function.
bdice Sep 20, 2021
244f437
Use process function for string data.
bdice Sep 20, 2021
2023ac1
Add comments to process function.
bdice Sep 20, 2021
502e11a
Use constexpr.
bdice Sep 20, 2021
82dd92b
Split sha1_hash_step.
bdice Sep 20, 2021
f05a43a
Move hash step functions above the SHA classes.
bdice Sep 20, 2021
f291c93
Use east const, add comments.
bdice Sep 20, 2021
4b49f2f
Pass hash state by reference.
bdice Sep 20, 2021
0ffa903
Pass hash state by reference in operator and process functions.
bdice Sep 20, 2021
84c034d
Update comment.
bdice Sep 20, 2021
987992e
Store sha_intermediate_data in Hasher instance.
bdice Sep 21, 2021
8e38d61
Drop const.
bdice Sep 21, 2021
56ab37b
Use underlying for hash_step calls.
bdice Sep 21, 2021
b9a37cd
Use memcpy instead of std::memcpy.
bdice Sep 21, 2021
5ae53ca
Update Java enum.
bdice Sep 21, 2021
1591793
Update Cython enum.
bdice Sep 21, 2021
dbd469c
Rename fixed width process function.
bdice Sep 21, 2021
48a08c4
Combine unsupported type dispatches.
bdice Sep 21, 2021
0d280a5
Use const&.
bdice Sep 21, 2021
952251b
Perform memcpys once instead of as a loop.
bdice Sep 21, 2021
2474ec9
Move hash constants into sha_hash.cu.
bdice Sep 21, 2021
d7cfbc5
Fail on invalid hash functions.
bdice Sep 21, 2021
8c6983d
Use uint32_t consistently to avoid mixing signed/unsigned types.
bdice Sep 21, 2021
590f8b3
Simplify word size.
bdice Sep 21, 2021
440583d
Minor improvements to constness.
bdice Sep 21, 2021
d9ae7f1
Add tests for empty tables.
bdice Sep 21, 2021
4e8fdf3
Enable debug mode on sha_hash.cu so that CI can compile.
bdice Sep 22, 2021
c47945d
Rename intermediate data to hash state.
bdice Sep 27, 2021
b37e5f0
Use HashDispatcher for type dispatch.
bdice Sep 27, 2021
607aaad
Cleanup of templates and class/variable names.
bdice Sep 27, 2021
2779a96
Reorganize headers, update error message.
bdice Sep 28, 2021
93b6f54
Generate null mask for all hash values.
bdice Sep 28, 2021
f850e5f
Update tests for new null behavior.
bdice Sep 28, 2021
c5711c8
Merge remote-tracking branch 'upstream/branch-21.12' into sha
bdice Oct 4, 2021
1c6cc2b
Simplify SFINAE.
bdice Oct 4, 2021
2374df4
Add benchmarks for SHA functions.
bdice Oct 8, 2021
c0381b1
Limit range to reduce memory usage for SHA512.
bdice Oct 8, 2021
21b3e26
Merge remote-tracking branch 'upstream/branch-21.12' into sha
bdice Oct 14, 2021
d1936f3
Add SHA methods to Python.
bdice Oct 19, 2021
a373221
Add tests for SHA hashing.
bdice Oct 19, 2021
a7773b8
Move result_location to constructor.
bdice Oct 20, 2021
92466b6
Merge branch 'branch-21.12' into sha
bdice Oct 22, 2021
27ee762
Merge remote-tracking branch 'upstream/branch-21.12' into sha
bdice Oct 25, 2021
927b419
Fix SHA constant qualifiers.
bdice Oct 25, 2021
6decb54
Rename and move leaf type check.
bdice Oct 25, 2021
95b0945
Move shared utility functions to utilities/hash_functions.cuh.
bdice Oct 25, 2021
327effb
Clean up use of utility functions.
bdice Oct 25, 2021
f2f6715
Add includes for column_device_view.
bdice Oct 26, 2021
665a692
Simplify dispatcher construction.
bdice Oct 26, 2021
bce1f65
Combine SFINAE templates into one method with if constexpr.
bdice Oct 26, 2021
aa14261
Use bitmask_and for MD5 null mask.
bdice Oct 26, 2021
adf2a23
Move base sha_hash function into anonymous namespace.
bdice Oct 26, 2021
b8cdbf6
Merge remote-tracking branch 'upstream/branch-22.04' into sha
bdice Mar 16, 2022
4e9ab2c
Merge remote-tracking branch 'upstream/branch-22.04' into sha
bdice Mar 18, 2022
98595e5
Merge remote-tracking branch 'upstream/branch-22.08' into sha
bdice May 23, 2022
ed20e83
Merge remote-tracking branch 'upstream/branch-22.08' into sha
bdice Jun 25, 2022
c6f6a82
Update copyright.
bdice Jun 25, 2022
3a8d4a6
Merge remote-tracking branch 'upstream/branch-22.08' into sha
bdice Jul 18, 2022
0d2e91f
Merge remote-tracking branch 'upstream/branch-22.12' into sha
bdice Nov 15, 2022
ae6c58b
Merge remote-tracking branch 'upstream/branch-23.02' into sha
bdice Nov 15, 2022
42beabd
Merge remote-tracking branch 'upstream/branch-23.02' into sha
bdice Nov 16, 2022
96cd76f
Use __device__ inline instead of CUDA_DEVICE_CALLABLE.
bdice Nov 17, 2022
3b2b618
Use null count from bitmask_and.
bdice Nov 17, 2022
706c702
Drop constexpr because is_fixed_width is no longer constexpr.
bdice Nov 17, 2022
9e44661
Use CUDF_TEST_EXPECT_COLUMNS_EQUAL.
bdice Nov 17, 2022
17591c7
Fix namespaces.
bdice Nov 17, 2022
00b172c
Remove default stream/mr.
bdice Nov 17, 2022
9689d92
Update includes.
bdice Nov 17, 2022
1dba6b3
Try compiling sha_hash.cu in CI without debug flag.
bdice Nov 17, 2022
f4e6aef
Merge branch 'branch-23.02' into sha
bdice Jan 21, 2023
65ee2b9
Merge remote-tracking branch 'upstream/branch-23.04' into sha
bdice Feb 1, 2023
dfa1dbb
Update copyright.
bdice Feb 1, 2023
b70fa8e
Merge remote-tracking branch 'upstream/branch-23.12' into sha
bdice Oct 17, 2023
143ae6a
Remove combined test file.
bdice Oct 17, 2023
68b23e0
Split into multiple TUs.
bdice Oct 17, 2023
9fd9e8d
Update tests.
bdice Oct 18, 2023
84f0527
Merge remote-tracking branch 'upstream/branch-23.12' into sha
bdice Oct 20, 2023
7598247
Merge remote-tracking branch 'upstream/branch-23.12' into sha
bdice Oct 31, 2023
80185b4
Merge remote-tracking branch 'upstream/branch-23.12' into sha
bdice Nov 9, 2023
1442bfd
Add alignment to avoid compiler bug.
bdice Nov 9, 2023
2cf9c1a
Merge branch 'branch-23.12' into sha
bdice Nov 9, 2023
47ccdd2
Remove extra copy of device function.
bdice Nov 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ add_library(cudf
src/hash/hashing.cu
src/hash/md5_hash.cu
src/hash/murmur_hash.cu
src/hash/sha_hash.cu
src/interop/dlpack.cpp
src/interop/from_arrow.cu
src/interop/to_arrow.cu
Expand Down Expand Up @@ -468,6 +469,8 @@ set_target_properties(cudf
INTERFACE_POSITION_INDEPENDENT_CODE ON
)

set_source_files_properties(src/hash/sha_hash.cu PROPERTIES COMPILE_OPTIONS "-G")

target_compile_options(cudf
PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:${CUDF_CXX_FLAGS}>"
"$<$<COMPILE_LANGUAGE:CUDA>:${CUDF_CUDA_FLAGS}>"
Expand Down
7 changes: 6 additions & 1 deletion cpp/benchmarks/hashing/hash_benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,16 @@ static void BM_hash(benchmark::State& state, cudf::hash_id hid)
(::benchmark::State & st) { BM_hash(st, cudf::hash_id::name); } \
BENCHMARK_REGISTER_F(HashBenchmark, name) \
->RangeMultiplier(4) \
->Ranges({{1 << 14, 1 << 24}}) \
->Ranges({{1 << 14, 1 << 23}}) \
->UseManualTime() \
->Unit(benchmark::kMillisecond);

HASH_BENCHMARK_DEFINE(HASH_MURMUR3)
HASH_BENCHMARK_DEFINE(HASH_MD5)
HASH_BENCHMARK_DEFINE(HASH_SERIAL_MURMUR3)
HASH_BENCHMARK_DEFINE(HASH_SPARK_MURMUR3)
HASH_BENCHMARK_DEFINE(HASH_SHA1)
HASH_BENCHMARK_DEFINE(HASH_SHA224)
HASH_BENCHMARK_DEFINE(HASH_SHA256)
HASH_BENCHMARK_DEFINE(HASH_SHA384)
HASH_BENCHMARK_DEFINE(HASH_SHA512)
25 changes: 25 additions & 0 deletions cpp/include/cudf/detail/hashing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,31 @@ std::unique_ptr<column> serial_murmur_hash3_32(
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

std::unique_ptr<column> sha1_hash(
table_view const& input,
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

std::unique_ptr<column> sha224_hash(
table_view const& input,
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

std::unique_ptr<column> sha256_hash(
table_view const& input,
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

std::unique_ptr<column> sha384_hash(
table_view const& input,
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

std::unique_ptr<column> sha512_hash(
table_view const& input,
rmm::cuda_stream_view stream = rmm::cuda_stream_default,
rmm::mr::device_memory_resource* mr = rmm::mr::get_current_device_resource());

/* Copyright 2005-2014 Daniel James.
*
* Use, modification and distribution is subject to the Boost Software
Expand Down
101 changes: 101 additions & 0 deletions cpp/include/cudf/detail/utilities/hash_functions.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,107 @@ T CUDA_DEVICE_CALLABLE normalize_nans_and_zeros(T const& key)
return key;
}

CUDA_DEVICE_CALLABLE uint32_t rotate_bits_left(uint32_t x, int8_t r)
{
// This function is equivalent to (x << r) | (x >> (32 - r))
return __funnelshift_l(x, x, r);
}

CUDA_DEVICE_CALLABLE uint32_t rotate_bits_right(uint32_t x, int8_t r)
{
// This function is equivalent to (x >> r) | (x << (32 - r))
return __funnelshift_r(x, x, r);
}

CUDA_DEVICE_CALLABLE uint64_t rotate_bits_right(uint64_t x, int8_t r)
{
return (x >> r) | (x << (64 - r));
}

// Swap the endianness of a 32 bit value
CUDA_DEVICE_CALLABLE uint32_t swap_endian(uint32_t x)
{
// The selector 0x0123 reverses the byte order
return __byte_perm(x, 0, 0x0123);
}

// Swap the endianness of a 64 bit value
// There is no CUDA intrinsic for permuting bytes in 64 bit integers
CUDA_DEVICE_CALLABLE uint64_t swap_endian(uint64_t x)
{
// Reverse the endianness of each 32 bit section
uint32_t low_bits = swap_endian(static_cast<uint32_t>(x));
uint32_t high_bits = swap_endian(static_cast<uint32_t>(x >> 32));
// Reassemble a 64 bit result, swapping the low bits and high bits
return (static_cast<uint64_t>(low_bits) << 32) | (static_cast<uint64_t>(high_bits));
};

template <int capacity, typename hash_step_callable>
struct hash_circular_buffer {
uint8_t storage[capacity];
uint8_t* cur;
int available_space{capacity};
hash_step_callable hash_step;

CUDA_DEVICE_CALLABLE hash_circular_buffer(hash_step_callable hash_step)
: cur{storage}, hash_step{hash_step}
{
}

CUDA_DEVICE_CALLABLE void put(uint8_t const* in, int size)
{
int copy_start = 0;
while (size >= available_space) {
// The buffer will be filled by this chunk of data. Copy a chunk of the
// data to fill the buffer and trigger a hash step.
memcpy(cur, in + copy_start, available_space);
hash_step(storage);
size -= available_space;
copy_start += available_space;
cur = storage;
available_space = capacity;
}
// The buffer will not be filled by the remaining data. That is, `size >= 0
// && size < capacity`. We copy the remaining data into the buffer but do
// not trigger a hash step.
memcpy(cur, in + copy_start, size);
cur += size;
available_space -= size;
}

CUDA_DEVICE_CALLABLE void pad(int const space_to_leave)
{
if (space_to_leave > available_space) {
memset(cur, 0x00, available_space);
hash_step(storage);
cur = storage;
available_space = capacity;
}
memset(cur, 0x00, available_space - space_to_leave);
cur += available_space - space_to_leave;
available_space = space_to_leave;
}

CUDA_DEVICE_CALLABLE const uint8_t& operator[](int idx) const { return storage[idx]; }
};

// Get a uint8_t pointer to a column element and its size as a pair.
template <typename Element>
auto CUDA_DEVICE_CALLABLE get_element_pointer_and_size(Element const& element)
{
if constexpr (is_fixed_width<Element>() && !is_chrono<Element>()) {
return thrust::make_pair(reinterpret_cast<uint8_t const*>(&element), sizeof(Element));
} else {
cudf_assert(false && "Unsupported type.");
}
}

template <>
auto CUDA_DEVICE_CALLABLE get_element_pointer_and_size(string_view const& element)
{
return thrust::make_pair(reinterpret_cast<uint8_t const*>(element.data()), element.size_bytes());
}

/**
* Modified GPU implementation of
* https://johnnylee-sde.github.io/Fast-unsigned-integer-to-hex-string/
Expand Down
7 changes: 6 additions & 1 deletion cpp/include/cudf/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,12 @@ enum class hash_id {
HASH_MURMUR3, ///< Murmur3 hash function
HASH_MD5, ///< MD5 hash function
HASH_SERIAL_MURMUR3, ///< Serial Murmur3 hash function
HASH_SPARK_MURMUR3 ///< Spark Murmur3 hash function
HASH_SPARK_MURMUR3, ///< Spark Murmur3 hash function
HASH_SHA1, ///< SHA-1 hash function
HASH_SHA224, ///< SHA-224 hash function
HASH_SHA256, ///< SHA-256 hash function
HASH_SHA384, ///< SHA-384 hash function
HASH_SHA512 ///< SHA-512 hash function
};

/**
Expand Down
7 changes: 6 additions & 1 deletion cpp/src/hash/hashing.cu
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,12 @@ std::unique_ptr<column> hash(table_view const& input,
return serial_murmur_hash3_32<MurmurHash3_32>(input, seed, stream, mr);
case (hash_id::HASH_SPARK_MURMUR3):
return serial_murmur_hash3_32<SparkMurmurHash3_32>(input, seed, stream, mr);
default: return nullptr;
case (hash_id::HASH_SHA1): return sha1_hash(input, stream, mr);
case (hash_id::HASH_SHA224): return sha224_hash(input, stream, mr);
case (hash_id::HASH_SHA256): return sha256_hash(input, stream, mr);
case (hash_id::HASH_SHA384): return sha384_hash(input, stream, mr);
case (hash_id::HASH_SHA512): return sha512_hash(input, stream, mr);
default: CUDF_FAIL("Unsupported hash function.");
}
}

Expand Down
73 changes: 5 additions & 68 deletions cpp/src/hash/md5_hash.cu
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cudf/column/column_device_view.cuh>
#include <cudf/column/column_factories.hpp>
#include <cudf/detail/hashing.hpp>
#include <cudf/detail/iterator.cuh>
#include <cudf/detail/null_mask.hpp>
#include <cudf/detail/utilities/hash_functions.cuh>
#include <cudf/lists/lists_column_view.hpp>
#include <cudf/scalar/scalar.hpp>
Expand Down Expand Up @@ -55,72 +57,6 @@ const __constant__ uint32_t md5_hash_constants[64] = {
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
};

template <int capacity, typename hash_step_callable>
struct hash_circular_buffer {
uint8_t storage[capacity];
uint8_t* cur;
int available_space{capacity};
hash_step_callable hash_step;

CUDA_DEVICE_CALLABLE hash_circular_buffer(hash_step_callable hash_step)
: cur{storage}, hash_step{hash_step}
{
}

CUDA_DEVICE_CALLABLE void put(uint8_t const* in, int size)
{
int copy_start = 0;
while (size >= available_space) {
// The buffer will be filled by this chunk of data. Copy a chunk of the
// data to fill the buffer and trigger a hash step.
memcpy(cur, in + copy_start, available_space);
hash_step(storage);
size -= available_space;
copy_start += available_space;
cur = storage;
available_space = capacity;
}
// The buffer will not be filled by the remaining data. That is, `size >= 0
// && size < capacity`. We copy the remaining data into the buffer but do
// not trigger a hash step.
memcpy(cur, in + copy_start, size);
cur += size;
available_space -= size;
}

CUDA_DEVICE_CALLABLE void pad(int const space_to_leave)
{
if (space_to_leave > available_space) {
memset(cur, 0x00, available_space);
hash_step(storage);
cur = storage;
available_space = capacity;
}
memset(cur, 0x00, available_space - space_to_leave);
cur += available_space - space_to_leave;
available_space = space_to_leave;
}

CUDA_DEVICE_CALLABLE const uint8_t& operator[](int idx) const { return storage[idx]; }
};

// Get a uint8_t pointer to a column element and its size as a pair.
template <typename Element>
auto CUDA_DEVICE_CALLABLE get_element_pointer_and_size(Element const& element)
{
if constexpr (is_fixed_width<Element>() && !is_chrono<Element>()) {
return thrust::make_pair(reinterpret_cast<uint8_t const*>(&element), sizeof(Element));
} else {
cudf_assert(false && "Unsupported type.");
}
}

template <>
auto CUDA_DEVICE_CALLABLE get_element_pointer_and_size(string_view const& element)
{
return thrust::make_pair(reinterpret_cast<uint8_t const*>(element.data()), element.size_bytes());
}

struct MD5Hasher {
static constexpr int message_chunk_size = 64;

Expand Down Expand Up @@ -205,7 +141,7 @@ struct MD5Hasher {
A = D;
D = C;
C = B;
B = B + __funnelshift_l(F, F, md5_shift_constants[((j / 16) * 4) + (j % 4)]);
B = B + rotate_bits_left(F, md5_shift_constants[((j / 16) * 4) + (j % 4)]);
}

hash_values[0] += A;
Expand Down Expand Up @@ -309,7 +245,8 @@ std::unique_ptr<column> md5_hash(table_view const& input,
auto chars_view = chars_column->mutable_view();
auto d_chars = chars_view.data<char>();

rmm::device_buffer null_mask{0, stream, mr};
// Build an output null mask from the logical AND of all input columns' null masks.
rmm::device_buffer null_mask{cudf::detail::bitmask_and(input, stream)};

auto const device_input = table_device_view::create(input, stream);

Expand Down
Loading