跳到正文
RadarAI· Meta Engineering Blog(RSS)·· 3 小时前AI 评分36

Meta 扩展 LLDB:用加速器插件架构同时调试 CPU 与 GPU 应用

AI 导读

Meta 在 lldb-server 中构建了厂商中立的加速器插件架构,将 CPU 与 GPU 表示为两个独立 LLDB target,并在同一调试会话中呈现。该设计让共享调试器基础设施与硬件专属设备控制分离,硬件厂商只需实现设备相关行为;仅当应用使用受支持的 GPU runtime 时才启用 GPU 调试,纯 CPU 应用仍走原有原生调试路径,不产生额外运行时开销。

正文 · AI 翻译

Meta 工程博客·2026-11-10 01:00· 2 小时前AI 评分48

扩展 LLDB 以调试跨 CPU 和 GPU 的应用程序

AI 导读

Meta 在 lldb-server 中构建了厂商中立的加速器插件架构,把 CPU 与 GPU 表示为两个独立 LLDB target,却在同一调试会话中呈现。

正文 · 原文

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

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

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

历史上,GPU 厂商构建了特定于设备的调试器,包括 AMD 的 ROCgdb 和 NVIDIA 的 CUDA-GDB。这些工具为其各自的平台提供了深度支持,但常见的调试器功能往往需要单独实现和维护。

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

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

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

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

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

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

面向 GPU 调试的 lldb-server 插件支持

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

由于 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 中的插件协调主机和设备调试。

协调主机与设备

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

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

结构化操作协调双方。插件可以请求 CPU 断点、提供连接信息、报告设备模块,并同步主机与设备的执行。通用协议描述了调试器需要做什么,而无需向 LLDB 客户端暴露厂商特定的 API 细节。

我们还构建了一个模拟加速器插件,无需专用硬件即可演练此流程。它让 LLVM 测试套件能够验证发现、断点协调、连接创建和基本设备状态。这对于开发可独立于任何特定 GPU 进行审查和测试的共享基础设施非常重要。

典型的 GPU 工作流程

向量点积 HIP 示例产生了以下精简会话:

(lldb) target list
Current targets:
  target #0: gpu_demo (x86_64, stopped)
* target #1: amd_memory_kernel[...] (amdgcn, stopped)

(lldb) b compute_element
Breakpoint 1: no locations (pending).
(lldb) c
(lldb) target select 0
(lldb) c
Launching kernel: 2 blocks x 32 threads
1 location added to breakpoint 1
Target 1 stopped.

(lldb) target select 1
(lldb) bt
* frame #0: compute_element(..., idx=32) at gpu_demo.hip:26
  frame #1: vector_dot_kernel(..., n=64) at gpu_demo.hip:35
当 GPU 模块加载时,挂起的断点被解析,回溯
来自 GPU 目标。

跨硬件厂商的通用插件框架

插件边界有意基于调试器操作而非特定 GPU 平台的概念。这使得它适用于指令集、运行时 API 和执行模型差异很大的各种设备。

该框架支持事后 GPU 调试以及实时会话。GPU 核心转储插件使用通用基类进行 LLDB 集成,而厂商实现则提供设备特定的线程、寄存器、内存和模块状态。

Meta 的 GPU 调试工作已经在利用这一架构。由于我们运营着具有不同硬件和软件栈的异构 GPU 集群,这些工作使用同一模型这一事实是对设计的重要验证:通用 LLDB 层可以保持稳定,同时每个后端准确表示自己的设备。

在撰写本文时,我们已将大部分通用框架上游到 LLVM。这包括 lldb-server 插件接口;用于插件发现、初始化、运行时事件协调和 GPU 连接创建的 GDB-remote 数据包;支持关联 CPU 和 GPU 调试器进程同时保持其独立架构;支持多个地址空间,以及硬件无关的模拟测试。我们预计很快会上游剩余部分。

展望未来

接下来,我们计划完成剩余通用基础设施的上游工作,并扩展建立在其上的厂商集成。我们的目标是,将新硬件与 LLDB 集成应只需一个厂商特定插件,而无需构建和维护单独的调试器。 

致谢 

我们感谢 Meta 开发者基础设施领导团队,特别是 Shane Nay、Todd Fiala 和 Ale Contenti,他们的直接支持使这项工作成为可能。

我们还感谢调试与工具团队的同事 Jacob Lalonde、David Young、Alexandre Perez、Zhiyuan Li、Piyush Jaiswal 和 Philip DePetro 的合作与支持。

最后,我们感谢开源社区,特别是 Jonas Devlieghere、Jim Ingham、David Spickett 和 Jason Molenda,感谢他们审查 RFC 和上游拉取请求。

文章 扩展 LLDB 以调试跨 CPU 和 GPU 的应用程序 首次发表于 Engineering at Meta。

来源:Meta Engineering Blog · engineering.fb.com

来源:RadarAI · aihot.news