Skip to content

Commit 79cbe23

Browse files
authored
Merge pull request #16 from cppalliance/CUDA_MD5
Add NVCC testing to MD5 and SHA1
2 parents 21d8cce + 52a2c7c commit 79cbe23

File tree

10 files changed

+513
-4
lines changed

10 files changed

+513
-4
lines changed

.github/workflows/cuda.yml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright 2024 Matt Borland
2+
# Distributed under the Boost Software License, Version 1.0.
3+
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
4+
5+
name: cuda
6+
on:
7+
push:
8+
branches:
9+
- master
10+
- develop
11+
- feature/**
12+
pull_request:
13+
release:
14+
types: [published, created, edited]
15+
16+
concurrency:
17+
group: ${{ github.head_ref || github.run_id }}
18+
cancel-in-progress: true
19+
20+
jobs:
21+
cuda-cmake-test:
22+
strategy:
23+
fail-fast: false
24+
25+
runs-on: gpu-runner-1
26+
27+
steps:
28+
- uses: Jimver/[email protected]
29+
id: cuda-toolkit
30+
with:
31+
cuda: '12.5.0'
32+
method: 'network'
33+
sub-packages: '["nvcc"]'
34+
35+
- name: Output CUDA information
36+
run: |
37+
echo "Installed cuda version is: ${{steps.cuda-toolkit.outputs.cuda}}"+
38+
echo "Cuda install location: ${{steps.cuda-toolkit.outputs.CUDA_PATH}}"
39+
nvcc -V
40+
- uses: actions/checkout@v4
41+
42+
- name: Install Packages
43+
run: |
44+
sudo apt-get install -y cmake make
45+
- name: Setup Boost
46+
run: |
47+
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
48+
LIBRARY=${GITHUB_REPOSITORY#*/}
49+
echo LIBRARY: $LIBRARY
50+
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
51+
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
52+
echo GITHUB_REF: $GITHUB_REF
53+
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
54+
REF=${REF#refs/heads/}
55+
echo REF: $REF
56+
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
57+
echo BOOST_BRANCH: $BOOST_BRANCH
58+
cd ..
59+
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
60+
cd boost-root
61+
mkdir -p libs/$LIBRARY
62+
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
63+
git submodule update --init tools/boostdep
64+
python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
65+
- name: Configure
66+
run: |
67+
cd ../boost-root
68+
mkdir __build__ && cd __build__
69+
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc -DBOOST_CRYPT_ENABLE_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES=70 -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-12.5 ..
70+
- name: Build tests
71+
run: |
72+
cd ../boost-root/__build__
73+
cmake --build . --target tests -j $(nproc)
74+
- name: Run tests
75+
run: |
76+
cd ../boost-root/__build__
77+
ctest --output-on-failure --no-tests=error

include/boost/crypt/hash/sha1.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class sha1_hasher
4444
bool computed {};
4545
bool corrupted {};
4646

47-
constexpr auto sha1_process_message_block() -> void;
47+
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1_process_message_block() -> void;
4848

4949
template <typename ForwardIter>
5050
BOOST_CRYPT_GPU_ENABLED constexpr auto sha1_update(ForwardIter data, boost::crypt::size_t size) noexcept -> hasher_state;
@@ -75,6 +75,7 @@ class sha1_hasher
7575

7676
namespace detail {
7777

78+
BOOST_CRYPT_GPU_ENABLED
7879
constexpr auto round1(boost::crypt::uint32_t& A,
7980
boost::crypt::uint32_t& B,
8081
boost::crypt::uint32_t& C,
@@ -90,6 +91,7 @@ constexpr auto round1(boost::crypt::uint32_t& A,
9091
A = temp;
9192
}
9293

94+
BOOST_CRYPT_GPU_ENABLED
9395
constexpr auto round2(boost::crypt::uint32_t& A,
9496
boost::crypt::uint32_t& B,
9597
boost::crypt::uint32_t& C,
@@ -105,6 +107,7 @@ constexpr auto round2(boost::crypt::uint32_t& A,
105107
A = temp;
106108
}
107109

110+
BOOST_CRYPT_GPU_ENABLED
108111
constexpr auto round3(boost::crypt::uint32_t& A,
109112
boost::crypt::uint32_t& B,
110113
boost::crypt::uint32_t& C,
@@ -120,6 +123,7 @@ constexpr auto round3(boost::crypt::uint32_t& A,
120123
A = temp;
121124
}
122125

126+
BOOST_CRYPT_GPU_ENABLED
123127
constexpr auto round4(boost::crypt::uint32_t& A,
124128
boost::crypt::uint32_t& B,
125129
boost::crypt::uint32_t& C,

include/boost/crypt/utility/cstddef.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ namespace crypt {
1616
using size_t = unsigned long;
1717
using ptrdiff_t = long;
1818
using nullptr_t = void;
19-
using std::max_align_t = double;
20-
19+
using max_align_t = double;
2120

2221
} // namespace crypt
2322
} // namespace boost

include/boost/crypt/utility/iterator.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@
1313

1414
namespace boost {
1515
namespace crypt {
16+
namespace utility {
1617

1718
template <typename Iter>
1819
struct iterator_traits : public cuda::std::iterator_traits<Iter> {};
1920

2021
template <typename T>
2122
struct iterator_traits<T*> : public cuda::std::iterator_traits<T*> {};
2223

24+
} // namespace utility
2325
} // namespace crypt
2426
} // namespace boost
2527

test/CMakeLists.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
77

88
if(HAVE_BOOST_TEST)
99

10-
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::crypt Boost::core Boost::uuid)
10+
if (BOOST_CRYPT_ENABLE_CUDA)
11+
12+
message(STATUS "Building boost.crypt with CUDA")
13+
find_package(CUDA REQUIRED)
14+
enable_language(CUDA)
15+
set(CMAKE_CUDA_EXTENSIONS OFF)
16+
17+
boost_test_jamfile(FILE nvcc_jamfile LINK_LIBRARIES Boost::crypt ${CUDA_LIBRARIES} INCLUDE_DIRECTORIES ${CUDA_INCLUDE_DIRS} )
18+
19+
else ()
20+
21+
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::crypt Boost::core Boost::uuid)
22+
23+
endif ()
1124

1225
endif()

test/cuda_managed_ptr.hpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
2+
// Copyright John Maddock 2016.
3+
// Use, modification and distribution are subject to the
4+
// Boost Software License, Version 1.0. (See accompanying file
5+
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_MATH_CUDA_MANAGED_PTR_HPP
8+
#define BOOST_MATH_CUDA_MANAGED_PTR_HPP
9+
10+
#ifdef _MSC_VER
11+
#pragma once
12+
#endif
13+
14+
#include <iostream>
15+
#include <cuda_runtime.h>
16+
17+
class managed_holder_base
18+
{
19+
protected:
20+
static int count;
21+
managed_holder_base() { ++count; }
22+
~managed_holder_base()
23+
{
24+
if(0 == --count)
25+
cudaDeviceSynchronize();
26+
}
27+
};
28+
29+
int managed_holder_base::count = 0;
30+
31+
//
32+
// Reset the device and exit:
33+
// cudaDeviceReset causes the driver to clean up all state. While
34+
// not mandatory in normal operation, it is good practice. It is also
35+
// needed to ensure correct operation when the application is being
36+
// profiled. Calling cudaDeviceReset causes all profile data to be
37+
// flushed before the application exits.
38+
//
39+
// We have a global instance of this class, plus instances for each
40+
// managed pointer. Last one out the door switches the lights off.
41+
//
42+
class cudaResetter
43+
{
44+
static int count;
45+
public:
46+
cudaResetter() { ++count; }
47+
~cudaResetter()
48+
{
49+
if(--count == 0)
50+
{
51+
cudaError_t err = cudaDeviceReset();
52+
if(err != cudaSuccess)
53+
{
54+
std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl;
55+
}
56+
}
57+
}
58+
};
59+
60+
int cudaResetter::count = 0;
61+
62+
cudaResetter global_resetter;
63+
64+
template <class T>
65+
class cuda_managed_ptr
66+
{
67+
T* data;
68+
static const cudaResetter resetter;
69+
cuda_managed_ptr(const cuda_managed_ptr&) = delete;
70+
cuda_managed_ptr& operator=(cuda_managed_ptr const&) = delete;
71+
void free()
72+
{
73+
if(data)
74+
{
75+
cudaDeviceSynchronize();
76+
cudaError_t err = cudaFree(data);
77+
if(err != cudaSuccess)
78+
{
79+
std::cerr << "Failed to deinitialize the device! error=" << cudaGetErrorString(err) << std::endl;
80+
}
81+
}
82+
}
83+
public:
84+
cuda_managed_ptr() : data(0) {}
85+
cuda_managed_ptr(std::size_t n)
86+
{
87+
cudaError_t err = cudaSuccess;
88+
void *ptr;
89+
err = cudaMallocManaged(&ptr, n * sizeof(T));
90+
if(err != cudaSuccess)
91+
throw std::runtime_error(cudaGetErrorString(err));
92+
cudaDeviceSynchronize();
93+
data = static_cast<T*>(ptr);
94+
}
95+
cuda_managed_ptr(cuda_managed_ptr&& o)
96+
{
97+
data = o.data;
98+
o.data = 0;
99+
}
100+
cuda_managed_ptr& operator=(cuda_managed_ptr&& o)
101+
{
102+
free();
103+
data = o.data;
104+
o.data = 0;
105+
return *this;
106+
}
107+
~cuda_managed_ptr()
108+
{
109+
free();
110+
}
111+
112+
class managed_holder : managed_holder_base
113+
{
114+
T* pdata;
115+
public:
116+
managed_holder(T* p) : managed_holder_base(), pdata(p) {}
117+
managed_holder(const managed_holder& o) : managed_holder_base(), pdata(o.pdata) {}
118+
operator T* () { return pdata; }
119+
T& operator[] (std::size_t n) { return pdata[n]; }
120+
};
121+
class const_managed_holder : managed_holder_base
122+
{
123+
const T* pdata;
124+
public:
125+
const_managed_holder(T* p) : managed_holder_base(), pdata(p) {}
126+
const_managed_holder(const managed_holder& o) : managed_holder_base(), pdata(o.pdata) {}
127+
operator const T* () { return pdata; }
128+
const T& operator[] (std::size_t n) { return pdata[n]; }
129+
};
130+
131+
managed_holder get() { return managed_holder(data); }
132+
const_managed_holder get()const { return data; }
133+
T& operator[](std::size_t n) { return data[n]; }
134+
const T& operator[](std::size_t n)const { return data[n]; }
135+
};
136+
137+
template <class T>
138+
cudaResetter const cuda_managed_ptr<T>::resetter;
139+
140+
#endif

test/nvcc_jamfile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2024 Matt Borland
2+
# Distributed under the Boost Software License, Version 1.0.
3+
# https://www.boost.org/LICENSE_1_0.txt
4+
5+
import testing ;
6+
import ../../config/checks/config : requires ;
7+
8+
project : requirements
9+
[ requires cxx14_decltype_auto cxx14_generic_lambdas cxx14_return_type_deduction cxx14_variable_templates cxx14_constexpr ]
10+
;
11+
12+
run test_md5_nvcc.cu ;
13+
run test_sha1_nvcc.cu ;

test/stopwatch.hpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright John Maddock 2016.
2+
// Use, modification and distribution are subject to the
3+
// Boost Software License, Version 1.0. (See accompanying file
4+
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5+
6+
#ifndef BOOST_MATH_CUDA_STOPWATCH_HPP
7+
#define BOOST_MATH_CUDA_STOPWATCH_HPP
8+
9+
#ifdef _MSC_VER
10+
#pragma once
11+
#endif
12+
13+
#include <chrono>
14+
15+
template <class Clock>
16+
struct stopwatch
17+
{
18+
typedef typename Clock::duration duration;
19+
stopwatch()
20+
{
21+
m_start = Clock::now();
22+
}
23+
double elapsed()
24+
{
25+
duration t = Clock::now() - m_start;
26+
return std::chrono::duration_cast<std::chrono::duration<double>>(t).count();
27+
}
28+
void reset()
29+
{
30+
m_start = Clock::now();
31+
}
32+
33+
private:
34+
typename Clock::time_point m_start;
35+
};
36+
37+
typedef stopwatch<std::chrono::high_resolution_clock> watch;
38+
39+
#endif

0 commit comments

Comments
 (0)