返回资讯中心
外部精选
架构
#平台工程#DevInfra

LLDB 新增厂商中立加速器插件架构,支持跨 CPU 与 GPU 调试

来源标题:Extending LLDB to Debug Applications That Span CPUs and GPUs

LLDB 团队为 lldb-server 构建了厂商中立的加速器插件架构,用于调试跨 CPU 和 GPU 的应用。该设计将共享调试基础设施与硬件特定设备控制分离,并把 CPU 和 GPU 表示为独立调试进程、呈现在同一调试会话中。此前 GPU 厂商各自维护专用调试器,如 AMD 的 ROCgdb 和 NVIDIA 的 CUDA-GDB。

Meta Engineering2026/11/9 · 今天24 分钟阅读

以下正文由 AI 翻译自 Meta Engineering(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

  • 我们在 lldb-server 中构建了一套厂商中立的加速器插件架构,用于调试同时跨越 CPU 和 GPU 的应用程序。它将共享的调试器基础设施与硬件特定的设备控制分离。
  • 该设计将 CPU 和 GPU 表示为独立的调试器进程,同时在同一个调试会话中呈现它们。

现代 AI 应用很少只在一个地方执行。一个工作负载可能从高层框架开始,然后在原生 CPU 代码和运行在 GPU 上的 kernel 之间来回切换。当 bug 跨越这些边界时,开发者需要同时理解主机应用和设备。

这比把传统调试器附加到另一个进程要困难得多。CPU 和 GPU 可能使用不同的指令集、寄存器、内存空间和执行模型。GPU 还是通过主机进程内的运行时和驱动来控制的,因此调试设备往往需要与 CPU 仔细协调。

过去,GPU 厂商构建了设备特定的调试器,包括 AMD 的 ROCgdb 和 NVIDIA 的 CUDA-GDB。这些工具为各自的平台提供了深度支持,但通用的调试器能力往往需要分别实现和维护。

在 Meta,我们一直在为 LLDB 开发一种不同的方法:在 lldb-server 中提供一套通用的加速器插件架构。在本文中,“GPU”指的是具体的设备和示例,而“加速器”指的是 LLDB 更广泛、厂商中立的插件抽象。该架构在 Meta 工程师以及整个加速器生态的贡献下不断演进。它让共享的调试器独立于任何一款 GPU,同时为硬件厂商提供一个专注于实现设备特定行为的地方。

为什么 GPU 调试挑战传统调试器模型

传统调试器通常假设一个进程只有一种架构,并且对线程、寄存器和内存有一致的视图。GPU 程序挑战了上述每一个假设。

主机进程可能运行在 x86-64 上,而它的 kernel 使用完全不同的指令集。CPU 线程有熟悉的寄存器上下文,而 GPU 可能以锁步方式执行成组的 lane。主机指针和设备指针可能指向不同的地址空间。GPU 可能暴露数千个执行 lane,这些 lane 无法干净地映射到大多数命令行和图形调试器所呈现的线程模型上。

将所有这些状态合并到一个人为的进程模型中,会让调试器更加复杂。每个操作都必须先判断它适用于 CPU 还是 GPU。寄存器处理、内存读取、断点、单步执行和停止事件都变得依赖于所选硬件。单一进程模型还会迫使 CPU 和 GPU 进入一个统一的内存映射,尽管它们的地址空间可能是独立的:同一个地址(例如 0x1000)在 CPU 进程和 GPU 进程中可能指向不同的位置。

LLDB 加速器架构没有隐藏这些差异,而是为它们划出了清晰的边界。

lldb-server 中对 GPU 调试的插件支持

LLDB 使用一个名为 lldb-server 的伴随进程来启动或附加到程序,并执行底层调试操作。LLDB 客户端通过 GDB remote protocol 与服务器通信,这是一种用于读取内存、检查寄存器、控制执行和设置断点等操作的命令协议。

由于 lldb-server 已经控制了原生进程,它也是与加速器运行时协调的合适位置。新的插件接口让硬件特定的后端可以与正常的 CPU 调试器协同工作。后端将厂商的设备调试 API 转换为 LLDB 已经理解的概念,例如进程、线程、寄存器、内存、模块和停止原因。

这种分离使 LLDB 客户端保持厂商中立。对命令行、远程协议、符号处理和 IDE 集成的通用改进可以让每个加速器受益。与此同时,每个厂商仍然负责其硬件和驱动栈独有的细节。

GPU 调试支持仅在调试的应用程序使用受支持的 GPU 运行时时才启用。对于仅使用 CPU 的应用程序,LLDB 和 lldb-server 继续走现有的原生调试路径,不会产生运行时计算开销。

两个目标,一种调试体验

该架构将 CPU 和加速器表示为独立的 LLDB 目标。

每个目标都有自己的架构,并关联一个调试器进程,由该进程维护其线程、寄存器、地址空间和执行状态。CPU 继续使用 LLDB 既有的原生调试路径。当加速器可用时,插件提供第二个连接,LLDB 用它来创建设备目标。

对调试器而言,这两个目标在技术上是独立的。对开发者而言,它们可以出现在同一个 LLDB 或 IDE 会话中。这避免了将不兼容的 CPU 和 GPU 概念强行塞进单一进程,同时仍然支持统一的工作流。

CPU 和 GPU 保持为独立的 LLDB 目标,同时 lldb-server 中的插件协调主机和设备调试。

协调主机与设备

典型的调试会话遵循一小组步骤:

  • LLDB 连接到 lldb-server,并发现哪些加速器插件可用。
  • 插件可以请求 LLDB 在主机进程中设置内部断点。这些断点标识重要的运行时事件,例如 GPU 调试会话可以开始的时刻。
  • 当主机到达这些点之一时,lldb-server 通知插件。插件初始化厂商调试 API,并准备一个加速器调试端点。
  • LLDB 为加速器创建第二个目标并连接到它。此后,设备线程、寄存器、内存、模块和断点都可以使用 LLDB 现有的抽象。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →