GPU Direct DMA P2P FPGA 通讯在Jetson 平台与X86测试表现 Jetson 与 H100

GPU Direct DMA 在Jetson NX 与 X86平台的测试

测试了jetson NX 16GB 与 H100的性能,后续会继续补充其它平台的测试

1. 技术原理

1.1 什么是 GPU Direct RDMA

GPU Direct RDMA(Remote Direct Memory Access)是 NVIDIA 提供的一种高性能数据传输技术,允许第三方 PCIe 设备(如 FPGA、网卡、视频采集卡)绕过 CPU 和系统内存,通过 PCIe 总线直接与 GPU 显存进行数据交换。

传统数据路径(FPGA → GPU):

复制代码
FPGA ──DMA──→ CPU内存 ──cudaMemcpy──→ GPU显存
         ↑                    ↑
      PCIe传输            内存总线拷贝
      (第1次)              (第2次)

GPU Direct RDMA 路径(FPGA → GPU):

复制代码
FPGA ──PCIe DMA──→ GPU显存
         ↑
    仅一次PCIe传输
    零CPU拷贝

1.2 核心优势

优势 说明
延迟降低 消除 CPU 中间拷贝,端到端延迟减少约 50%
带宽提升 避免内存总线争用,有效带宽提升 1.5x~2.5x
CPU卸载 DMA 传输期间 CPU 完全空闲,可处理其他任务
零拷贝 数据直达 GPU,无需系统内存中转缓冲
确定性延迟 无 CPU 调度干扰,适合实时系统

1.3 适配设备与平台

平台 支持状态 GPU 类型 备注
NVIDIA Jetson Orin (Tegra) ✅ 已验证 集成 GPU (统一内存) 通过 nvidia-p2p 内核接口
NVIDIA Jetson Xavier ✅ 可适配 集成 GPU 同 Orin 架构
x86 + NVIDIA 独立显卡 ✅ 已验证 H100 PCIe 通过 nvidia-peermem + cudaMalloc
FPGA(Xilinx Kintex/Artix) ✅ 已验证 N/A 通过 XDMA IP 核 + 自定义驱动
其他 PCIe DMA 设备 ✅ 可扩展 - 需实现 Pin/Unpin/Transfer ioctl

1.4 工作流程

复制代码
1. GPU 缓冲区分配 (cudaHostAlloc / cudaMalloc)
2. Pin 操作: 将 GPU 虚拟地址映射为物理页面,锁定在内存中
3. DMA 传输: FPGA 直接读写 GPU 物理页面(通过 PCIe BAR)
4. Unpin 操作: 释放页面锁定

关键点:Pin 操作仅需执行一次,后续可无限次复用同一 Handle 进行 DMA 传输,避免了传统方式中每次传输都需要的地址转换开销。


2. 测试环境

2.1 硬件平台

Tegra 平台 (Jetson Orin)

组件 规格
嵌入式平台 NVIDIA Jetson Orin (aarch64)
GPU Orin 集成 Ampere GPU, 统一内存架构
FPGA Xilinx 系列, PCIe Gen3 x4
FPGA 端内存 DDR4 2GB
PCIe 链路 Gen3 x4 (理论峰值 ~2GB/s)
系统内存 LPDDR5 (统一内存)

Desktop 平台 (x86 + H100)

组件 规格
CPU Intel Xeon Platinum 8462Y+
GPU NVIDIA H100 PCIe (80GB HBM2e), 独立显存架构
FPGA Xilinx 系列 (VID:0x0B03, PID:0x1004), PCIe Gen3 x8
FPGA 端内存 DDR4 2GB
PCIe 链路 Gen3 x8 (理论峰值 ~7.88 GB/s)
系统内存 DDR5 (独立于 GPU 显存)

2.2 软件环境

Tegra 平台

组件 版本
OS Ubuntu 22.04 (aarch64)
CUDA 12.6
内核驱动 HelloFPGA XDMA 自定义驱动 (v2020.2.2) + GPU Direct 扩展
用户空间库 libHelloFPGACore.so (含 GPU Direct 兼容层)
编译器 nvcc (CUDA 12.6) + GCC

Desktop 平台

组件 版本
OS Ubuntu 22.04 (x86_64)
内核 6.8.0-124-generic
CUDA 12.4 (V12.4.99)
GPU 驱动 NVIDIA 590.48.01
内核驱动 HelloFPGA XDMA 自定义驱动 + nvidia-peermem 扩展
用户空间库 libHelloFPGACore.so (x64, 含 GPU Direct 兼容层)
编译器 nvcc (CUDA 12.4) + GCC

2.3 驱动架构

复制代码
用户空间:  HelloFPGACore.so (TransferMode API)
               │
               ├─ CPU模式: open(/dev/HelloFPGA0_c2h_*) → read/write
               │
               └─ GPU Direct模式: open → ioctl(XDMA_IOC_GPU_PIN/XFER/UNPIN)
                        │
内核空间:  HelloFPGA.ko (XDMA + xdma_gpu_direct + xdma_gpu_tegra)
                        │
硬件:      FPGA XDMA IP ←──PCIe──→ GPU BAR (物理地址直通)

3. 测试方法

3.1 测试工具

测试程序: gpu_direct_api_test.cu

支持两种运行模式:

  • 快速功能测试: 验证 API 正确性 + 性能对比(约 2 分钟)
  • 长稳态压力测试 : 12 小时持续运行,每 10 分钟记录数据(--long 参数)

3.2 测试对比方案

路径编号 方案名称 数据流向 说明
A CPU DMA 仅 FPGA → CPU 内存 传统 DMA,数据停留在 CPU 侧
B FPGA→CPU→GPU 全路径 FPGA → CPU → GPU 传统方式将数据送达 GPU 的完整路径
C GPU Direct Handle FPGA → GPU 直达 预 Pin + DMA 直传,无 CPU 中转

3.3 测试项目

测试项 内容
API 功能验证 GetStatus / Pin / ReadC2H / WriteH2C / Unpin
数据正确性 写入 pattern → 回读 → 逐字节比对
多尺寸性能 4KB ~ 8MB,6 种尺寸全覆盖
2GB 地址空间 遍历 FPGA 0~2GB 全范围,验证无地址死角
多缓冲区轮转 4 帧 GPU 缓冲区循环采集,对比单缓冲区
TransferMode 兼容 老接口零修改,内部自动路由至 GPU Direct
12 小时稳定性 72 次采样,功耗/性能/抖动全记录

3.4 关键参数

  • 传输块大小: 4MB(长测试) / 4KB~8MB(快速测试)
  • FPGA 地址步进: 64MB(遍历 0~2GB,32 个测试点/轮)
  • 采样频率: 每 10 分钟(长测试)
  • 每采样点迭代: 5 次取平均
  • 功耗采集: INA3221 传感器 (VDD_IN 通道)

4. 测试结果

4.1 多尺寸性能对比(快速测试)

时延对比 (μs,越小越好)

数据大小 CPU DMA 仅 FPGA→CPU→GPU 全路径 GPU Direct 加速比 (vs CPU) 加速比 (vs 全路径)
4KB 82.6 / 58.4 232.8 / 86.2 54.4 / 45.4 1.52x / 1.29x 4.28x / 1.90x
64KB 87.8 / 80.4 122.4 / 195.2 70.2 / 74.4 1.25x / 1.08x 1.74x / 2.62x
512KB 341.8 / 301.6 635.2 / 740.2 292.0 / 243.4 1.17x / 1.24x 2.18x / 3.04x
1MB 638.4 / 574.6 1016.0 / 1219.2 521.2 / 412.6 1.22x / 1.39x 1.95x / 2.95x
4MB 2398.0 / 2102.8 3417.6 / 3522.2 1773.6 / 1487.0 1.35x / 1.41x 1.93x / 2.37x
8MB 4888.2 / 4250.0 6564.8 / 6507.6 3557.4 / 2951.2 1.37x / 1.44x 1.85x / 2.21x

表格格式: Read / Write

带宽对比 (GB/s,越大越好)

数据大小 CPU DMA 仅 FPGA→CPU→GPU GPU Direct
512KB 1.53 / 1.74 0.83 / 0.71 1.80 / 2.15
1MB 1.64 / 1.82 1.03 / 0.86 2.01 / 2.54
4MB 1.75 / 1.99 1.23 / 1.19 2.36 / 2.82
8MB 1.72 / 1.97 1.28 / 1.29 2.36 / 2.84

GPU Direct 峰值带宽达 2.84 GB/s,逼近 PCIe Gen3 x4 理论极限

4.2 TransferMode 兼容模式性能

用户代码零修改 (仍调用 HelloFPGA_DMA_MM_*),仅通过 2 行配置切换模式:

数据大小 CPU 模式 (μs) GPU_PINNED 模式 (μs) 加速比
4KB 79.6 / 65.4 57.8 / 51.8 1.38x / 1.26x
64KB 140.4 / 123.2 69.8 / 75.0 2.01x / 1.64x
256KB 198.2 / 210.6 141.4 / 155.2 1.40x / 1.36x
1MB 607.0 / 677.8 417.2 / 487.6 1.45x / 1.39x
4MB 2183.2 / 2516.2 1491.8 / 1781.4 1.46x / 1.41x
8MB 4279.4 / 4977.4 2954.4 / 3541.0 1.45x / 1.41x

格式: Write / Read

4.3 多缓冲区 vs 单缓冲区对比

模拟实际图像采集场景:4 个 GPU 缓冲区轮转 vs 单缓冲区重复读写(100 次迭代,1MB/帧)

指标 多缓冲区 (4帧轮转) 单缓冲区 差异
平均时延 501.7 μs 491.9 μs -
最小时延 460.0 μs 455.0 μs -
最大时延 1124.0 μs 660.0 μs -
平均带宽 2.09 GB/s 2.13 GB/s -
等效帧率 1993 fps 2033 fps -
比值 - - 0.98x (基本一致)

结论:多缓冲区地址查表匹配开销可忽略不计,不影响性能。

4.4 12 小时长稳态测试

  • 测试时长: 12.00 小时
  • 采样点数: 72 次(每 10 分钟)
  • 传输块大小: 4MB
  • 地址遍历: 0 ~ 2GB(完成 2 轮完整遍历)

性能统计

指标 CPU DMA 仅 FPGA→CPU→GPU GPU Direct
平均 Read (μs) 2711.9 3518.3 1785.1
平均 Write (μs) 2276.2 3701.2 1489.0
平均带宽 Read 1.55 GB/s 1.19 GB/s 2.35 GB/s
平均带宽 Write 1.84 GB/s 1.13 GB/s 2.82 GB/s

加速比

对比基准 Read Write
GPU Direct vs CPU DMA 1.52x 1.53x
GPU Direct vs 传统全路径 1.97x 2.49x

性能稳定性

指标 GPU Direct Read GPU Direct Write
最小时延 1749.6 μs 1461.2 μs
最大时延 2008.0 μs 1554.6 μs
抖动 (max-min) 258.4 μs 93.4 μs
相对波动 ±7.2% ±3.1%

时间趋势(无退化)

时段 GPU Read 平均 GPU Write 平均 功耗
0 ~ 4h 1782 μs 1483 μs 18.38 W
4 ~ 8h 1784 μs 1490 μs 18.65 W
8 ~ 12h 1786 μs 1488 μs 18.78 W

功耗统计

指标 数值
平均功耗 18.57 W
最小功耗 18.23 W
最大功耗 18.91 W
波动范围 0.69 W (±1.8%)

地址空间一致性

FPGA 全2GB 地址范围(0MB ~ 1984MB,64MB 步进)的 GPU Direct 传输时延无显著差异(标准差 < 15μs),表明 FPGA 端 DDR 控制器对全地址空间性能一致。


4.5 x86 Desktop 平台 (H100) 测试结果

测试日期: 2025-07-05

平台: Intel Xeon 8462Y+ / NVIDIA H100 PCIe / FPGA PCIe Gen3 x8

测试结果: 15 项全部通过

4.5.1 API 功能验证

测试项 结果 说明
GetStatus ✅ PASS platform=2 (Desktop), supported=1, alignment=65536
Pin ✅ PASS 使用 cudaMalloc 分配设备显存, 耗时 45.0 μs
ReadC2H (批量) ✅ PASS 1MB, 160.0 μs, 6.55 GB/s
WriteH2C (批量) ✅ PASS 1MB, 164.0 μs, 6.39 GB/s
Unpin ✅ PASS 耗时 17.0 μs
数据正确性 ✅ PASS 262144 int32 全部匹配
批量模式 10×ReadC2H ✅ PASS 10MB, 1503.0 μs, 6.98 GB/s
2GB地址空间 7点 ✅ PASS 全部数据匹配
2GB压力测试 6偏移 ✅ PASS 全部通过
2GB边界测试 6点 ✅ PASS 全部通过

4.5.2 多尺寸性能对比

时延对比 (μs,越小越好)
数据大小 CPU DMA 仅 (Read/Write) FPGA→CPU→GPU 全路径 GPU Direct Handle 加速比 (vs CPU) 加速比 (vs 全路径)
4KB 15.2 / 13.2 29.8 / 37.6 12.8 / 13.4 1.19x / 0.99x 2.33x / 2.81x
64KB 22.2 / 21.8 33.0 / 36.8 20.4 / 22.0 1.09x / 0.99x 1.62x / 1.67x
512KB 94.2 / 93.6 118.8 / 146.2 82.2 / 86.0 1.15x / 1.09x 1.45x / 1.70x
1MB 175.0 / 176.4 220.8 / 270.0 152.2 / 159.2 1.15x / 1.11x 1.45x / 1.70x
4MB 672.8 / 664.8 912.0 / 924.0 574.8 / 600.8 1.17x / 1.11x 1.59x / 1.54x
8MB 1330.2 / 1332.0 1739.4 / 1784.2 1138.8 / 1191.8 1.17x / 1.12x 1.53x / 1.50x
带宽对比 (GB/s,越大越好)
数据大小 CPU DMA 仅 FPGA→CPU→GPU GPU Direct Handle GPU Direct MM (auto)
512KB 5.57 / 5.60 4.41 / 3.59 6.38 / 6.10 5.04 / 5.01
1MB 5.99 / 5.94 4.75 / 3.88 6.89 / 6.59 5.95 / 5.67
4MB 6.23 / 6.31 4.60 / 4.54 7.30 / 6.98 6.62 / 6.41
8MB 6.31 / 6.30 4.82 / 4.70 7.37 / 7.04 6.79 / 6.51

GPU Direct Handle 峰值带宽达 7.37 GB/s,逼近 PCIe Gen3 x8 理论极限 (~7.88 GB/s)

4.5.3 TransferMode 兼容模式性能 (Desktop)

用户代码零修改 (仍调用 HelloFPGA_DMA_MM_*),仅通过配置切换模式:

数据大小 CPU 模式 (Write/Read μs) GPU_PINNED 模式 (μs) 加速比 (Wr/Rd)
4KB 13.2 / 13.2 12.2 / 10.6 1.08x / 1.25x
64KB 21.8 / 21.2 20.0 / 18.4 1.09x / 1.15x
256KB 52.2 / 51.6 47.4 / 45.0 1.10x / 1.15x
1MB 174.0 / 173.0 157.6 / 151.8 1.10x / 1.14x
4MB 661.4 / 655.8 596.6 / 571.2 1.11x / 1.15x
8MB 1307.4 / 1295.8 1183.0 / 1133.2 1.11x / 1.14x

Desktop 平台加速比 ~1.1-1.15x,因 PCIe Gen3 x8 带宽充裕,CPU DMA 本身已接近峰值

4.5.4 多缓冲区 vs 单缓冲区 (Desktop)

4 个 GPU 缓冲区轮转 vs 单缓冲区重复读写(100 次迭代,1MB/帧)

指标 多缓冲区 (4帧轮转) 单缓冲区 差异
平均时延 150.1 μs 150.2 μs -
最小时延 149.0 μs 149.0 μs -
最大时延 159.0 μs 159.0 μs -
波动范围 10.0 μs 10.0 μs -
平均带宽 6.985 GB/s 6.981 GB/s -
等效帧率 6661 fps 6658 fps -
比值 - - 1.0005x (基本一致)

结论:多缓冲区地址查表开销可忽略不计,帧率达 6600+ fps。

4.5.5 12 小时长稳态测试 (Desktop H100)

测试日期: 2026-07-05 12:05 ~ 23:55

测试时长: 12.00 小时

采样点数: 72 次(每 10 分钟)

传输块大小: 4MB

地址遍历: 0 ~ 2GB(完成 2 轮完整遍历)

原始数据: gpu_direct_long_test_20260705_120520.csv

性能统计
指标 CPU DMA 仅 FPGA→CPU→GPU 全路径 GPU Direct
平均 Read (μs) 948.4 1671.6 601.0
平均 Write (μs) 869.8 1967.1 620.4
平均带宽 Read 4.42 GB/s 2.51 GB/s 6.98 GB/s
平均带宽 Write 4.82 GB/s 2.13 GB/s 6.76 GB/s
加速比
对比基准 Read Write
GPU Direct vs CPU DMA 1.58x 1.40x
GPU Direct vs 传统全路径 2.78x 3.17x
性能稳定性
指标 GPU Direct Read GPU Direct Write
最小时延 596.8 μs 615.8 μs
最大时延 711.2 μs 736.8 μs
抖动 (max-min) 114.4 μs 121.0 μs
相对波动 ±8.8% ±9.3%

注:出现 2 个异常点(640min Read=711.2μs, 660min Write=736.8μs),其余 70 个采样点均在 ±5% 范围内,整体稳定性良好。

时间趋势(无退化)
时段 GPU Read 平均 GPU Write 平均 备注
0 ~ 4h 598.8 μs 617.6 μs 稳定
4 ~ 8h 600.2 μs 619.8 μs 稳定
8 ~ 12h 601.0 μs 621.2 μs 稳定
功耗统计
指标 数值
功耗采集 未接入 INA3221 传感器
备注 后续测试将补充功耗数据
地址空间一致性

FPGA 全 2GB 地址范围(0MB ~ 1984MB,64MB 步进)的 GPU Direct 传输时延无显著差异(标准差 < 8μs),表明 FPGA 端 DDR 控制器对全地址空间性能一致。

4.5.6 平台对比汇总 (Tegra vs Desktop)

指标 Tegra (Orin, Gen2 x4) Desktop (H100, Gen3 x8) 提升倍数
GPU Direct Handle 峰值带宽 2.84 GB/s 7.37 GB/s 2.6x
GPU Direct Handle 1MB Read 521.2 μs 152.2 μs 3.4x
Pin 操作时延 ~53 μs ~45 μs -
Unpin 操作时延 ~17 μs ~17 μs 相当
多缓冲区帧率 (1MB) 1993 fps 6661 fps 3.3x
数据正确性 -
2GB地址空间覆盖 -

性能提升主要来源于 PCIe 链路升级 (Gen3 x4 → Gen3 x8,理论带宽 2x)


5. 结论

5.1 性能结论

  1. GPU Direct 相比传统全路径 (FPGA→CPU→GPU) 加速 ~1.5x~3.2x

    • Tegra: Read 加速 1.97x,Write 加速 2.49x(4MB 块,12h 平均)
    • Desktop: Read 加速 2.78x,Write 加速 3.17x(4MB 块,12h 平均)
    • 消除 cudaMemcpy 中间拷贝是主要收益来源
  2. GPU Direct 相比 CPU DMA 仅加速 ~1.1x~1.6x

    • Tegra: ~1.5x(PCIe Gen3 x4 带宽受限,GPU Direct 优势明显)
    • Desktop: Read 1.58x / Write 1.40x(PCIe Gen3 x8 带宽充裕,GPU Direct 仍有明显优势)
  3. 峰值带宽

    • Tegra (Gen2 x4): 2.84 GB/s,接近理论极限
    • Desktop (Gen3 x8): 7.37 GB/s,逼近理论极限 (~7.88 GB/s,达 93.5%)
    • Desktop 长稳态 Read 平均带宽: 6.98 GB/s ,Write 平均带宽: 6.76 GB/s
  4. Desktop 平台帧率达 6600+ fps (1MB/帧),适合高帧率图像采集场景

  5. Desktop 12 小时长稳态:GPU Direct Read 平均 601.0 μs,Write 平均 620.4 μs,性能无退化

5.2 稳定性结论

  1. Tegra 12 小时无性能退化:前 4h 与后 4h 性能差异 < 0.3%
  2. Desktop 12 小时无性能退化:0~4h / 4~8h / 8~12h 三时段 Read/Write 时延波动 < 0.4%
  3. 无内存泄漏:Pin/Unpin 生命周期管理正确
  4. 无热节流:Tegra 功耗稳定在 18.2~18.9W,无过热降频
  5. 2GB 全地址空间一致:无 FPGA 端 DDR 热点(两平台均验证)

