CUDA-GDB(3)——快速入门 - 详解

安全二次方(security²)博客目录导读

目录

3.1. 设置调试器环境

3.1.1. 临时目录

3.1.2. 在Jetson和Drive Tegra设备上使用CUDA-GDB调试器

3.2. 编译应用程序

3.2.1. 调试编译

3.2.2. 带行号信息的编译

3.2.3. 使用PTX调试选项进行编译

3.2.4. 为特定GPU架构编译

3.3. 使用调试器

3.3.1. 在桌面管理器运行时进行单GPU调试

3.3.2. 多GPU调试

3.3.3. 远程调试

3.3.4. 多调试器

3.3.5. 附加/分离Attaching/Detaching


CUDA工具包可以按照Quick Start Guide中的说明进行安装。

需要采取进一步步骤来设置调试器环境、构建应用程序并运行调试器。

3.1. 设置调试器环境

3.1.1. 临时目录

默认情况下,CUDA-GDB使用/tmp作为存储临时文件的目录。要选择其他目录,请设置$TMPDIR环境变量。

【注意】:

用户必须对CUDA-GDB使用的临时目录具有写入和执行权限。否则,调试器将因内部错误而失败。

【注意】:

$TMPDIR的值在应用程序环境和CUDA-GDB中必须保持一致。如果不匹配,CUDA-GDB将无法attach到应用程序进程上。

【注意】:

由于Android设备上不存在/tmp目录,在启动cuda-gdb前必须设置$TMPDIR环境变量并指向用户可写入的文件夹。

3.1.2. 在Jetson和Drive Tegra设备上使用CUDA-GDB调试器

默认情况下,在Jetson和Drive Tegra设备上,仅当cuda-gdbcuda-gdbserver由属于debug组成员的用户启动时,才支持GPU调试。

要将当前用户添加到debug组,请运行以下命令:

sudo usermod -a -G debug $USER

3.2. 编译应用程序

3.2.1. 调试编译

NVCC,即NVIDIA CUDA编译器驱动程序,提供了一种生成CUDA-GDB正常工作所需的调试信息的机制。为了便于使用CUDA-GDB进行调试,在编译应用程序时必须向NVCC传递-g -G选项对;例如,

nvcc -g -G foo.cu -o foo

使用此行编译CUDA应用程序 foo.cu

  • 强制使用-O0编译选项,仅保留极其有限的dead-code消除和寄存器溢出优化。

  • 使编译器在可执行文件中包含调试信息

【注意】:

启用-G选项会增加二进制文件大小,因为它包含调试信息,并且由于缺少编译器优化而降低性能。

为了编译您的CUDA Fortran代码并包含CUDA-GDB正常工作所需的调试信息,必须使用PGI CUDA Fortran编译器pgfortran,并加上-g选项。此外,为了便于调试和与未来GPU架构的前向兼容性,建议使用-Mcuda=nordc选项编译代码;例如,

pgfortran -g -Mcuda=nordc foo.cuf -o foo

有关可用编译标志的更多信息,请参阅PGI编译器文档。

3.2.2. 带行号信息的编译

对cuda-gdb调试使用-lineinfo编译但未使用-G编译的程序的支持进行了多项改进。这主要针对使用OptiX/RTCore构建的程序调试。

请注意,在尝试调试优化代码时可以使用-lineinfo。在这种情况下,调试器的单步执行和断点行为可能会显得有些不稳定。

  • 单步执行时,PC指针可能会意外地向前或向后跳转。

  • 用户可能会进入没有行号信息的代码,导致无法确定PC处的代码属于哪个源文件/行号。

  • 断点可能会在不同于最初设置的行上中断。

在调试OptiX/RTCore代码时,需要注意以下几点:

  • 用户无法调试或检查NVIDIA内部代码。

  • OptiX/RTCode 调试仅限于 -lineinfo,不支持使用完整调试信息 (-G) 构建此代码。

  • OptiX/RTCode代码经过高度优化,因此上述关于调试优化代码的注意事项同样适用。

