error.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2022, NVIDIA CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 #include <cuda.h>
20 #include <cuda_runtime_api.h>
21 #include <stdexcept>
22 #include <string>
23 
24 namespace cudf {
37 struct logic_error : public std::logic_error {
38  logic_error(char const* const message) : std::logic_error(message) {}
39 
40  logic_error(std::string const& message) : std::logic_error(message) {}
41 
42  // TODO Add an error code member? This would be useful for translating an
43  // exception to an error code in a pure-C API
44 };
48 struct cuda_error : public std::runtime_error {
49  cuda_error(std::string const& message, cudaError_t const& error)
50  : std::runtime_error(message), _cudaError(error)
51  {
52  }
53 
54  public:
55  cudaError_t error_code() const { return _cudaError; }
56 
57  protected:
58  cudaError_t _cudaError;
59 };
60 
61 struct fatal_cuda_error : public cuda_error {
62  using cuda_error::cuda_error;
63 };
66 } // namespace cudf
67 
68 #define STRINGIFY_DETAIL(x) #x
69 #define CUDF_STRINGIFY(x) STRINGIFY_DETAIL(x)
70 
91 #define CUDF_EXPECTS(cond, reason) \
92  (!!(cond)) ? static_cast<void>(0) \
93  : throw cudf::logic_error("cuDF failure at: " __FILE__ \
94  ":" CUDF_STRINGIFY(__LINE__) ": " reason)
95 
109 #define CUDF_FAIL(reason) \
110  throw cudf::logic_error("cuDF failure at: " __FILE__ ":" CUDF_STRINGIFY(__LINE__) ": " reason)
111 
112 namespace cudf {
113 namespace detail {
114 
115 inline void throw_cuda_error(cudaError_t error, const char* file, unsigned int line)
116 {
117  // Calls cudaGetLastError twice. It is nearly certain that a fatal error occurred if the second
118  // call doesn't return with cudaSuccess.
119  cudaGetLastError();
120  auto const last = cudaGetLastError();
121  auto const msg = std::string{"CUDA error encountered at: " + std::string{file} + ":" +
122  std::to_string(line) + ": " + std::to_string(error) + " " +
123  cudaGetErrorName(error) + " " + cudaGetErrorString(error)};
124  // Call cudaDeviceSynchronize to ensure `last` did not result from an asynchronous error.
125  // between two calls.
126  if (error == last && last == cudaDeviceSynchronize()) {
127  throw fatal_cuda_error{"Fatal " + msg, error};
128  } else {
129  throw cuda_error{msg, error};
130  }
131 }
132 } // namespace detail
133 } // namespace cudf
134 
142 #define CUDF_CUDA_TRY(call) \
143  do { \
144  cudaError_t const status = (call); \
145  if (cudaSuccess != status) { cudf::detail::throw_cuda_error(status, __FILE__, __LINE__); } \
146  } while (0);
147 
161 #ifndef NDEBUG
162 #define CUDF_CHECK_CUDA(stream) \
163  do { \
164  CUDF_CUDA_TRY(cudaStreamSynchronize(stream)); \
165  CUDF_CUDA_TRY(cudaPeekAtLastError()); \
166  } while (0);
167 #else
168 #define CUDF_CHECK_CUDA(stream) CUDF_CUDA_TRY(cudaPeekAtLastError());
169 #endif
170 
cudf::fatal_cuda_error
Definition: error.hpp:61
cudf::cuda_error
Exception thrown when a CUDA error is encountered.
Definition: error.hpp:48
cudf
cuDF interfaces
Definition: aggregation.hpp:34
cudf::logic_error
Exception thrown when logical precondition is violated.
Definition: error.hpp:37