1
+ /*
2
+ Copyright 2025 Equinor ASA
3
+
4
+ This file is part of the Open Porous Media project (OPM).
5
+ OPM is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+ OPM is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+ You should have received a copy of the GNU General Public License
14
+ along with OPM. If not, see <http://www.gnu.org/licenses/>.
15
+ */
16
+ #include < boost/test/tools/old/interface.hpp>
17
+ #include < config.h>
18
+ #include < stdexcept>
19
+
20
+ #define BOOST_TEST_MODULE TestThrowMacrosOnGPU
21
+
22
+ #include < cuda.h>
23
+ #include < cuda_runtime.h>
24
+ #include < boost/test/unit_test.hpp>
25
+ #include < opm/common/ErrorMacros.hpp>
26
+ #include < opm/simulators/linalg/gpuistl/detail/gpu_safe_call.hpp>
27
+
28
+ namespace {
29
+ __global__ void codeThatContainsMacros (bool call) {
30
+ if (call) {
31
+ OPM_THROW (std::logic_error, " Something went wrong" );
32
+ OPM_THROW_NOLOG (std::logic_error, " Something went wrong" );
33
+ OPM_THROW_PROBLEM (std::logic_error, " Something went wrong" );
34
+ }
35
+ OPM_ERROR_IF (!call, " Something went horribly wrong" );
36
+ }
37
+
38
+ // TODO: Check if this is better on HIP
39
+ #if 0 // I am leaving this here to show that this is not possible due to limitations in CUDA
40
+ // the assert will indeed cause an error, but the CUDA context will be broken for
41
+ // the rest of the lifetime of the process, see
42
+ // https://forums.developer.nvidia.com/t/how-to-clear-cuda-errors/296393/5
43
+ __global__ void checkThrow() {
44
+ OPM_THROW(std::logic_error, "Something went wrong");
45
+ }
46
+
47
+ __global__ void checkThrowNoLog() {
48
+ OPM_THROW_NOLOG(std::logic_error, "Something went wrong");
49
+ }
50
+
51
+ __global__ void checkThrowProblem() {
52
+ OPM_THROW_PROBLEM(std::logic_error, "Something went wrong");
53
+ }
54
+
55
+ __global__ void checkErrorIf() {
56
+ OPM_ERROR_IF(true, "Something went horribly wrong");
57
+ }
58
+ #endif
59
+ }
60
+
61
+ BOOST_AUTO_TEST_CASE (TestKernel)
62
+ {
63
+ OPM_GPU_SAFE_CALL (cudaDeviceSynchronize ());
64
+ OPM_GPU_SAFE_CALL (cudaGetLastError ());
65
+ codeThatContainsMacros<<<1 , 1 >>> (false );
66
+ OPM_GPU_SAFE_CALL (cudaDeviceSynchronize ());
67
+ OPM_GPU_SAFE_CALL (cudaGetLastError ());
68
+
69
+ #if 0 // I am leaving this here to show that this is not possible due to limitations in CUDA
70
+ // the assert will indeed cause an error, but the CUDA context will be broken for
71
+ // the rest of the lifetime of the process, see
72
+ // https://forums.developer.nvidia.com/t/how-to-clear-cuda-errors/296393/5
73
+ codeThatContainsMacros<<<1, 1>>>(true);
74
+ // Make sure this actually throws
75
+ BOOST_CHECK_THROW(OPM_GPU_SAFE_CALL(cudaDeviceSynchronize()), std::runtime_error);
76
+ OPM_GPU_SAFE_CALL(cudaDeviceReset());
77
+ OPM_GPU_SAFE_CALL(cudaGetLastError());
78
+
79
+ checkThrow<<<1, 1>>>();
80
+ BOOST_CHECK_THROW(OPM_GPU_SAFE_CALL(cudaDeviceSynchronize()), std::runtime_error);
81
+ OPM_GPU_SAFE_CALL(cudaDeviceReset());
82
+ OPM_GPU_SAFE_CALL(cudaGetLastError());
83
+
84
+ checkThrowNoLog<<<1, 1>>>();
85
+ BOOST_CHECK_THROW(OPM_GPU_SAFE_CALL(cudaDeviceSynchronize()), std::runtime_error);
86
+ OPM_GPU_SAFE_CALL(cudaDeviceReset());
87
+ OPM_GPU_SAFE_CALL(cudaGetLastError());
88
+
89
+ checkThrowProblem<<<1, 1>>>();
90
+ BOOST_CHECK_THROW(OPM_GPU_SAFE_CALL(cudaDeviceSynchronize()), std::runtime_error);
91
+ OPM_GPU_SAFE_CALL(cudaDeviceReset());
92
+ OPM_GPU_SAFE_CALL(cudaGetLastError());
93
+
94
+ checkErrorIf<<<1, 1>>>();
95
+ BOOST_CHECK_THROW(OPM_GPU_SAFE_CALL(cudaDeviceSynchronize()), std::runtime_error);
96
+ OPM_GPU_SAFE_CALL(cudaDeviceReset());
97
+ OPM_GPU_SAFE_CALL(cudaGetLastError());
98
+ #endif
99
+ }
100
+
101
+ BOOST_AUTO_TEST_CASE (TestOutsideKernel)
102
+ {
103
+ // This is to make sure that the macros work outside of kernels but inside a .cu file
104
+ // ie. inside a file compiled by nvcc/hipcc.
105
+ BOOST_CHECK_THROW (OPM_THROW (std::runtime_error, " THROW" ), std::runtime_error);
106
+ BOOST_CHECK_THROW (OPM_THROW_NOLOG (std::runtime_error, " THROW_NOLOG" ), std::runtime_error);
107
+ BOOST_CHECK_THROW (OPM_THROW_PROBLEM (std::runtime_error, " THROW_PROBLEM" ), std::runtime_error);
108
+ BOOST_CHECK_THROW (OPM_ERROR_IF (true , " ERROR_IF" ), std::logic_error);
109
+ }
0 commit comments