3.2.3. 使用PTX调试选项进行编译

使用-Xptxas nvcc选项时,--make-errors-visible-at-exit可用于错误检测。

--make-errors-visible-at-exit                                          (-make-errors-visible-at-exit)
     Generate required instructions at exit point to make memory faults and errors visible at exit.

【注意】:

该标志生成的额外指令可能会降低应用程序性能。

3.2.4. 为特定GPU架构编译

默认情况下,编译器只会为compute_52 PTX和sm_52 cubins生成代码。对于更新的GPU,内核会在运行时根据目标GPU的架构从PTX重新编译。针对特定虚拟架构进行编译可以确保应用程序在性能权衡的前提下,能够兼容该架构之后的所有GPU架构。这样做是为了实现向前兼容。

强烈建议一次性为应用程序所针对的GPU架构编译应用程序,并为最新的虚拟架构生成PTX代码以确保向前兼容性。

GPU架构由其计算能力定义。有关GPU列表及其各自的计算能力,请参阅https://developer.nvidia.com/cuda-gpus。同一个应用程序可以为多个GPU架构进行编译。使用-gencode编译选项来指定要编译的GPU架构。该选项可以多次指定。

例如,要为计算能力7.0的GPU编译应用程序,请在编译命令中添加以下标志:

-gencode arch=compute_70,code=sm_70

要为未来任何计算能力超过7.0的架构编译PTX代码,请在编译命令中添加以下标志:

-gencode arch=compute_70,code=compute_70

有关其他信息,请参阅编译器文档https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#extended-notation

3.3. 使用调试器

CUDA-GDB可在以下系统配置中使用:

3.3.1. 在桌面管理器运行时进行单GPU调试

对于计算能力6.0及以上的设备,CUDA-GDB可用于在运行桌面图形界面的同一GPU上调试CUDA应用程序。

此外,对于计算能力低于6.0的设备,可以使用软件抢占功能在同一块运行桌面图形界面的GPU上调试CUDA应用程序。启用此功能有两种方法:

【注意】:

这是Linux上的一个BETA功能,仅支持Maxwell架构。对于计算能力为SM6.0及以上的GPU,下面列出的选项将被忽略。

  • 使用以下命令:

    set cuda software_preemption on
  • export以下环境变量:

    CUDA_DEBUGGER_SOFTWARE_PREEMPTION=1

以上任一选项都将激活软件抢占功能。这些选项必须在运行应用程序之前设置。当GPU遇到断点或任何通常会导致GPU冻结的事件时,CUDA-GDB会释放GPU供桌面或其他应用程序使用。这使得CUDA-GDB能够在运行桌面GUI的同一GPU上调试CUDA应用程序,并支持在同一GPU上进行多CUDA应用程序的上下文切换调试。

3.3.2. 多GPU调试

多GPU调试指的是应用程序在多个支持CUDA的设备上运行的场景。多GPU调试与单GPU调试差别不大,只是多了一些额外的CUDA-GDB命令,允许你在不同GPU之间切换。

任何GPU遇到断点都会暂停该系统上所有运行CUDA的GPU。暂停后,您可以使用info cuda kernels查看所有活跃的内核及其运行的GPU。当任一GPU恢复运行时,所有GPU都将恢复运行。

【注意】:

如果使用了CUDA_VISIBLE_DEVICES,则只会暂停和恢复指定的设备。

所有支持CUDA的GPU可以运行一个或多个内核。要切换到活动内核,请使用cuda kernel <n>,其中n是从info cuda kernels获取的内核ID。

【注意】:

同一个内核可以同时被不同的上下文和设备加载使用。当通过名称或文件名加行号的方式在此类内核中设置断点时,该断点将随机解析到该内核的某一个实例上。使用运行时API时,无法控制断点具体解析到哪个实例。而使用驱动API时,用户可以通过在模块加载后立即设置断点来控制断点解析到哪个实例。

3.3.3. 远程调试

有多种方法可以使用CUDA-GDB远程调试应用程序。除了通过主机系统使用SSH或VNC连接到目标系统外,还可以使用target remote GDB功能。使用此选项时,本地的cuda-gdb(客户端)将连接到在目标系统上运行的cuda-gdbserver进程(服务器)。此选项支持Linux客户端与Linux或QNX服务器之间的连接。

按照这种方式设置远程调试需要两个步骤:

在远程主机上启动cuda-gdbserver

cuda-gdbserver可以在远程主机上以不同的操作模式启动。

  • 选项1:以调试模式启动新应用程序。

    要以调试模式启动新应用程序,请按以下方式调用cuda-gdb服务器:

    $ cuda-gdbserver :1234 app_invocation

    其中1234cuda-gdbserver将监听的TCP端口号,用于接收来自cuda-gdb的传入连接,而app-invocation是启动应用程序的调用命令(包含参数)。

  • 选项2:将cuda-gdbserver附加到正在运行的进程

    要将cuda-gdbserver附加到已运行的进程,必须使用--attach选项后跟进程标识号(PID):

    $ cuda-gdbserver :1234 --attach 5678

    其中1234是TCP端口号,5678是cuda-gdbserver需要附加到的应用程序进程标识符。

【注意】:

在QNX平台上不支持附加到已运行的进程。

在客户端上启动cuda-gdb

配置cuda-gdb以使用以下任一方式连接到远程目标:

(cuda-gdb) target remote

(cuda-gdb) target extended-remote

【注意】:

QNX平台需要将QNX_TARGET环境变量设置为目标根文件系统的位置。如果在运行cuda-gdb的客户端上不可用,请将其设置为空字符串。

如果调试目标上安装的库可能与调试主机上安装的库不同,建议使用set sysroot命令。例如,可以按以下方式配置cuda-gdb以连接到远程目标:

(cuda-gdb) set sysroot remote://
(cuda-gdb) target remote 192.168.0.2:1234

其中192.168.0.2是远程目标的IP地址或域名,1234是之前由cuda-gdbserver打开的TCP端口。

3.3.4. 多调试器

对于计算能力6.0及以上的设备,可以同时进行多个调试会话。

对于计算能力低于6.0的设备,只要CUDA设备被独占使用,就可以同时进行多个调试会话。例如,一个CUDA-GDB实例可以调试使用第一个GPU的第一个应用程序,而另一个CUDA-GDB实例可以调试使用第二个GPU的第二个应用程序。通过使用CUDA_VISIBLE_DEVICES环境变量指定应用程序可见的GPU,可以实现对GPU的独占使用。

$ CUDA_VISIBLE_DEVICES=1 cuda-gdb my_app

此外,对于计算能力低于6.0的设备,在启用软件抢占功能的情况下(set cuda software_preemption on),可以使用多个CUDA-GDB实例来调试在同一GPU上进行上下文切换的CUDA应用程序。

3.3.5. 附加/分离Attaching/Detaching

CUDA-GDB 可以使用 GDB 内置的进程附加/分离命令,对运行在计算能力 2.0 及以上 GPU 上的 CUDA 应用程序进行附加和分离操作。

此外,如果在运行CUDA应用程序之前将环境变量CUDA_DEVICE_WAITS_ON_EXCEPTION设置为1,应用程序将正常运行直到发生设备异常。随后应用程序将等待CUDA-GDB附加到它进行进一步调试。此功能在WSL上不受支持。

【注意】:

在某些Linux发行版上,默认情况下由于安全设置,调试器无法附加到已运行的进程。要启用CUDA调试器的附加功能,可以以root身份启动cuda-gdb,或者使用以下命令将/proc/sys/kernel/yama/ptrace_scope设置为零:

$ sudo sh -c "echo 0 >/proc/sys/kernel/yama/ptrace_scope"

要使更改永久生效,请编辑 /etc/sysctl.d/10-ptrace.conf

posted @ 2026-02-10 10:16  gccbuaa  阅读(137)  评论(0)    收藏  举报