Alex_McAvoy

想要成为渔夫的猎手

NVIDIA CUDA2023春训营(六)CUDA 错误检测

Reference

错误类型

CUDA 的 Runtime API 都带有 cudaError_t 类型的返回值,其是一个封装了各错误码的枚举类,常见的取值如下:

  • cudaSuccess:函数执行成功,没有错误
  • cudaErrorInvalidValue:传递给 API 调用的一个或多个参数不在可接受的范围内
  • cudaErrorMemoryAllocation:无法分配足够的内存来执行请求的操作
  • cudaErrorInitializationError:无法初始化 CUDA 驱动程序
  • cudaErrorCudartUnloading:无法检测到 CUDA 驱动

更多的取值信息详见 CUDA 官方文档

错误检测

CUDA 提供了相应的错误信息函数,常用的有以下两个:

  • cudaGetErrorName(cudaError_t error):返回错误代码 error 对应的错误类型名
  • cudaGetErrorString(cudaError_t error):返回错误代码 error 对应的具体信息

在 CUDA 运行时,每个线程都会维护一个初始值为 cudaSuccess 的错误变量,并在每次发生错误时被错误代码覆盖,使用如下两个函数可以检测出现错误时的错误代码:

  • cudaGetLastError():返回维护的错误变量值
  • cudaPeekAtLastError():返回维护的错误变量值并将其重置为 cudaSuccess

利用上述的函数,即可组合使用来检测 runtime API 是否运行成功,例如:

1
2
cudaMalloc(...)
printf("cudaMalloc function : %s\n",cudaGetErrorString(cudaGetLastError()));

封装实例

下面给出一个将 cudaGetErrorString() 封装成 error.cuh 中的一个宏的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
#include <stdio.h>

#define CHECK(call) \
do { \
const cudaError_t error_code = call; \
if (error_code != cudaSuccess) { \
printf("CUDA Error:\n"); \
printf(" File: %s\n", __FILE__); \
printf(" Line: %d\n", __LINE__); \
printf(" Error code: %d\n", error_code); \
printf(" Error text: %s\n", \
cudaGetErrorString(error_code)); \
exit(1); \
} \
} while (0)

那么就可以在代码中这么使用:

1
2
3
4
5
6
7
#include "error.cuh"

int main() {
int *a;
CHECK(cudaMallocHost((void **) &a, sizeof(int)*100));
return 0;
}
感谢您对我的支持,让我继续努力分享有用的技术与知识点!