5.3 兼容性结论

  1. 完全向后兼容:老代码无需任何修改即可继续使用
  2. 最小侵入接入:仅需新增 2 行代码(SetGPUBuffer + SetTransferMode)
  3. 多缓冲区无开销:4 帧轮转性能与单帧一致,适合图像流应用
  4. 跨平台透明 :同一套测试代码同时兼容 Tegra (cudaHostAlloc) 和 Desktop (cudaMalloc),通过 GetStatus.platform 自动适配
  5. 双平台验证通过:Tegra (Orin) 和 Desktop (H100) 均 15/15 测试全通过

5.4 适用场景建议

场景 推荐方案 预期加速
FPGA 图像采集 → GPU 推理 GPU Direct (多缓冲) 2.0x
FPGA 信号处理 → GPU 计算 GPU Direct (单缓冲) 1.5x~2.0x
FPGA ↔ CPU 数据交换(不涉及GPU) 传统 CPU DMA 无需切换
小数据包 (< 4KB) 传统 CPU DMA GPU Direct 优势不明显

5.5 建议与限制

  • 最小传输块建议 ≥ 64KB:小数据包中 DMA 建立开销占比大,GPU Direct 优势有限
  • Pin 操作仅需一次:应在初始化阶段完成,避免传输循环中频繁 Pin/Unpin
  • 4K 对齐要求:GPU 缓冲地址和大小必须 4096 字节对齐
  • 需 root 权限:GPU Direct ioctl 需要特权访问设备文件

6. 与 NVIDIA jetson-rdma-picoevb 开源方案对比

NVIDIA/jetson-rdma-picoevb 是 NVIDIA 官方提供的最小化 GPU Direct RDMA 硬件演示项目,使用 PicoEVB (Xilinx Artix-7) FPGA 板卡在 Jetson AGX Xavier 上验证 GPUDirect RDMA 功能。下面从多个维度与 HelloFPGA GPU Direct 方案进行对比。

6.1 架构对比

维度 NVIDIA picoevb HelloFPGA GPU Direct
定位 最小化演示/参考实现 生产级驱动框架
FPGA PicoEVB (Artix-7) / HTG-K800 (Kintex UltraScale) Xilinx Kintex/Artix 系列 (XDMA IP)
内核模块 picoevb-rdma.ko (独立专用驱动) HelloFPGA.ko (XDMA 基础 + GPU Direct 扩展模块)
用户空间 独立测试程序直接 ioctl libHelloFPGACore.so 封装库 + TransferMode 兼容层
设备文件 /dev/picoevb (单设备) /dev/HelloFPGA0_c2h_*, /dev/HelloFPGA0_h2c_* (多通道)
多设备支持 不支持 支持多 FPGA 板卡 (slot 编号)

6.2 内核层实现对比

特性 picoevb HelloFPGA
Pin 接口 nvidia_p2p_get_pages() (Tegra简化版,无 token) nvidia_p2p_get_pages() (同, xdma_gpu_tegra 适配层)
Unpin 接口 nvidia_p2p_put_pages() nvidia_p2p_put_pages()
DMA 映射 nvidia_p2p_dma_map_pages() → 手动操作 BAR nvidia_p2p_dma_map_pages() → XDMA SG-DMA 引擎
传输方式 FPGA BAR 直接读写 (MMIO/PIO), 64KB 分块 XDMA Scatter-Gather DMA 引擎,支持大块连续传输
中断 无 (轮询) XDMA 中断/轮询可选
DMA 引擎 FPGA 自定义简单引擎 (64KB BRAM 中转) Xilinx XDMA IP 硬核 (支持 MM/ST 模式)
Pin 缓存 有 (cache_hits/cache_misses 统计)
地址对齐 64KB (Desktop) / 4KB (Tegra) 4KB (Tegra) / 64KB (Desktop)

6.3 用户空间接口对比

picoevb 方案 (裸 ioctl):

c 复制代码
// 1. 分配 CUDA 内存
cudaHostAlloc(&buf, size, cudaHostAllocDefault);  // Tegra 必须用 cudaHostAlloc
cuPointerSetAttribute(&flag, CU_POINTER_ATTRIBUTE_SYNC_MEMOPS, (CUdeviceptr)buf);

// 2. Pin
ioctl(fd, PICOEVB_IOC_PIN_CUDA, &pin_params);

// 3. DMA 传输
ioctl(fd, PICOEVB_IOC_DMA_C2H, &xfer_params);  // 每次传输都需要单独 ioctl

// 4. Unpin
ioctl(fd, PICOEVB_IOC_UNPIN_CUDA, &unpin_params);

HelloFPGA 方案 (封装 API + TransferMode 兼容):

c 复制代码
// 方式一:显式 GPU Direct API
HelloFPGA_GPUDirect_Pin(hDev, gpuAddr, size, &handle);
HelloFPGA_GPUDirect_ReadC2H(hDev, ch, handle, ep_addr, size, timeout);
HelloFPGA_GPUDirect_Unpin(hDev, handle);

// 方式二:TransferMode 兼容(零修改老代码)
HelloFPGA_SetGPUBuffer(hDev, gpuAddr, size);    // Pin 一次
HelloFPGA_SetTransferMode(hDev, HELLOFPGA_XFER_MODE_GPU_PINNED);
HelloFPGA_DMA_MM_ReadC2H(hDev, ch, buf, offset, len, &actual);  // 内部自动路由
HelloFPGA_ReleaseGPUBuffer(hDev);               // 清理

6.4 传输性能机制对比

特性 picoevb HelloFPGA
DMA 类型 FPGA 自定义引擎 (BAR-based) Xilinx XDMA IP (SG-DMA)
最大单次传输 64KB (受 FPGA BRAM 限制) 无限制 (SG 链表)
大数据传输 应用层分 64KB 块循环 驱动层自动 SG 分片
中断/完成通知 轮询 BAR 状态寄存器 XDMA 完成中断 + 事件通知
零拷贝路径 ✅ GPU 页面 → FPGA BAR → GPU 页面 ✅ GPU 页面 → PCIe DMA → FPGA DDR
吞吐量瓶颈 FPGA BRAM 64KB 中转 + 轮询延迟 PCIe 链路带宽 (无额外中转)

6.5 关键差异总结

对比项 picoevb 优势 HelloFPGA 优势
代码复杂度 ✅ 极简 (~800行内核代码) 功能丰富但复杂
学习参考价值 ✅ 适合理解 RDMA 原理 适合生产部署
传输效率 64KB 分块,吞吐受限 ✅ SG-DMA 大块传输,带宽接近 PCIe 极限
API 易用性 裸 ioctl,需手动管理 ✅ 高层 API + 向后兼容
多缓冲区 不支持 ✅ 多 GPU buffer 注册 + 地址查表路由
生产级特性 ✅ 进程互斥锁、错误恢复、多设备、DB 记录
平台支持 Xavier/PC ✅ Xavier/Orin/PC
内存分配 Tegra 必须 cudaHostAlloc cudaHostAlloccudaMalloc 均可
TransferMode ✅ 老代码零修改切换 GPU Direct

6.6 技术路线差异分析

picoevb 的设计哲学:最小化验证 GPU Direct RDMA 的可行性。FPGA 只有一块 64KB BRAM,内核模块直接操作 BAR 空间做 PIO 读写,传输逻辑由应用层驱动。适合学习和原型验证。

HelloFPGA 的设计哲学:生产级高性能框架。利用 Xilinx XDMA IP 提供的硬件 SG-DMA 引擎,在驱动层完成地址翻译和 DMA 调度,对用户层暴露高层 API,并通过 TransferMode 机制实现零侵入式升级。适合实际产品部署。

核心技术差异:

  1. DMA 引擎层面:picoevb 使用 FPGA 自定义的简单引擎(BAR 读写),受限于 BRAM 大小;HelloFPGA 使用 Xilinx XDMA IP 核的硬件 SG-DMA,可一次发起 MB 级传输。

  2. Pin 管理策略:picoevb 每次操作都是独立的 Pin→Transfer→Unpin 流程;HelloFPGA 支持 "Pin Once, Use Many" 模式,Pin 操作在初始化阶段完成一次,后续传输复用 Handle,消除了 Pin/Unpin 开销。

  3. 兼容层设计 :picoevb 无兼容层概念,应用需要直接感知 RDMA;HelloFPGA 通过 TransferMode 路由,让已有的 DMA_MM_Read/Write 接口在设置模式后自动切换底层路径,实现了零代码改造升级。

  4. 内存分配差异 :picoevb 在 Tegra 平台强制 使用 cudaHostAlloc()(因为 Tegra 版 nvidia_p2p_get_pages 不支持 cudaMalloc 的地址);HelloFPGA 通过 xdma_gpu_tegra 适配层统一处理,对用户透明。