由于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]
运行如下命令: