爨爨爨好

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 在核函数中使用强制终止函数 assert()。并且在静态代码和运行时编译两种条件下使用。

▶ 源代码:静态使用

 1 #include <windows.h>
 2 #include <stdio.h>
 3 #include <cuda_runtime.h>
 4 #include "device_launch_parameters.h"
 5 #include <helper_functions.h>
 6 #include <helper_cuda.h>
 7 
 8 #define WINDOWS_LEAN_AND_MEAN
 9 #define NOMINMAX
10 
11 __global__ void testKernel(int N)
12 {
13     int tid = blockIdx.x*blockDim.x + threadIdx.x ;
14     
15     // 检查条件为“线程总编号小于 N”,即阻塞不满足该条件的线程
16     // 阻塞的同时向屏幕输出阻塞线程的信息,包括核函数所在文件绝对路径、行号、线程块号,线程号,没有通过的检查条件
17     assert(tid < N) ;
18 }
19 
20 bool runTest()
21 {
22     // 使用2个线程块各32条线程,使用 assert() 阻塞最后 4 条(即第 1 线程块的第 29、30、31、32 号线程)
23     int Nblocks = 2;
24     int Nthreads = 32;
25     cudaError_t error ;
26 
27     dim3 dimGrid(Nblocks);
28     dim3 dimBlock(Nthreads);
29     testKernel<<<dimGrid, dimBlock>>>(60);
30 
31     printf("\n-- Begin assert output\n\n");
32     error = cudaDeviceSynchronize();        // 使用设备同步来获取错误信息
33     printf("\n-- End assert output\n\n");
34     
35     if (error == cudaErrorAssert)           // 输出错误信息种类
36         printf("CUDA error message is: %s\n",cudaGetErrorString(error));
37 
38     return error == cudaErrorAssert;
39 }
40 
41 int main()
42 {
43     bool testResult; 
44     
45     printf("\n\tStarted!\n");
46 
47     testResult = runTest();
48 
49     printf("\n\tCompleted! main function returned %s\n", testResult ? "OK!" : "ERROR!");
50     getchar();
51 
52     return 0;
53 }

即时编译版:

1 /*simpleAssert_kernel.cu*/
2 extern "C" __global__ void testKernel(int N)
3 {
4     int tid = blockIdx.x*blockDim.x + threadIdx.x ;
5     assert(tid < N) ;
6 }
 1 /*simpleAssert.cpp*/
 2 #include <windows.h>
 3 #include <stdio.h>
 4 #include <cuda_runtime.h>
 5 #include <helper_functions.h>
 6 #include "nvrtc_helper.h"
 7 
 8 #define WINDOWS_LEAN_AND_MEAN
 9 #define NOMINMAX
10 
11 bool runTest()
12 {
13     int Nblocks = 2;
14     int Nthreads = 32;
15 
16     // 紧张的 .cu 即时编译过程
17     char *kernel_file = sdkFindFilePath("simpleAssert_kernel.cu", NULL);
18 
19     char *ptx;
20     size_t ptxSize;
21     compileFileToPTX(kernel_file, 0, NULL, &ptx, &ptxSize);
22 
23     CUmodule module = loadPTX(ptx, 1, NULL);
24     
25     CUfunction kernel_addr;
26     cuModuleGetFunction(&kernel_addr, module, "testKernel");
27 
28     dim3 dimGrid(Nblocks);
29     dim3 dimBlock(Nthreads);
30     int count = 60;
31     void *args[] = { (void *)&count };
32     cuLaunchKernel(kernel_addr,dimGrid.x, dimGrid.y, dimGrid.z,dimBlock.x, dimBlock.y, dimBlock.z,0,0,&args[0],0);
33 
34     printf("\n-- Begin assert output\n\n");
35     CUresult res = cuCtxSynchronize();      // 用的是上下文同步?
36     printf("\n-- End assert output\n\n");
37 
38     if (res == CUDA_ERROR_ASSERT)
39         printf("Device assert failed as expected\n");
40 
41     return res == CUDA_ERROR_ASSERT ;
42 }
43 
44 int main()
45 {
46     bool testResult;
47 
48     printf("\n\tStarted!\n");
49 
50     testResult = runTest();
51 
52     printf("\n\tCompleted! main function returned %s\n", testResult ? "OK!" : "ERROR!");
53     getchar();
54 
55     return 0;
56 }

 

▶ 输出结果:

    Started!

-- Begin assert output

D:/Program/CUDA/Samples/0_Simple/simpleAssert/simpleAssert.cu:18: block: [1,0,0], thread: [28,0,0] Assertion `tid < N` failed.
D:/Program/CUDA/Samples/0_Simple/simpleAssert/simpleAssert.cu:18: block: [1,0,0], thread: [29,0,0] Assertion `tid < N` failed.
D:/Program/CUDA/Samples/0_Simple/simpleAssert/simpleAssert.cu:18: block: [1,0,0], thread: [30,0,0] Assertion `tid < N` failed.
D:/Program/CUDA/Samples/0_Simple/simpleAssert/simpleAssert.cu:18: block: [1,0,0], thread: [31,0,0] Assertion `tid < N` failed.

-- End assert output

CUDA error message is: device-side assert triggered

    Completed! main function returned OK!

 

▶ 涨姿势:

● 在核函数中使用  assert( condition )  来检查各线程中是否满足某条件。
    若不满足条件 condition,则强制终止该线程,并输出核函数所在文件绝对路径、行号、线程块号,线程号,没有通过的检查条件
    返回错误种类: cudaErrorAssert,错误代码 59,信息为 device-side assert triggered
    cudaErrorAssert 为定义在 driver_type.h 中的枚举类型  enum __device_builtin__ cudaError{...};  中,记录了各种错误信息。

 

● 调用核函数的另一种方法。使用定义在 cuda.h 中的函数 cuLaunchKernel。使用的参数与 <<< >>> 方式基本相同。

 1 CUresult CUDAAPI cuLaunchKernel
 2 (
 3     CUfunction f,
 4     unsigned int gridDimX, unsigned int gridDimY, unsigned int gridDimZ,
 5     unsigned int blockDimX, unsigned int blockDimY, unsigned int blockDimZ,
 6     unsigned int sharedMemBytes,
 7     CUstream hStream,
 8     void **kernelParams,
 9     void **extra
10 );

 

● 两种方法使用的同步函数

  静态方法时使用的是设备同步  extern __host__ __cudart_builtin__ cudaError_t CUDARTAPI cudaDeviceSynchronize(void);,定义在 cuda_runtime_api.h 中

  即时编译时用的是上下文同步  CUresult CUDAAPI cuCtxSynchronize(void); ,定义在 cuda.h 中

  尚不清楚两者的差别,等待填坑。

posted on 2017-11-02 23:55  爨爨爨好  阅读(517)  评论(0)    收藏  举报