相关文章推荐
神勇威武的感冒药  ·  Android ...·  1 年前    · 
傻傻的键盘  ·  matlab importdata ...·  1 年前    · 

报错解决:CUDA Runtime error(an illegal memory access was encountered, cudaErrorIllegalAddress = 700)

博主在cuda编程时,遇到了报错:

CUDA Runtime error cudaEventSynchronize(end_) # an illegal memory access was encountered, code = cudaErrorIllegalAddress [ 700 ]

出现该现象,在框架稳定的背景下基本上可以确定是网络中有算子踩显存,因此CUDA上报非法内存访问,错误码为700,可能原因如下:

  1. 访问越界问题:算子计算过程中使用的size比申请的显存大了,导致访问越界。
  2. 同步与异步问题:由于GPU的算子执行是host下发到device上异步执行的,host使用了CUDA一些同步接口导致不是device的期望值出现非法内存。

解决方法是首先排查是否是访问越界问题,若不是,接着排查是否是同步与异步问题。

访问越界问题

由于GPU的算子执行是host下发到device上异步执行的,因此执行报错的地方不一定是bug所在,可能是前面的算子有bug,但是device是异步执行的,所以执行到后面才会报错。

因此可以设置环境变量export CUDA_LAUNCH_BLOCKING=1表示阻塞式执行,即一个算子在device执行完成后,host才会下发一个算子到device上执行,这种完全同步执行方式下如果还是报此错误(非法内存访问)的话,配合算子执行日志就可以初步确定是当前执行算子的问题了。

接着,可以利用Compute Sanitizer工具进一步检查,并可以进一步验证是否是此算子的问题。

Compute Sanitizer 是一套工具,可以对代码的功能正确性执行不同类型的检查。调试的一个关键挑战是找到错误的根本原因,解决它通常比追踪它更容易,尤其是在并行执行环境中,因为在这种环境中,错误的来源可能是瞬态的。

Compute Sanitizer 通过检查代码是否存在内存访问违规、竞争条件、对未初始化变量的访问以及同步错误,擅长于根本原因调试。所有这些都可能表现为 bug,但其行为不一定会直接导致源代码中的根本原因。

您可能已经熟悉一种用于调试的工具:cuda-memcheck。但是,该工具已在 CUDA 11.6 中被弃用,并在 ZCk 12.0 及更高版本中被删除。Compute Sanitizer 已取代它的位置,提供了额外的功能,如改进的性能和对 Microsoft hardware-accelerated GPU scheduling 的支持,以及对内存检查之外的功能的更广泛支持。

Compute Sanitizer 中有四个主要工具:

  • memcheck:用于内存访问错误和泄漏检测
  • racecheck:共享内存数据访问危险检测工具
  • initcheck:未初始化的设备全局内存访问检测工具
  • synccheck:用于线程同步危险检测

除了这些工具, Compute Sanitizer 还有一些额外的功能:

  • 用于创建针对 CUDA 应用程序的清理和跟踪工具的 API 。
  • 与 NVIDIA 工具扩展(NVTX)集成
  • Coredump 支持可用于 cuda-gdb

使用方法:compute-sanitizer [options] app_name [app_options]

运行如下命令:

compute-sanitizer --launch-timeout=0 --tool=memcheck ./example > opt.txt 2>&1

打开opt.txt,查看输出:

cat opt.txt

示例输出:

========= COMPUTE-SANITIZER
Before: Array 0, 1 .. N-1: 1.000000 1.000000 1.000000
========= Invalid __global__ read of size 4 bytes
=========     at 0x70 in /home/pgraham/devblog/NCS/example1.cu:8:scaleArray(float *, float)
=========     by thread (255,0,0) in block (3,0,0)
=========     Address 0x7f3aae000ffc is out of bounds
=========     and is 1 bytes after the nearest allocation at 0x7f3aae000000 of size 4092 bytes

首先,由上述输出得到错误 info Invalid __global__ read,因为 GPU 正试图读取某个不是合法地址的全局存储器。然后,可以获得报错代码文件和行号,以及导致此问题的实际线程和块。在这种情况下,example1.cu:8 映射到代码中的array[threadGlobalID] = array[threadGlobalID]*value;

使用printf查看索引的值,观察是否越界。

最简单的修改方法是在数组访问前添加对索引的判断条件:if (threadGlobalID<N)

同步与异步问题

