ORT(ONNX runtime)GPU 问题总结

现象

bt的堆栈信息

ORT(ONNX runtime)GPU 问题总结_第1张图片

standard io上的错误输出

ORT(ONNX runtime)GPU 问题总结_第2张图片

从报错信息上看是非法的内存访问,但是报错的位置不一定是真实的位置,因为GPU都是异步发起的,错误可能会被在后面的op捕捉。例如cudaEventDestory:

ORT(ONNX runtime)GPU 问题总结_第3张图片

 debug方式

思维方式  

  1. 复现,解决问题一定要复现问题,不能复现的问题不能确定正真解决。所以首先要做的是复现。
  2. 定位,定位范围是逐渐缩小,优先排查自定义的代码。对于cuda-kernel,默认都是异步的操作,很多时候捕获错误的位置在抛出错误位置的后面。这种情况可以在可能出错的op后面加上下面代码:
 CUDA_RETURN_IF_ERROR(cudaStreamSynchronize(stream));

 cuda-memcheck

命令行,使用cuda-memcheck的工具memcheck,当然它还有另外的三个工具,详情看文档。

cuda-memcheck --tool memcheck [application application-option]

结果返回发生越界的thread号和block号。 

然后通过block和thread的坐标信息,借助cuda-gdb工具,定位到具体的位置。

cuda-gdb

在编译时,给nvcc加上-g -G标识(cmake中是CMAKE_CUDA_FLAGS),就可以得到device的debug符号信息,其中的-G是标识开启device的debug编译。

set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -g -G")

Debug的操作指令: 

# switch to the forced thread and block
cuda kernel 0 block (3,103,0) thread(0,0,0)

# condition breakpoint
b file:498 if blockIdx.y==103 && blockIdx.x==3

# set conditions for an existing breakpoint
condition 1 blockIdx.x == 0 && n > 3

ORT(ONNX runtime)GPU 问题总结_第4张图片

 找到了具体越界的位置。

printf定位具体位置

对于代码比较简单,但是并发度很高的cuda-kernel-func,采用这个方式比较高效。但是需要注意:

  1.  ort里的cuda代码默认是开启了O3的优化等级的。如果注释掉一些代码,相关的一些代码可能被优化掉。解决方法:把删除的代码中的变量,用printf加上,可以屏蔽这个优化,当然也可以开启nvcc的debug模式。
  2. cuda-kernel里的printf要注意数据的字节数,例如,int64的类型,在打印的时候需要加l(%ld),不然会引起错位,该字符串后面的输出,都会出现错误。

参考文档

https://on-demand.gputechconf.com/gtc/2014/presentations/S4580-cuda-gdb-cuda-memcheck-debugging-tools.pdf

https://ece.northeastern.edu/groups/nucar/Analogic/cuda-gdb.pdf

你可能感兴趣的:(C++/C,CUDA,开发语言,深度学习)