CUDA-GDB(12)——技巧与窍门
安全二次方(security²)博客目录导读
目录
12.1. 设置cuda break_on_launch
12.2. 设置 cuda 启动阻塞模式
12.3. 设置cuda通知
12.4. 设置cuda ptx缓存
12.5. 设置CUDA单步调试优化
12.6. 设置cuda线程选择
12.7. 设置CUDA值外推
12.8. 调试Docker容器
12.9. 切换至经典调试器后端
12.10. 线程块集群
12.11. 调试OptiX/RTCore应用程序
12.12. 在Windows子系统Linux上进行调试
12.13. 从主机线程访问非托管设备内存
本节作为高级设置和各种技巧的参考指南,供CUDA-GDB用户使用,这些内容在其他文档中未被记录。
12.1. 设置cuda break_on_launch
要在每个启动的内核的第一条指令处中断,请将break_on_launch选项设置为application:
(cuda-gdb) set cuda break_on_launch application
可能的选项包括:
none
无内核、应用程序或系统(默认)
application
由用户应用程序启动的内核
system
由驱动程序启动的任何内核,例如memset
all
任何内核、应用程序和系统
这些自动断点不会通过info breakpoints命令显示,并且与单独设置的断点分开管理。关闭该选项不会删除设置在同一地址的其他单独断点,反之亦然。
12.2. 设置 cuda 启动阻塞模式
启用后,内核启动将变为同步模式,就像环境变量CUDA_LAUNCH_BLOCKING被设置为1一样。一旦进入阻塞状态,内核启动实际上会被序列化,可能更易于调试。
-
(cuda-gdb) set cuda launch_blocking off
内核启动将根据应用程序的要求同步或异步执行。这是默认设置。
-
(cuda-gdb) set cuda launch_blocking on
内核启动将变为同步模式。如果应用程序已经启动,该更改只会在当前会话结束后生效。
12.3. 设置cuda通知
每当发生CUDA事件时,都需要通知调试器。通知通过向主机线程发送信号的形式进行。接收该特殊信号的主机线程由set cuda notify选项确定。
-
(cuda-gdb) set cuda notify youngest
线程ID最小的主机线程将接收通知信号(默认设置)。
-
(cuda-gdb) set cuda notify random
任意一个主机线程将收到通知信号。
12.4. 设置cuda ptx_cache
在访问变量值之前,调试器会检查该变量在当前程序计数器(PC)位置是否存活。在CUDA设备上,变量可能不会一直保持存活状态,并会被报告为"已优化移除"。
CUDA-GDB提供了一种绕过此限制的选项,通过缓存PTX寄存器级别的变量值。每个源变量会被编译成一个PTX寄存器,随后映射到一个或多个硬件寄存器。利用编译器发出的调试信息,调试器可以根据变量先前映射的最新硬件寄存器来缓存PTX寄存器的值。
此优化始终正确。启用后,缓存值将显示为从实际硬件寄存器读取的正常值,并带有(cached)前缀标识。该优化仅在单步执行代码时生效。
-
(cuda-gdb) set cuda ptx_cache off
调试器仅读取活动变量的值。
-
(cuda-gdb) set cuda ptx_cache on
调试器将尽可能使用缓存值。此设置为默认设置且始终安全。
12.5. 设置CUDA单步调试优化
单步调试可能会耗费大量时间。启用此选项后,调试器将使用安全技巧来加速单步执行。
-
(cuda-gdb) set cuda single_stepping_optimizations off
调试器将不会尝试加速单步执行。这是5.5版本及更早版本中唯一且默认的行为。
-
(cuda-gdb) set cuda single_stepping_optimizations on
调试器将使用安全技术来加速单步执行。这是从6.0版本开始的默认设置。
12.6. 设置cuda线程选择
当调试器需要选择一个活动线程进行聚焦时,该决策由启发式算法指导。set cuda thread_selection命令用于指导这些启发式规则。
-
(cuda-gdb) set cuda thread_selection logical
将选择具有最低blockIdx/threadIdx坐标的线程。
-
(cuda-gdb) set cuda thread_selection physical
将选择具有最低dev/sm/warp/lane坐标的线程。
12.7. 设置CUDA值外推
在访问变量值之前,调试器会检查该变量在当前程序计数器(PC)位置是否存活。在CUDA设备上,变量可能不会一直存活,会被报告为"优化移除"状态。
CUDA-GDB 提供了一种选项,可以在调试器将变量标记为"优化掉"时,通过推测变量的值来规避这一限制。这种推测并不保证准确性,必须谨慎使用。如果用于存储变量值的寄存器自上次变量被视为活跃以来已被重新使用,那么报告的值将是错误的。因此,使用该选项打印的任何值都将被标记为"(possibly)"。
-
(cuda-gdb) set cuda value_extrapolation off
调试器仅读取活动变量的值。此设置为默认设置,始终安全。
-
(cuda-gdb) set cuda value_extrapolation on
调试器将尝试推断变量超出其各自生命周期范围的值。此设置可能会报告错误的值。
12.8. 调试Docker容器
在Docker容器内调试应用程序时,需要启用PTRACE功能。用户还需确保根文件系统已设置读写权限。
要启用PTRACE功能,请将以下内容添加到您的Docker运行命令中:
--cap-add=SYS_PTRACE
12.9. 切换至经典调试器后端
随着CTK 11.8版本的发布,Linux平台引入了一个名为统一调试器(UD)的新调试后端。UD实现了与cuda-gdb和NVIDIA® Nsight™ VSE等调试工具共享的统一调试后端。UD支持包括Windows和Linux在内的多平台。终端用户使用UD的体验与现有工具完全兼容。
之前的调试器后端,称为经典调试器后端,仍然可以通过在启动CUDA-GDB之前将环境变量CUDBG_USE_LEGACY_DEBUGGER设置为1来使用。
Maxwell GPU不支持UD。用户必须切换至经典调试器后端才能在Maxwell GPU上调试应用程序。
12.10. 线程块集群
使用线程块集群的CUDA应用程序将在CUDA焦点中显示集群索引。通过打印便捷变量clusterIdx和clusterDim可以查询集群索引和集群维度。
12.11. 调试OptiX/RTCore应用程序
在使用OptiX/RTCore构建的程序进行调试时,可能需要将环境变量OPTIX_FORCE_DEPRECATED_LAUNCHER设置为1。如果无法命中断点,请尝试在启动应用程序之前设置此环境变量。
12.12. 在Windows子系统Linux上进行调试
如果您无法在Windows Subsystem for Linux上使用调试器,请确保通过将注册表键>HKEY_LOCAL_MACHINE\SOFTWARE\NVIDIA Corporation\GPUDebugger\EnableInterface设置为(DWORD) 1来启用调试接口
12.13. 从主机线程访问非托管设备内存
当访问通过CUDA内存分配API创建的非托管设备内存时,需要特别注意以下几点:
CUdeviceptr d_global; cuMemAlloc(&d_global, sizeof(uint32_t));uint32_t h_global_32 = 0x1234; cuMemcpyHtoD(d_global, &h_global, sizeof(uint32_t));
当在主机线程上直接检查d_global的内容时,我们会观察到不正确的值:
(cuda-gdb) print /x *d_global $1 = 0x0
用户需要显式类型转换为正确的地址空间标识符,以检查设备上的非托管内存:
(cuda-gdb) print *(@global unsigned long long *)d_global $2 = 0x1234
当聚焦于CUDA线程时,显式类型转换是不必要的。