执行上述的操作后问题不复现,也就是同步执行的这种方式下没有问题,基本上可以确定是有算子里依赖同步执行的结果,因为正常device算子执行是异步执行,所以拿的结果不是预期值,同步执行就掩盖了这个问题。出现这种情况,除了阅读代码去确认是哪个算子里有使用同步操作接口外,一般可以通过二分法去加同步流来去定位(如果一个网络中有100个算子,可以在第50个算子加同步流,如果加了同步流没有复现,说明就前面的某个算子有问题了),同步流添加方法:在GPUDeviceContext::LaunchKernel函数中调用DoLaunchKernel后面增加SyncStream()

  1. 算子实现逻辑中针对size需要check,确保访问不越界。
  2. 由于GPU的算子执行是host下发到device上异步执行的,尽量避免使用CUDA同步接口,如果使用的话,需要确保数据是正确的。
  1. https://developer.nvidia.com/zh-cn/blog/debugging-cuda-more-efficiently-with-nvidia-compute-sanitizer/
  2. https://www.cnblogs.com/cxl11/articles/15730720.html
  3. https://stackoverflow.com/questions/27277365/unspecified-launch-failure-on-memcpy/27278218#27278218
  4. https://blog.csdn.net/Bit_Coders/article/details/113181262
  5. https://blog.csdn.net/LostUnravel/article/details/133780624
  6. https://forums.developer.nvidia.com/t/compute-sanitizer-not-quite-a-drop-in-replacement-of-cuda-memcheck/225877/6
报错原因: 这种报错的本质就是模型model、输入数据(input_image、input_label)没有全部移动到GPU(cuda)上。 **温馨提示:**debug时一定要仔细检查是否每一个输入变量以及网络模型都移动到了GPU上,我一般报错都是因为漏掉了其中一两个。 解决方法: 将model、input_image、input_label全部移动到cuda上,实... 然而使用CPU跑却可以 报错 RuntimeError: CUDA error: an illegal memory access was encountered CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be ...
RuntimeError: CUDA error: invalid device ordinalCUDA kernel errors might be asynchronously reported
RuntimeError: CUDA error: invalid device ordinal CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect. For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
这个error发生在我得到训练好的Decoder之后,对latent space采样并生成新数据的时候,如下 RuntimeError: cuda runtime error (700) : an illegal memory access was encountered at ..\aten\src\THC\THCCachingHostAllocator.cpp:278 问题出在如何把数据sample存储在gpu上:torch.tensor(sample, device=device)。其中de
pytorch1.6版本在训练时报错RuntimeError: CUDA error: an illegal memory access was encountered 报错原因与低版本的pytorch(如1.1版本)报错相同: RuntimeError: Expected object of backend CUDA but got backend CPU for argument # 解决方法: https://blog.csdn.net/weixin_44414948/article/detai
用pytorch在多卡训练transformers的时候出现了以下问题: RuntimeError: CUDA error: an illegal memory access was encountered terminate called after throwing an instance of 'c10::Error' what(): CUDA error: an illegal memory access was encountered Exception raised from create
先说一下在网上看到的问题: 第一种可能你的程序涉及到并行计算,但你只有一张卡,因此只要将程序涉及到并行计算的部分改成单卡即可 找找有没有 torch.nn.DataParallel() 第二种一部分数据或者模型在cpu上,另外一部分在gpu上。 PS:第二种和第一种可以强行 os.environ["CUDA_VISIBLE_DEVICES"]为指定ID 第三种CUDNN版本不对?感觉这种可能比较小 然后说一下我是怎么解决的: 最关键的,也是我遇到的问题,这个错误没有表明和显存溢出存在着联系,因为显存溢出
为了解决这个问题,你可以尝试以下操作: 1. 确保正确地分配和初始化设备内存。确保使用`cudaMalloc`或相关函数分配设备内存,并使用`cudaMemset`等函数将其初始化为零。 2. 检查你的代码,确保没有访问超出设备内存范围的位置。这可能需要检查你的索引计算或循环边界条件是否正确。 3. 检查你的设备内存读写操作,并确保它们是有效的。例如,确保读取操作使用`cudaMemcpy`等函数进行,写入操作使用`cudaMemcpyHostToDevice`或`cudaMemcpyDeviceToDevice`等函数进行。 4. 检查你的设备代码中的内存访问限制。有时候,如果你在设备上定义了某个数据结构,但在主机代码中尝试访问它,就会导致非法内存访问错误。 如果以上方法仍然无法解决问题,我建议你提供更多的代码和上下文信息,以便我能够更具体地帮助你。 报错解决:RuntimeError:The detected CUDA version mismatches the version that was used to compile PyTorch. 27463 报错解决:RuntimeError: Error compiling objects for extension和nvcc fatal: Unsupported gpu architecture 16217 报错解决:RuntimeError:The detected CUDA version mismatches the version that was used to compile PyTorch. AI Player: sudo ./cuda-uninstaller 报错解决:RuntimeError:The detected CUDA version mismatches the version that was used to compile PyTorch. AI Player: 试试修改软链接指向之前的cuda?