Enhance GPU and NPU kernel driver documentation and monitoring scripts

- Updated README.zh.md for GPU kernel driver to improve clarity and formatting.
- Added nvidia_driver.bt script for monitoring NVIDIA proprietary GPU driver activity using kernel probes.
- Revised README.md for NPU kernel driver to enhance explanations and correct minor grammatical issues.
This commit is contained in:
yunwei37
2025-10-13 07:18:48 -07:00
parent d4ec997ab2
commit b8cc834d7f
4 changed files with 668 additions and 42 deletions

View File

@@ -10,7 +10,7 @@ GPU 跟踪点是内核直接渲染管理器(DRM)子系统中内置的仪器
关键洞察:内核跟踪点仅在事件发生时激活,每个事件添加纳秒级开销。它们捕获 100% 的活动,包括微秒级持续时间的作业。基于轮询的监控每 100ms 检查一次 GPU 状态,完全错过短期操作。
GPU 跟踪点跨越三层。**DRM 调度器跟踪点**(`gpu_scheduler` 事件组)是稳定的 uAPI - 格式永不改变。它们在 Intel、AMD 和 Nouveau 驱动上工作完全相同,适合供应商中立的监控。**供应商特定跟踪点**暴露驱动内部 - Intel i915 跟踪 GEM 对象创建和 VMA 绑定,AMD AMDGPU 监控缓冲对象和命令提交。**通用 DRM 跟踪点**通过 vblank 事件处理显示同步,用于诊断丢帧。
GPU 跟踪点跨越三层。DRM 调度器跟踪点(`gpu_scheduler` 事件组)是稳定的 uAPI,格式永不改变。它们在 Intel、AMD 和 Nouveau 驱动上工作完全相同,适合供应商中立的监控。供应商特定跟踪点暴露驱动内部。Intel i915 跟踪 GEM 对象创建和 VMA 绑定,而 AMD AMDGPU 监控缓冲对象和命令提交。通用 DRM 跟踪点通过 vblank 事件处理显示同步,用于诊断丢帧。
## DRM 调度器监视器:通用 GPU 跟踪
@@ -123,29 +123,29 @@ END
## Intel i915 跟踪点:内存管理深入分析
Intel 的 i915 驱动暴露了内存操作的详细跟踪点。这些需要内核配置中的 `CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS=y` - 使用 `grep CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS /boot/config-$(uname -r)` 检查。
Intel 的 i915 驱动暴露了内存操作的详细跟踪点。这些需要内核配置中的 `CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS=y`,使用 `grep CONFIG_DRM_I915_LOW_LEVEL_TRACEPOINTS /boot/config-$(uname -r)` 检查。
**i915_gem_object_create** 在驱动分配 GEM(图形执行管理器)对象时触发 - GPU 可访问内存的基本单位。格式:`obj=0xffff888... size=0x100000` 表示分配 1MB 对象。随时间跟踪总分配内存以检测泄漏。性能下降前的突然分配峰值表示内存压力。将对象指针与后续绑定/故障事件关联以了解对象生命周期。
i915_gem_object_create 在驱动分配 GEM(图形执行管理器)对象时触发,这是 GPU 可访问内存的基本单位。格式:`obj=0xffff888... size=0x100000` 表示分配 1MB 对象。随时间跟踪总分配内存以检测泄漏。性能下降前的突然分配峰值表示内存压力。将对象指针与后续绑定/故障事件关联以了解对象生命周期。
**i915_vma_bind** 跟踪将内存映射到 GPU 地址空间。分配内存还不够 - 它必须绑定到 GPU 虚拟地址空间。格式:`obj=0xffff888... offset=0x0000100000 size=0x10000 mappable vm=0xffff888...` 显示在 GPU 虚拟地址 0x100000 处绑定的 64KB。频繁的重新绑定表示内存抖动 - 驱动在压力下驱逐和重新绑定对象。GPU 页面故障通常与绑定操作相关。
i915_vma_bind 跟踪将内存映射到 GPU 地址空间。分配内存还不够,它必须绑定到 GPU 虚拟地址空间。格式:`obj=0xffff888... offset=0x0000100000 size=0x10000 mappable vm=0xffff888...` 显示在 GPU 虚拟地址 0x100000 处绑定的 64KB。频繁的重新绑定表示内存抖动,即驱动在压力下驱逐和重新绑定对象。GPU 页面故障通常与绑定操作相关。
**i915_gem_shrink** 捕获内存压力响应。在内存压力下,驱动回收 GPU 内存。格式:`dev=0 target=0x1000000 flags=0x3` 意味着驱动尝试回收 16MB。高收缩活动表示工作负载的 GPU 内存过小。与性能下降关联 - 如果在帧渲染期间发生收缩,会导致卡顿。
i915_gem_shrink 捕获内存压力响应。在内存压力下,驱动回收 GPU 内存。格式:`dev=0 target=0x1000000 flags=0x3` 意味着驱动尝试回收 16MB。高收缩活动表示工作负载的 GPU 内存过小。与性能下降关联,如果在帧渲染期间发生收缩,会导致卡顿。
**i915_gem_object_fault** 跟踪 CPU 或 GPU 访问未映射内存时的页面故障。格式:`obj=0xffff888... GTT index=128 writable` 表示图形转换表页 128 上的写故障。故障代价昂贵 - 它们在内核解决缺失映射时停止执行。写故障比读故障更昂贵(需要使缓存失效)。GTT 故障表示作业提交前资源绑定不完整。
i915_gem_object_fault 跟踪 CPU 或 GPU 访问未映射内存时的页面故障。格式:`obj=0xffff888... GTT index=128 writable` 表示图形转换表页 128 上的写故障。故障代价昂贵,因为它们在内核解决缺失映射时停止执行。写故障比读故障更昂贵,因为需要使缓存失效。GTT 故障表示作业提交前资源绑定不完整。
## AMD AMDGPU 跟踪点:命令提交管道
AMD 的 AMDGPU 驱动提供命令提交和硬件中断的全面跟踪。
**amdgpu_cs_ioctl** 捕获用户空间命令提交。当应用通过 ioctl 提交 GPU 工作时,此跟踪点触发。格式:`sched_job=12345 timeline=gfx context=1000 seqno=567 ring_name=gfx_0.0.0 num_ibs=2` 显示提交到图形环的作业 12345 有 2 个间接缓冲区。这标志着用户空间将工作交给内核的时间。记录时间戳以在与 `amdgpu_sched_run_job` 结合时测量提交到执行的延迟。高频率表示小批次 - 更好批处理的潜力。
amdgpu_cs_ioctl 捕获用户空间命令提交。当应用通过 ioctl 提交 GPU 工作时,此跟踪点触发。格式:`sched_job=12345 timeline=gfx context=1000 seqno=567 ring_name=gfx_0.0.0 num_ibs=2` 显示提交到图形环的作业 12345 有 2 个间接缓冲区。这标志着用户空间将工作交给内核的时间。记录时间戳以在与 `amdgpu_sched_run_job` 结合时测量提交到执行的延迟。高频率表示小批次和更好批处理的潜力。
**amdgpu_sched_run_job** 在内核调度器开始执行先前提交的作业时触发。将时间戳与 `amdgpu_cs_ioctl` 比较可揭示提交延迟。超过 100μs 的提交延迟表示内核调度延迟。每个环的延迟显示特定引擎是否受调度限制。
amdgpu_sched_run_job 在内核调度器开始执行先前提交的作业时触发。将时间戳与 `amdgpu_cs_ioctl` 比较可揭示提交延迟。超过 100μs 的提交延迟表示内核调度延迟。每个环的延迟显示特定引擎是否受调度限制。
**amdgpu_bo_create** 跟踪缓冲对象分配 - AMD 的 i915 GEM 对象等价物。格式:`bo=0xffff888... pages=256 type=2 preferred=4 allowed=7 visible=1` 分配 1MB(256 页)。类型表示 VRAM 与 GTT(GPU 可访问的系统内存)。首选/允许域显示放置策略。类型不匹配(请求 VRAM 但回退到 GTT)表示 VRAM 耗尽。可见标志表示 CPU 可访问的内存 - 昂贵,谨慎使用。
amdgpu_bo_create 跟踪缓冲对象分配,这是 AMD 的 i915 GEM 对象等价物。格式:`bo=0xffff888... pages=256 type=2 preferred=4 allowed=7 visible=1` 分配 1MB(256 页)。类型表示 VRAM 与 GTT(GPU 可访问的系统内存)。首选/允许域显示放置策略。请求 VRAM 但使用 GTT 的类型不匹配表示 VRAM 耗尽。可见标志表示 CPU 可访问的内存,这很昂贵,应谨慎使用。
**amdgpu_bo_move** 在缓冲对象在 VRAM 和 GTT 之间迁移时触发。迁移代价昂贵(需要通过 PCIe 复制数据)。过度的移动表示内存抖动 - 工作集超过 VRAM 容量。测量移动频率和大小以量化 PCIe 带宽消耗。与性能下降关联 - 迁移停止 GPU 执行。
amdgpu_bo_move 在缓冲对象在 VRAM 和 GTT 之间迁移时触发。迁移代价昂贵,因为需要通过 PCIe 复制数据。过度的移动表示内存抖动,即工作集超过 VRAM 容量。测量移动频率和大小以量化 PCIe 带宽消耗。与性能下降关联,因为迁移会停止 GPU 执行。
**amdgpu_iv** 捕获 GPU 中断。GPU 为完成的工作、错误和事件发出中断信号。格式:`ih:0 client_id:1 src_id:42 ring:0 vmid:5 timestamp:1234567890 pasid:100 src_data: 00000001...` 捕获中断详细信息。源 ID 表示中断类型(完成、故障、热)。高中断率影响 CPU 性能。VMID 和 PASID 识别哪个进程/VM 触发了中断 - 对于多租户调试至关重要。
amdgpu_iv 捕获 GPU 中断。GPU 为完成的工作、错误和事件发出中断信号。格式:`ih:0 client_id:1 src_id:42 ring:0 vmid:5 timestamp:1234567890 pasid:100 src_data: 00000001...` 捕获中断详细信息。源 ID 表示中断类型(完成、故障、热)。高中断率影响 CPU 性能。VMID 和 PASID 识别哪个进程/VM 触发了中断,这对于多租户调试至关重要。
## DRM Vblank 跟踪点:显示同步
@@ -155,13 +155,111 @@ Vblank(垂直消隐)事件将渲染与显示刷新同步。错过 vblank 会
**drm_vblank_event_queued** 和 **drm_vblank_event_delivered** 跟踪 vblank 事件传递到用户空间。排队延迟(队列到传递)测量内核调度延迟。总延迟(vblank 到传递)包括内核和驱动处理。超过 1ms 的延迟表示合成器问题。与用户可见的丢帧关联 - 延迟传递的事件意味着错过的帧。
## 运行监控脚本
## NVIDIA 专有驱动:不同的架构
导航到脚本目录并运行 DRM 调度器监视器。它在所有 GPU 上工作:
与使用内核直接渲染管理器(DRM)子系统的 Intel、AMD 和 Nouveau 不同,**NVIDIA 的专有驱动(nvidia.ko)在 DRM 之外运行**。它实现了自己的内核模块接口,带有供应商特定的函数和单个跟踪点。这种架构差异意味着 NVIDIA GPU 需要不同的监控方法 - 我们附加到 nvidia.ko 函数的内核探针,而不是 DRM 跟踪点。
关键区别:DRM 驱动暴露标准化的 `gpu_scheduler` 跟踪点,在供应商之间工作完全相同。NVIDIA 的闭源驱动只提供一个跟踪点(`nvidia:nvidia_dev_xid` 用于硬件错误),需要监控内部内核函数如 `nvidia_open`、`nvidia_unlocked_ioctl` 和 `nvidia_isr`。这使得 NVIDIA 监控更脆弱 - 函数名称可能在驱动版本之间改变 - 但仍然提供有价值的 GPU 活动洞察。
### NVIDIA 驱动监控:nvidia_driver.bt
`nvidia_driver.bt` 脚本通过对专有驱动的内核探针跟踪 NVIDIA GPU 操作。与供应商中立的 DRM 调度器监控不同,此脚本是 NVIDIA 特定的,需要加载专有 nvidia.ko 模块。完整源代码可在 `scripts/nvidia_driver.bt` 中找到。
**关键脚本特性:**
脚本附加 18 个内核探针以监控:
- **设备操作**:open、close、ioctl(采样 1% 以降低开销)
- **内存管理**:mmap、页故障、VMA 操作
- **中断处理**:ISR、MSI-X、下半部处理程序及延迟直方图
- **P2P 通信**:GPU 到 GPU 的页面请求和 DMA 映射
- **电源管理**:挂起/恢复周期及持续时间跟踪
- **错误报告**:通过 `nvidia:nvidia_dev_xid` 跟踪点报告 Xid 硬件/驱动错误
**运行 NVIDIA 驱动监视器**
验证 NVIDIA 驱动已加载并检查可用探针:
```bash
cd bpf-developer-tutorial/src/xpu/gpu-kernel-driver/scripts
sudo bpftrace drm_scheduler.bt
# 检查 NVIDIA 驱动模块
lsmod | grep nvidia
# 列出可用的 NVIDIA 探针
sudo bpftrace -l 'kprobe:nvidia_*' | head -20
sudo bpftrace -l 'tracepoint:nvidia:*'
```
在 GPU 工作负载期间运行监视器:
```bash
cd bpf-developer-tutorial/src/xpu/gpu-kernel-driver
sudo bpftrace scripts/nvidia_driver.bt
```
**真实执行输出**(捕获 llama-server(LLM 推理)、nvtop(GPU 监控)和 CUDA 应用清理):
```
Attaching 18 probes...
Tracing NVIDIA GPU driver activity... Hit Ctrl-C to end.
TIME(ms) EVENT COMM PID GPU_ID DETAILS
2627 IOCTL nvtop 759434 - cmd=0xc020462a
38984 CLOSE python 783815 - GPU device closed
70693 CLOSE cuda00001400006 781802 - GPU device closed
72427 OPEN llama-server 800150 - GPU device opened
72427 CLOSE llama-server 800150 - GPU device closed
72427 OPEN llama-server 800150 - GPU device opened
72428 OPEN llama-server 800150 - GPU device opened
72431 MMAP llama-server 800150 - offset=0xffff968357d37140 size=...
72448 OPEN llama-server 800150 - GPU device opened
... (在初始化期间 llama-server 的 39 次 open,26 次 mmap)
========================================
NVIDIA GPU Driver Statistics
========================================
--- Device Operations ---
Opens by process:
@opens[llama-server]: 39
Closes by process:
@closes[llama-server]: 1
@closes[python]: 8
@closes[cuda00001400006]: 38
Total ioctls:
@ioctl_count: 2779
Top ioctl callers:
@ioctls_per_process[llama-server]: 422
@ioctls_per_process[nvtop]: 2357
Total mmaps:
@mmap_count: 26
--- Async Operations ---
Poll calls:
@poll_count: 24254
Currently open PIDs:
@open_pids[800150]: 1
```
**分析**:这个真实世界的跟踪揭示了几个模式。llama-server 进程在初始化期间打开了 GPU 设备 39 次 - 对于为不同模型层或批处理策略初始化多个 CUDA 上下文的 LLM 推理引擎来说很典型。来自 llama-server 的 422 次 ioctl 表示活跃的推理工作。nvtop 监控工具发出了 2,357 次 ioctl 轮询 GPU 状态。脚本捕获了来自终止 CUDA 应用(cuda00001400006)的 38 次设备关闭和来自 Python 进程的 8 次 - 显示清理模式。24,254 次轮询调用表示来自监控工具的高异步 I/O 活动。零页故障表明所有内存都已正确预分配。零 Xid 错误意味着硬件运行正常。当前打开的 PID 800150(llama-server)在跟踪结束后仍保持活动状态。
## 运行监控脚本
导航到教程目录并根据你的 GPU 运行适当的监视器。
**对于基于 DRM 的 GPU(Intel、AMD、Nouveau)** - 通用监控:
```bash
cd bpf-developer-tutorial/src/xpu/gpu-kernel-driver
sudo bpftrace scripts/drm_scheduler.bt
```
**对于 NVIDIA 专有驱动**:
```bash
cd bpf-developer-tutorial/src/xpu/gpu-kernel-driver
sudo bpftrace scripts/nvidia_driver.bt
```
预期输出: