跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • 浅色
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • 深色
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(LCZ-Blue)
  • 不使用皮肤
  • LCZ-Green
  • LCZ-Blue
  • LCZ-Black
折叠
品牌标识

抡锤者

首页 版块 标签 硬件 AI 广场
  1. 主页
  2. 版块
  3. AI硬件
  4. # X99 洋垃圾 + 双 R9700 续篇:限频降压救活双卡供电,P2P/TP 却全线阵亡 —— 最终形态是「双卡双实例」

# X99 洋垃圾 + 双 R9700 续篇:限频降压救活双卡供电,P2P/TP 却全线阵亡 —— 最终形态是「双卡双实例」

已定时 固定直到 2026/9/15 17:35 已锁定 已移动 AI硬件
x99r9700多卡部署
12 帖子 5 发布者 204 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • 张光璞张 在线
    张光璞张 在线
    张光璞
    劳动模范 德高望重
    编写于 最后由 编辑
    #1

    上一篇讲了怎么把这台 X99 洋垃圾(Dell T7910)刷成能跑 R9700 的推理机,以及插上第二张卡后一满载就硬断电的翻车。
    这篇是续集,三件事:
    ① 把供电问题彻底解决(不是换电源);
    ② 把「双卡跑一个大模型提速」这条路从 TP → 行拆分 → tensor 全试一遍;
    ③ 得到最终形态 —— 双卡双实例,一卡一个模型。


    TL;DR

    我想做的事 结果 关键原因
    双卡同时满载不掉电 ✅ 做到了(400W 稳定 225 秒) OD 限频 + 降压,不是换电源
    双卡 TP(张量并行)提速 ❌ 全线失败 P2P 不可用(内核白名单),绕不过去
    双卡「行拆分」提速 ❌ 加载即崩 ROCm 后端没实现 split_buffer_type
    双卡「tensor」模式提速 ⚠️ 能跑但不值 AllReduce 退化 + 不兼容投机解码
    双卡「层拆分」提速 ❌ 不提速,只加显存 层拆分是串行流水线
    双卡最终形态 ✅ 双实例,一卡一个模型 零通信开销、互不拖累

    一句话:这块平台的瓶颈从来不是钱,是**「并行」这件事在 X99 上被物理封死了** —— 双卡唯一正确的用法是让它俩各干各的。


    一、平台配置

    项 规格 备注
    机型 Dell Precision T7910 塔式工作站 洋垃圾整机
    CPU 2× Xeon E5-2683 v4(16C/32T each,32C/64T) 双路,两个 NUMA 节点
    内存 4× 32G DDR4-2400 每路双通道,76.8 GB/s
    电源 原装 1300W(型号 D1300EF-02) ⚠️ 规格是 4 路 12V × 18A
    GPU 2× AMD Radeon AI PRO R9700 32GB(gfx1201 / RDNA4) 250W/卡(限频后实际 ~250W 峰值)
    系统 Ubuntu 24.04.5 LTS,内核 7.0.0-31 ROCm 7.2.0
    推理后端 llama.cpp(HIP 后端,commit 56381e4) 自己编译,打了 FastMTP 补丁

    相对上一篇,平台这边新增的两件事

    1. 换了卡位:把其中一张卡从 CPU2 的槽搬到 CPU1 的空闲 x16 槽 → 两卡同 NUMA 节点、跳数 3→2。
    2. 关了 BIOS 虚拟化(本想关掉 IOMMU 隔离,后来发现没用,见第五节)。

    二、破解跳闸:根本不是功率问题

    2.1 先做对照实验(这一步是全文的地基)

    单卡任何配置都能跑,双卡一上负载 47 秒断电。所以我把「单卡 × 模型」全排列测了一遍,每档压 90 秒以上:

    88705bd0-6679-4b26-8b90-0c972ae12857-image.jpeg
    单卡三种配置全部通过,双卡合计仅 263W 就跳闸

    实验 平均功耗 峰值功耗 时长 结果
    A-1 新卡 + gemma-4-26B 182.3 W 262.0 W 90s ✅ 通过
    A-2 原卡 + gemma-4-26B 178.0 W 249.0 W 98s ✅ 通过
    A-3 新卡 + Qwen3.8-27B Q6 236.4 W 289.0 W 92s ✅ 通过
    双实例(两卡各常驻一个模型) 合计仅 263 W — 47s ❌ 硬断电

    功耗采样口径:读 /sys/class/drm/card*/device/hwmon/hwmon*/power1_average,0.15~15 秒一次,采样落盘到家目录(⚠️ 写 /tmp 会在重启后丢光,我踩过)。
    时长口径:三段单卡对照全部 ≥90 秒,和双卡失败那次的 47 秒可比。

    2.2 🔑 转折点

    看第三行和第四行:236W 的单卡不跳,263W 的双卡跳。

    也就是说 —— 失败跟总功率、跟在跑什么模型,都没有关系。

    再补一刀:我把 power1_cap(功率上限)从 280W 一路降到 210W(这卡的硬件下限),双卡依然一上负载就跳。

    结论:限制的不是「总功率」,是「瞬态尖峰的幅度」。
    power1_cap 管的是长窗口平均功耗,对微秒级的 dI/dt 尖峰毫无办法(它的 sysfs 标签其实叫 PPT = Power Target,是「目标」不是「上限」)。
    唯一和失败严格相关的变量是:两张卡的显存子系统是否同时从空闲转入满载。

    证据链(按排除顺序):

    1. 降 cap 后仍断 ⇒ 不是「上限设太高」
    2. 崩溃瞬间实测功率确实等于设定值 ⇒ 不是「限功没生效」
    3. 单卡 289W 不跳、双卡 263W 跳 ⇒ 不是「持续过载」
    4. 跳闸发生在上负载而非启动/加载(双卡空载挂 90+ 秒完全没事)⇒ 是尖峰触发电源保护

    (另外:崩溃前 journalctl 没有任何内核日志,登录会话全部标记 crash —— 这是电源保护跳闸的签名,不是内核 panic、不是驱动崩溃、不是过热。)


    三、解法:限频 + 降压(不换电源)

    既然要压的是尖峰,那就去动电压/频率曲线,而不是功耗上限。

    3.1 正确接口是 pp_od_clk_voltage,不是 pp_dpm_sclk

    # 每张卡都要做一遍
    echo "s -500"  | sudo tee /sys/class/drm/cardN/device/pp_od_clk_voltage   # SCLK  偏移 -500MHz
    echo "vo -100" | sudo tee /sys/class/drm/cardN/device/pp_od_clk_voltage   # VDDGFX 偏移 -100mV
    echo "c"       | sudo tee /sys/class/drm/cardN/device/pp_od_clk_voltage   # 提交
    # echo "r"     | sudo tee ...                                              # 复位回默认
    

    可调范围(读同一文件即得):SCLK_OFFSET: -500 ~ +1000 MHz、VDDGFX_OFFSET: -200 ~ 0 mV。

    ⚠️ 坑:pp_dpm_sclk 的档位写法 echo "s 2 1500" > pp_dpm_sclk 静默无效(写不报错、读回不变,实测平均功耗 172.6W 几乎没动)。正确接口只有 pp_od_clk_voltage 的偏移写法。

    3.2 效果:功耗 -29%,速度只掉 2%

    51285964-bdce-438b-83f8-ed8b10eae90f-image.jpeg
    (fig2.png)

    指标 限频前 限频后 变化
    单卡平均功耗 182.3 W 129.2 W -29%
    单卡峰值功耗 262.0 W 251.0 W -4%
    decode 速度 84 t/s 82 t/s -2%
    双卡同时满载 ❌ 47 秒跳闸 ✅ 403~426W 稳定 —

    速度口径:llama.cpp server 返回的 timings.predicted_per_second(纯 decode,不含 prefill);固定 prompt + max_tokens=600 长回答;--parallel 1 单流;开 MTP 投机解码。

    为什么速度几乎无损:decode 是显存带宽活(每 token 把权重读一遍),prefill 才是算力活。降 SCLK 主要砍 prefill,decode 掉得很少。

    3.3 固化 + 两个必踩的坑

    已经做成 systemd 服务(Type=oneshot + RemainAfterExit=yes),开机自动应用:

    • ⚠️ 坑 1:必须带「读回校验 + 重试」。首次部署时出现过只配置到一张卡的竞态(开机太早,第二张卡的 sysfs 节点还没出现,for d in /sys/class/drm/card*/... 只匹配到一张)——另一张卡没限频等于白限。脚本要逐卡读回 OD_SCLK_OFFSET 确认,不匹配就重试。
    • ⚠️ 坑 2:只 systemctl enable 不等于生效。必须真重启一次并读回每张卡的值才算验证过。

    四、双卡终于跑起来了

    修好供电之后,把两个模型同时挂上去,压了 225 秒:

    2d20b795-1d87-488a-aa3a-7c00a2d721c3-image.jpeg
    (fig3.png)

    时刻 卡A(跑 27B Q6) 卡B(跑 gemma-4-26B)
    15s 247W / 50°C 139W / 43°C
    60s 251W / 60°C 149W / 52°C
    120s 249W / 63°C 122W / 56°C
    225s 249W / 65°C 14W / 43°C

    双卡同时满载峰值合计 ≈ 400W,持续 225 秒不跳。
    (对比:改造前 263W 就 47 秒断电 —— 撑了 4.8 倍的时长、1.5 倍的功率。)

    口径说明:卡B 在 135 秒后掉到 14W 是正常的 —— gemma 是 MoE(26B/激活 4B),速度快 ~5 倍,它那批 1500 token 早就答完了;卡A 的 Q6 是稠密 27B,一直压到结束。

    顺手做的散热分配(这一步意外地有效):把持续重载的 Q6 放在下层卡(吸冷风顺畅),轻载的 gemma 放上层(散热条件差)。
    实测结果是下层卡最高 65°C、上层卡最高 56°C —— 如果把 Q6 放上层,估计要冲 75°C+。


    五、然后我想上 TP —— 结果撞了三堵墙

    供电解决后,第一个念头就是:既然两张卡都能满载了,那并行跑一个模型是不是能提速?

    答案是不能,而且原因比想象的深。

    5.1 第一堵墙:P2P 根本不可用

    amdgpu 驱动在初始化时就把判决写进了内核日志:

    amdgpu: PCIe P2P access from peer device ... is not supported by the chipset
    

    一行命令就能定性,不用猜。但我不信邪,把常见嫌疑逐个排除了:

    da30bfcb-188b-437c-aff3-a27b5f784e02-image.jpeg
    (fig4.png)

    嫌疑 实测 结论
    ACS 重定向 路径上 8 个 PCIe 桥的 ACSCtl 全是 - × 排除
    IOMMU 隔离 iommu=off;去 BIOS 关了虚拟化后仍然 False × 排除
    REBAR / BAR 太小 BAR 0: current size: 32GB —— 大 BAR 完全正常 × 排除(我原来的判断是错的)
    两卡跨 socket 搬卡到同一 CPU(hops 3→2、同 NUMA)后 P2P 仍为 False × 排除
    内核 p2pdma 白名单 根桥 8086:6f00(Broadwell-EP / X99)不在白名单里 ★ 真因

    这里是本文最大的一个认知修正:我原以为「X99 没有 REBAR」是死因 —— 错。开了 BIOS 的 Above 4G 之后,两张卡都拿到了完整的 32GB BAR。真正卡住的是 Linux 内核的 pci_p2pdma 白名单:只要数据路径要经过 host bridge,就要查这份白名单,而 Intel X99 的根桥不在里面。

    旁证:社区里有人在同代平台(E5-2699v4 + X99 + 同款 R9700)打内核补丁把 0x6f00 加进白名单后,hipDeviceCanAccessPeer() 确实返回了 1,带宽 10.2 GB/s。
    所以「芯片组不支持」这句话是内核策略,不等于硬件做不到。

    5.2 但就算修好,也是负收益

    同一份社区实测的后半段才是关键:硬件 P2P 打通之后,hipIpcOpenMemHandle 在 gfx1201 上恒定报错 17 → RCCL 的 P2P 传输用不上 → vLLM 的 TP=2 只能退回 SHM 传输:

    配置 传输路径 decode(同规模稠密模型)
    默认 SHM/direct/direct 13.6 t/s
    打 DMA 48 位补丁 SHM/direct/direct 14.1 t/s(天花板)
    强开 P2P → 死机,需物理重启 —

    14.1 t/s 比我这张单卡跑 MoE 模型的 84~92 t/s 慢 6 倍。 这是 AMD 侧的软件 bug,不是配置能解决的。

    → 结论:TP 这条路,在这块平台上「要么走不通,要么走通了也没用」。

    5.3 顺手澄清两个常见误区

    ① 「x16 拆分成 x8+x8 就能直连」——不行。
    内核判的是「数据路径是否经过 host bridge」,不是「是否同一个物理插槽」。拆分后两卡落在两个独立 root port(lspci 里表现为成对端口 00:01.0 / 00:01.1),彼此通信仍要「上行进 root complex 再下来」⇒ 依然查白名单 ⇒ 照样判死。
    唯一能绕开的是让两卡挂在同一个 PCIe switch 的下游(公共祖先变成交换芯片,TLP 直接被转发,不进 host bridge)。⚠️ 必须是「同一个」—— 板载两个 PLX、两卡各挂一个,无效。

    ② 「搬卡到同一 CPU 就好了」——也不行。
    实测搬卡后 hops 从 3 降到 2、NUMA 也统一了,P2P 仍然 False,而且层拆分的速度一模一样(详见 5.4)。

    5.4 第二堵墙:llama.cpp 的三种 split-mode 实测

    既然 TP 指望不上,那就试试 llama.cpp 自己的多卡拆分。它有四种模式,我把没测过的三种全测了:

    模式 加载 能否配投机解码 decode 判定
    layer ✅ 73s ✅ 16.8 t/s ✅ 唯一完整可用
    row ❌ 加载即崩 — — ❌ ROCm 后端没实现
    tensor ✅ 81s(不带投机) ❌ 带投机必崩 20.0 t/s ⚠️ 能跑但退化
    layer(关投机对照) ✅ — 18.6 t/s 投机在双卡下≈没开

    row 为什么直接崩(源码里是硬性 throw):

    E llama_model_load: error loading model: device ROCm0 does not support split buffers
    

    llama.cpp 的 ROW 模式要求后端提供 ggml_backend_split_buffer_type 这个接口 —— HIP/CUDA 后端没实现(只有 SYCL 和 Hexagon 有)。所以这不是配置问题,是后端实现缺口。

    tensor 为什么「能跑但不值」:日志里明说了

    W internal AllReduce init failed (n_devices != 2?); falling back to meta-backend butterfly
    W set_sampler: backend sampling not supported with SPLIT_MODE_TENSOR; using CPU
    

    快速 AllReduce 初始化失败,退化成了软件 butterfly —— 而它依赖的正是 peer access(P2P)。没有 P2P,tensor 模式注定退化。 再加上带投机解码会直接断言崩溃(GGML_ASSERT(... GGML_BACKEND_SPLIT_AXIS_1) failed),实际是负收益。

    5.5 闭环:为什么「双卡只能层拆分」是必然的

    X99 根桥不在 Linux pci_p2pdma 白名单
            ↓
    P2P 永远不可用
            ↓
    ├─ vLLM / SGLang TP2   → RCCL 用不上 P2P → 14.1 t/s 天花板
    ├─ llama.cpp `row`     → 后端没实现(另一条独立死因)
    └─ llama.cpp `tensor`  → AllReduce 退化 → 只 +19%,还不兼容投机
            ↓
    唯一能完整跑通的 = `layer`(串行流水线,不依赖 P2P)
            ↓
    但 layer 不提速,只加显存
    

    「双卡并行」这件事,在这块平台上是被物理封死的,不是没调好参数。


    六、速度总账

    d6abfd3a-d115-4736-8c5e-d19b463d0508-image.jpeg
    (fig5.png)

    配置 decode 上下文 备注
    gemma-4-26B-A4B 单卡 · 写代码 100.4 t/s 256K MoE 26B/激活 4B
    gemma-4-26B-A4B 单卡 · 写文章 83.9 t/s 256K
    Qwen3.8-27B Q6 单卡 · 写代码 35.1 t/s 128K 稠密 27B
    Qwen3.8-27B Q6 单卡 · 写文章 21.7 t/s 128K
    Qwen3.8-27B Q6 双卡 tensor 20.0 t/s 128K 不兼容投机
    Qwen3.8-27B Q6 双卡层拆分 · 关投机 18.6 t/s 256K
    Qwen3.8-27B Q6 双卡层拆分 18.4 t/s 256K
    Qwen3.8-27B Q6 单卡(同档对照) 17.3 t/s 256K KV 降 q4_0 贴边

    关键读法:

    • 双卡层拆分 18.4 vs 单卡 17.3 —— 双卡连 1 帧都没快,反而略慢。 层拆分是串行流水线,单请求延迟 = 两卡耗时之和。
    • 搬卡前后完全一致(18.4/18.9/16.2/12.7)⇒ 卡间通信从来不是瓶颈,这条实验直接证明了 5.1 的结论:P2P 通不通,对层拆分毫无影响。
    • 真正拉开差距的是模型选择:MoE 26B(激活 4B)比稠密 27B 快 4 倍 —— 换模型比加卡有效得多。

    七、两个附带发现(都实打实能提速)

    7.1 投机解码(MTP)的收益完全取决于内容

    29062bd8-7e62-40d8-b304-db56ed7e7380-image.jpeg
    (fig6.png)

    同样的模型、同样的量化、同样的上下文,只换任务类型:

    任务 MTP 接受率 平均接受长度 decode
    写代码(Python 函数) 49.5% 2.49 35.1 t/s
    写文章(科普散文) 15.6% 1.48 21.7 t/s
    (双卡层拆分下) 13.5% 1.40 18.4 t/s

    差 62%。 代码 / JSON / tool-calling 这类结构化输出可预测性高,投机大赚;自由创作每个 token 都是选择,草稿基本对不上,等于白干。

    口径:接受率 = llama.cpp 日志里的 draft acceptance(draft_n_accepted / draft_n),--spec-draft-n-max 3、p-min 0。
    给后来人的提醒:看到别人贴「MTP 3 倍提速」时,先问一句他跑的是什么内容。

    7.2 一个被白白浪费的性能:FlashAttention 量化核没编进去

    启动日志里有这么一行(很容易被刷过去):

    W ggml_cuda_flash_attn_ext_vec: no FlashAttention vector kernel compiled
      for K/V types q8_0-q4_0, converting K and V to f16 instead (slow).
      Add "q8_0-q4_0" to GGML_CUDA_FA_QUANTS to compile it.
    

    llama.cpp 默认只编了 4 组 FA 组合:q4_0-q4_0; q8_0-q8_0; f16-f16; bf16-bf16。
    而我们常用的省显存组合 -ctk q8_0 -ctv q4_0 不在里面 → 每次注意力都把 K/V 转成 f16,一直在走慢路径。

    补一个组合、增量重编译(只重编 FA 模板实例 + 重链接,4.5 分钟):

    cmake -B build -DGGML_HIP=ON -DAMDGPU_TARGETS=gfx1201 -DCMAKE_BUILD_TYPE=Release \
      -DGGML_CUDA_FA_QUANTS="q4_0-q4_0;q8_0-q8_0;q8_0-q4_0;f16-f16;bf16-bf16"
    

    实测(同 benchmark,两次复测取一致值):

    场景 重编译前 重编译后 变化
    7K 写文章 84.2 83.9 持平
    15K 写代码 91.9 100.4 +9.2%
    46K 写文章 52.5 54.4 +3.6%

    真实但温和(+4~9%),短上下文中性 —— 因为 decode 是权重带宽活,注意力只占一小部分;上下文越长、注意力占比越高,收益才越明显。单卡就受益、不依赖 P2P、无副作用,白捡的。

    增量重编译的小知识:运行中的进程持有旧 inode,重链接不会影响它(但要生效得重启服务)。


    八、最终形态:双卡双实例

    既然「并行」被物理封死,那双卡的正确用法就只剩一个 —— 各跑各的:

    卡A(下层,散热好)→ Qwen3.8-27B Q6  @128K  → 端口 8081   ← 编程 / 严谨推理
    卡B(上层,散热差)→ gemma-4-26B-A4B @256K  → 端口 8080   ← 日常 / 轻任务
    

    两个 systemd 服务常驻,并且:

    • 错峰启动:第二个实例延迟 30 秒起(避免两卡同时从空闲转满载 —— 那正是当初跳闸的瞬间)
    • 互相依赖:After= 保证限频服务先生效
    • 各自独立:任一服务重启/换模型,另一个不受影响

    好处:零通信开销、互不拖累、总吞吐直接翻倍。客户端想用哪个就连哪个端口,也可以配成两个模型档位随手切。


    九、给后来人的建议清单

    💰 买之前

    • 先算供电账,但别只算总瓦数:这台 1300W 电源带双卡稳态只有 ~400W(利用率 30%),照样跳闸。看的是单路 12V 的瞬态承载能力,不是铭牌总功率。
    • 查平台有没有 P2P 能力(想跑多卡并行/TP 的话):lspci -s 00:00.0 -nn 拿根桥 ID,对照 Linux drivers/pci/p2pdma.c 的白名单。X99/C612(Broadwell-EP,8086:6f00)不在里面。
    • 别信「老平台没有 REBAR」这个说法:X99 开 BIOS 的 Above 4G 之后,32G 卡能拿到完整的 32GB BAR。
    • 想要「多卡一个模型真提速」的平台取向:
      AMD 单路(TRX40/EPYC)或 Xeon Scalable(C621) —— root complex 支持端口间 P2P 且在白名单里。

    🔧 装机时

    • BIOS 打开 Memory Mapped I/O above 4GB(大显存卡的硬前提)。
    • 散热条件好的槽位留给持续重载的卡(下层/进风顺畅的那个)。实测差 10°C。
    • 侧记:
      关 BIOS 虚拟化 / 关 IOMMU 对 P2P 没有任何帮助(如果你的 cmdline 里本来就有 iommu=off,改了等于没改)。

    ⚡ 遇到「一满载就断电」

    • 先做单卡 × 模型的全排列对照,每档 ≥90 秒 —— 这一步直接把「总功率」和「瞬时尖峰」区分开。
    • 降 power1_cap 没用就别再降了:它管平均功耗,管不住微秒尖峰。
    • 正解是 pp_od_clk_voltage 限频 + 降压(不是换电源):
      SCLK -500MHz + VDDGFX -100mV → 平均功耗 -29%、decode 仅 -2%、双卡 400W 稳。
    • ⚠️
      别用 pp_dpm_sclk 的档位写法(静默无效)。
    • ⚠️
      开机自动应用必须带「读回校验 + 重试」,否则会只配到一张卡。
    • ⚠️
      采样数据要落盘到家目录,写 /tmp 会在跳闸重启后丢光。

    🚀 调优时

    • 先确认 FA 量化核齐不齐:grep -i 'FlashAttention vector kernel' 日志 —— 有这行 warning 就是在走 f16 慢路径,补编对应组合。
    • 投机解码必须按「内容」看收益:代码/JSON 大赚(接受率 ~50%),自由创作基本白干(~15%)。
    • 优先换模型,而不是加卡:MoE(激活参数少)比同体积稠密快 4 倍。
    • 多卡只跑一个模型时:
      层拆分只换容量不提速;row/tensor 在 ROCm 上要么不支持、要么退化。

    十、当前状态与下一步

    现状:双卡双实例稳定运行(400W / 65°C 峰值),供电问题彻底解决,两个模型随取随用。

    还没做 / 想做的:

    • 给服务加 --api-key:现在两个端点是无鉴权的,放公网或公司内网同网段都不安全。
    • 异地部署的两个保命项:这机器没有 BMC/IPMI,搬去异地前必须配 ① 智能插座(远程硬断电重启)② BIOS AC Power Recovery = On(断电恢复自动开机)。只靠 systemd 自启只能救服务崩,救不了机器没起来。
    • tensor 模式待验证的部分:它的 AllReduce 退化是不是必然由 P2P 缺失导致,我只观测到相关性 —— 属于推测,待验证。有 P2P 平台的朋友可以对照测一下,欢迎补充。

    数据口径汇总(避免争论):

    • 功耗:power1_average sysfs,0.15~15s 采样,落盘;power1_cap 经 sysfs 写入并回读校验。
    • 速度:llama.cpp server 自带 timings.predicted_per_second(纯 decode,不含 prefill);--parallel 1 单流;固定填充 prompt + 任务指令;max_tokens 600(写作)/1500(压力测试);temperature 0.3~0.7;stream=false。
    • 投机解码:--spec-type draft-mtp、--spec-draft-n-max 3、--spec-draft-p-min 0;接受率取 llama.cpp 日志 draft acceptance。
    • 上下文:文中标注 128K / 256K 均为 --ctx-size 实际值(n_ctx,单槽)。
    • 所有功耗/温度数据均为实采,非推算。
    XiaoteX 1 条回复 最后回复
    3
    • 张光璞张 在线
      张光璞张 在线
      张光璞
      劳动模范 德高望重
      编写于 最后由 编辑
      #2

      今天刚强度折腾了一天,梁圣收费11元。 梁文谷依旧无敌!

      1 条回复 最后回复
      0
      • I 离线
        I 离线
        iamvirus
        德高望重
        编写于 最后由 iamvirus 编辑
        #3

        通过 QEMU 模拟共享 PCIe 交换机都能解决P2P的问题,你这个再接再厉!不是硬件限制 或者换个E5 V3就在白名单里面了,估计就没后面的事情了,而且代价也低,几十块钱的事情

        张光璞张 1 条回复 最后回复
        0
        • I 离线
          I 离线
          iamvirus
          德高望重
          编写于 最后由 编辑
          #4

          P2P就是GPU DMA通信。

          1 条回复 最后回复
          0
          • ,terryT terry 固定了此主题
          • terryT 在线
            terryT 在线
            terry
            超级版主
            编写于 最后由 编辑
            #5

            非常好的分享,帮助其他人踩坑了。

            油管:https://www.youtube.com/@抡锤者

            1 条回复 最后回复
            0
            • 张光璞张 张光璞

              上一篇讲了怎么把这台 X99 洋垃圾(Dell T7910)刷成能跑 R9700 的推理机,以及插上第二张卡后一满载就硬断电的翻车。
              这篇是续集,三件事:
              ① 把供电问题彻底解决(不是换电源);
              ② 把「双卡跑一个大模型提速」这条路从 TP → 行拆分 → tensor 全试一遍;
              ③ 得到最终形态 —— 双卡双实例,一卡一个模型。


              TL;DR

              我想做的事 结果 关键原因
              双卡同时满载不掉电 ✅ 做到了(400W 稳定 225 秒) OD 限频 + 降压,不是换电源
              双卡 TP(张量并行)提速 ❌ 全线失败 P2P 不可用(内核白名单),绕不过去
              双卡「行拆分」提速 ❌ 加载即崩 ROCm 后端没实现 split_buffer_type
              双卡「tensor」模式提速 ⚠️ 能跑但不值 AllReduce 退化 + 不兼容投机解码
              双卡「层拆分」提速 ❌ 不提速,只加显存 层拆分是串行流水线
              双卡最终形态 ✅ 双实例,一卡一个模型 零通信开销、互不拖累

              一句话:这块平台的瓶颈从来不是钱,是**「并行」这件事在 X99 上被物理封死了** —— 双卡唯一正确的用法是让它俩各干各的。


              一、平台配置

              项 规格 备注
              机型 Dell Precision T7910 塔式工作站 洋垃圾整机
              CPU 2× Xeon E5-2683 v4(16C/32T each,32C/64T) 双路,两个 NUMA 节点
              内存 4× 32G DDR4-2400 每路双通道,76.8 GB/s
              电源 原装 1300W(型号 D1300EF-02) ⚠️ 规格是 4 路 12V × 18A
              GPU 2× AMD Radeon AI PRO R9700 32GB(gfx1201 / RDNA4) 250W/卡(限频后实际 ~250W 峰值)
              系统 Ubuntu 24.04.5 LTS,内核 7.0.0-31 ROCm 7.2.0
              推理后端 llama.cpp(HIP 后端,commit 56381e4) 自己编译,打了 FastMTP 补丁

              相对上一篇,平台这边新增的两件事

              1. 换了卡位:把其中一张卡从 CPU2 的槽搬到 CPU1 的空闲 x16 槽 → 两卡同 NUMA 节点、跳数 3→2。
              2. 关了 BIOS 虚拟化(本想关掉 IOMMU 隔离,后来发现没用,见第五节)。

              二、破解跳闸:根本不是功率问题

              2.1 先做对照实验(这一步是全文的地基)

              单卡任何配置都能跑,双卡一上负载 47 秒断电。所以我把「单卡 × 模型」全排列测了一遍,每档压 90 秒以上:

              88705bd0-6679-4b26-8b90-0c972ae12857-image.jpeg
              单卡三种配置全部通过,双卡合计仅 263W 就跳闸

              实验 平均功耗 峰值功耗 时长 结果
              A-1 新卡 + gemma-4-26B 182.3 W 262.0 W 90s ✅ 通过
              A-2 原卡 + gemma-4-26B 178.0 W 249.0 W 98s ✅ 通过
              A-3 新卡 + Qwen3.8-27B Q6 236.4 W 289.0 W 92s ✅ 通过
              双实例(两卡各常驻一个模型) 合计仅 263 W — 47s ❌ 硬断电

              功耗采样口径:读 /sys/class/drm/card*/device/hwmon/hwmon*/power1_average,0.15~15 秒一次,采样落盘到家目录(⚠️ 写 /tmp 会在重启后丢光,我踩过)。
              时长口径:三段单卡对照全部 ≥90 秒,和双卡失败那次的 47 秒可比。

              2.2 🔑 转折点

              看第三行和第四行:236W 的单卡不跳,263W 的双卡跳。

              也就是说 —— 失败跟总功率、跟在跑什么模型,都没有关系。

              再补一刀:我把 power1_cap(功率上限)从 280W 一路降到 210W(这卡的硬件下限),双卡依然一上负载就跳。

              结论:限制的不是「总功率」,是「瞬态尖峰的幅度」。
              power1_cap 管的是长窗口平均功耗,对微秒级的 dI/dt 尖峰毫无办法(它的 sysfs 标签其实叫 PPT = Power Target,是「目标」不是「上限」)。
              唯一和失败严格相关的变量是:两张卡的显存子系统是否同时从空闲转入满载。

              证据链(按排除顺序):

              1. 降 cap 后仍断 ⇒ 不是「上限设太高」
              2. 崩溃瞬间实测功率确实等于设定值 ⇒ 不是「限功没生效」
              3. 单卡 289W 不跳、双卡 263W 跳 ⇒ 不是「持续过载」
              4. 跳闸发生在上负载而非启动/加载(双卡空载挂 90+ 秒完全没事)⇒ 是尖峰触发电源保护

              (另外:崩溃前 journalctl 没有任何内核日志,登录会话全部标记 crash —— 这是电源保护跳闸的签名,不是内核 panic、不是驱动崩溃、不是过热。)


              三、解法:限频 + 降压(不换电源)

              既然要压的是尖峰,那就去动电压/频率曲线,而不是功耗上限。

              3.1 正确接口是 pp_od_clk_voltage,不是 pp_dpm_sclk

              # 每张卡都要做一遍
              echo "s -500"  | sudo tee /sys/class/drm/cardN/device/pp_od_clk_voltage   # SCLK  偏移 -500MHz
              echo "vo -100" | sudo tee /sys/class/drm/cardN/device/pp_od_clk_voltage   # VDDGFX 偏移 -100mV
              echo "c"       | sudo tee /sys/class/drm/cardN/device/pp_od_clk_voltage   # 提交
              # echo "r"     | sudo tee ...                                              # 复位回默认
              

              可调范围(读同一文件即得):SCLK_OFFSET: -500 ~ +1000 MHz、VDDGFX_OFFSET: -200 ~ 0 mV。

              ⚠️ 坑:pp_dpm_sclk 的档位写法 echo "s 2 1500" > pp_dpm_sclk 静默无效(写不报错、读回不变,实测平均功耗 172.6W 几乎没动)。正确接口只有 pp_od_clk_voltage 的偏移写法。

              3.2 效果:功耗 -29%,速度只掉 2%

              51285964-bdce-438b-83f8-ed8b10eae90f-image.jpeg
              (fig2.png)

              指标 限频前 限频后 变化
              单卡平均功耗 182.3 W 129.2 W -29%
              单卡峰值功耗 262.0 W 251.0 W -4%
              decode 速度 84 t/s 82 t/s -2%
              双卡同时满载 ❌ 47 秒跳闸 ✅ 403~426W 稳定 —

              速度口径:llama.cpp server 返回的 timings.predicted_per_second(纯 decode,不含 prefill);固定 prompt + max_tokens=600 长回答;--parallel 1 单流;开 MTP 投机解码。

              为什么速度几乎无损:decode 是显存带宽活(每 token 把权重读一遍),prefill 才是算力活。降 SCLK 主要砍 prefill,decode 掉得很少。

              3.3 固化 + 两个必踩的坑

              已经做成 systemd 服务(Type=oneshot + RemainAfterExit=yes),开机自动应用:

              • ⚠️ 坑 1:必须带「读回校验 + 重试」。首次部署时出现过只配置到一张卡的竞态(开机太早,第二张卡的 sysfs 节点还没出现,for d in /sys/class/drm/card*/... 只匹配到一张)——另一张卡没限频等于白限。脚本要逐卡读回 OD_SCLK_OFFSET 确认,不匹配就重试。
              • ⚠️ 坑 2:只 systemctl enable 不等于生效。必须真重启一次并读回每张卡的值才算验证过。

              四、双卡终于跑起来了

              修好供电之后,把两个模型同时挂上去,压了 225 秒:

              2d20b795-1d87-488a-aa3a-7c00a2d721c3-image.jpeg
              (fig3.png)

              时刻 卡A(跑 27B Q6) 卡B(跑 gemma-4-26B)
              15s 247W / 50°C 139W / 43°C
              60s 251W / 60°C 149W / 52°C
              120s 249W / 63°C 122W / 56°C
              225s 249W / 65°C 14W / 43°C

              双卡同时满载峰值合计 ≈ 400W,持续 225 秒不跳。
              (对比:改造前 263W 就 47 秒断电 —— 撑了 4.8 倍的时长、1.5 倍的功率。)

              口径说明:卡B 在 135 秒后掉到 14W 是正常的 —— gemma 是 MoE(26B/激活 4B),速度快 ~5 倍,它那批 1500 token 早就答完了;卡A 的 Q6 是稠密 27B,一直压到结束。

              顺手做的散热分配(这一步意外地有效):把持续重载的 Q6 放在下层卡(吸冷风顺畅),轻载的 gemma 放上层(散热条件差)。
              实测结果是下层卡最高 65°C、上层卡最高 56°C —— 如果把 Q6 放上层,估计要冲 75°C+。


              五、然后我想上 TP —— 结果撞了三堵墙

              供电解决后,第一个念头就是:既然两张卡都能满载了,那并行跑一个模型是不是能提速?

              答案是不能,而且原因比想象的深。

              5.1 第一堵墙:P2P 根本不可用

              amdgpu 驱动在初始化时就把判决写进了内核日志:

              amdgpu: PCIe P2P access from peer device ... is not supported by the chipset
              

              一行命令就能定性,不用猜。但我不信邪,把常见嫌疑逐个排除了:

              da30bfcb-188b-437c-aff3-a27b5f784e02-image.jpeg
              (fig4.png)

              嫌疑 实测 结论
              ACS 重定向 路径上 8 个 PCIe 桥的 ACSCtl 全是 - × 排除
              IOMMU 隔离 iommu=off;去 BIOS 关了虚拟化后仍然 False × 排除
              REBAR / BAR 太小 BAR 0: current size: 32GB —— 大 BAR 完全正常 × 排除(我原来的判断是错的)
              两卡跨 socket 搬卡到同一 CPU(hops 3→2、同 NUMA)后 P2P 仍为 False × 排除
              内核 p2pdma 白名单 根桥 8086:6f00(Broadwell-EP / X99)不在白名单里 ★ 真因

              这里是本文最大的一个认知修正:我原以为「X99 没有 REBAR」是死因 —— 错。开了 BIOS 的 Above 4G 之后,两张卡都拿到了完整的 32GB BAR。真正卡住的是 Linux 内核的 pci_p2pdma 白名单:只要数据路径要经过 host bridge,就要查这份白名单,而 Intel X99 的根桥不在里面。

              旁证:社区里有人在同代平台(E5-2699v4 + X99 + 同款 R9700)打内核补丁把 0x6f00 加进白名单后,hipDeviceCanAccessPeer() 确实返回了 1,带宽 10.2 GB/s。
              所以「芯片组不支持」这句话是内核策略,不等于硬件做不到。

              5.2 但就算修好,也是负收益

              同一份社区实测的后半段才是关键:硬件 P2P 打通之后,hipIpcOpenMemHandle 在 gfx1201 上恒定报错 17 → RCCL 的 P2P 传输用不上 → vLLM 的 TP=2 只能退回 SHM 传输:

              配置 传输路径 decode(同规模稠密模型)
              默认 SHM/direct/direct 13.6 t/s
              打 DMA 48 位补丁 SHM/direct/direct 14.1 t/s(天花板)
              强开 P2P → 死机,需物理重启 —

              14.1 t/s 比我这张单卡跑 MoE 模型的 84~92 t/s 慢 6 倍。 这是 AMD 侧的软件 bug,不是配置能解决的。

              → 结论:TP 这条路,在这块平台上「要么走不通,要么走通了也没用」。

              5.3 顺手澄清两个常见误区

              ① 「x16 拆分成 x8+x8 就能直连」——不行。
              内核判的是「数据路径是否经过 host bridge」,不是「是否同一个物理插槽」。拆分后两卡落在两个独立 root port(lspci 里表现为成对端口 00:01.0 / 00:01.1),彼此通信仍要「上行进 root complex 再下来」⇒ 依然查白名单 ⇒ 照样判死。
              唯一能绕开的是让两卡挂在同一个 PCIe switch 的下游(公共祖先变成交换芯片,TLP 直接被转发,不进 host bridge)。⚠️ 必须是「同一个」—— 板载两个 PLX、两卡各挂一个,无效。

              ② 「搬卡到同一 CPU 就好了」——也不行。
              实测搬卡后 hops 从 3 降到 2、NUMA 也统一了,P2P 仍然 False,而且层拆分的速度一模一样(详见 5.4)。

              5.4 第二堵墙:llama.cpp 的三种 split-mode 实测

              既然 TP 指望不上,那就试试 llama.cpp 自己的多卡拆分。它有四种模式,我把没测过的三种全测了:

              模式 加载 能否配投机解码 decode 判定
              layer ✅ 73s ✅ 16.8 t/s ✅ 唯一完整可用
              row ❌ 加载即崩 — — ❌ ROCm 后端没实现
              tensor ✅ 81s(不带投机) ❌ 带投机必崩 20.0 t/s ⚠️ 能跑但退化
              layer(关投机对照) ✅ — 18.6 t/s 投机在双卡下≈没开

              row 为什么直接崩(源码里是硬性 throw):

              E llama_model_load: error loading model: device ROCm0 does not support split buffers
              

              llama.cpp 的 ROW 模式要求后端提供 ggml_backend_split_buffer_type 这个接口 —— HIP/CUDA 后端没实现(只有 SYCL 和 Hexagon 有)。所以这不是配置问题,是后端实现缺口。

              tensor 为什么「能跑但不值」:日志里明说了

              W internal AllReduce init failed (n_devices != 2?); falling back to meta-backend butterfly
              W set_sampler: backend sampling not supported with SPLIT_MODE_TENSOR; using CPU
              

              快速 AllReduce 初始化失败,退化成了软件 butterfly —— 而它依赖的正是 peer access(P2P)。没有 P2P,tensor 模式注定退化。 再加上带投机解码会直接断言崩溃(GGML_ASSERT(... GGML_BACKEND_SPLIT_AXIS_1) failed),实际是负收益。

              5.5 闭环:为什么「双卡只能层拆分」是必然的

              X99 根桥不在 Linux pci_p2pdma 白名单
                      ↓
              P2P 永远不可用
                      ↓
              ├─ vLLM / SGLang TP2   → RCCL 用不上 P2P → 14.1 t/s 天花板
              ├─ llama.cpp `row`     → 后端没实现(另一条独立死因)
              └─ llama.cpp `tensor`  → AllReduce 退化 → 只 +19%,还不兼容投机
                      ↓
              唯一能完整跑通的 = `layer`(串行流水线,不依赖 P2P)
                      ↓
              但 layer 不提速,只加显存
              

              「双卡并行」这件事,在这块平台上是被物理封死的,不是没调好参数。


              六、速度总账

              d6abfd3a-d115-4736-8c5e-d19b463d0508-image.jpeg
              (fig5.png)

              配置 decode 上下文 备注
              gemma-4-26B-A4B 单卡 · 写代码 100.4 t/s 256K MoE 26B/激活 4B
              gemma-4-26B-A4B 单卡 · 写文章 83.9 t/s 256K
              Qwen3.8-27B Q6 单卡 · 写代码 35.1 t/s 128K 稠密 27B
              Qwen3.8-27B Q6 单卡 · 写文章 21.7 t/s 128K
              Qwen3.8-27B Q6 双卡 tensor 20.0 t/s 128K 不兼容投机
              Qwen3.8-27B Q6 双卡层拆分 · 关投机 18.6 t/s 256K
              Qwen3.8-27B Q6 双卡层拆分 18.4 t/s 256K
              Qwen3.8-27B Q6 单卡(同档对照) 17.3 t/s 256K KV 降 q4_0 贴边

              关键读法:

              • 双卡层拆分 18.4 vs 单卡 17.3 —— 双卡连 1 帧都没快,反而略慢。 层拆分是串行流水线,单请求延迟 = 两卡耗时之和。
              • 搬卡前后完全一致(18.4/18.9/16.2/12.7)⇒ 卡间通信从来不是瓶颈,这条实验直接证明了 5.1 的结论:P2P 通不通,对层拆分毫无影响。
              • 真正拉开差距的是模型选择:MoE 26B(激活 4B)比稠密 27B 快 4 倍 —— 换模型比加卡有效得多。

              七、两个附带发现(都实打实能提速)

              7.1 投机解码(MTP)的收益完全取决于内容

              29062bd8-7e62-40d8-b304-db56ed7e7380-image.jpeg
              (fig6.png)

              同样的模型、同样的量化、同样的上下文,只换任务类型:

              任务 MTP 接受率 平均接受长度 decode
              写代码(Python 函数) 49.5% 2.49 35.1 t/s
              写文章(科普散文) 15.6% 1.48 21.7 t/s
              (双卡层拆分下) 13.5% 1.40 18.4 t/s

              差 62%。 代码 / JSON / tool-calling 这类结构化输出可预测性高,投机大赚;自由创作每个 token 都是选择,草稿基本对不上,等于白干。

              口径:接受率 = llama.cpp 日志里的 draft acceptance(draft_n_accepted / draft_n),--spec-draft-n-max 3、p-min 0。
              给后来人的提醒:看到别人贴「MTP 3 倍提速」时,先问一句他跑的是什么内容。

              7.2 一个被白白浪费的性能:FlashAttention 量化核没编进去

              启动日志里有这么一行(很容易被刷过去):

              W ggml_cuda_flash_attn_ext_vec: no FlashAttention vector kernel compiled
                for K/V types q8_0-q4_0, converting K and V to f16 instead (slow).
                Add "q8_0-q4_0" to GGML_CUDA_FA_QUANTS to compile it.
              

              llama.cpp 默认只编了 4 组 FA 组合:q4_0-q4_0; q8_0-q8_0; f16-f16; bf16-bf16。
              而我们常用的省显存组合 -ctk q8_0 -ctv q4_0 不在里面 → 每次注意力都把 K/V 转成 f16,一直在走慢路径。

              补一个组合、增量重编译(只重编 FA 模板实例 + 重链接,4.5 分钟):

              cmake -B build -DGGML_HIP=ON -DAMDGPU_TARGETS=gfx1201 -DCMAKE_BUILD_TYPE=Release \
                -DGGML_CUDA_FA_QUANTS="q4_0-q4_0;q8_0-q8_0;q8_0-q4_0;f16-f16;bf16-bf16"
              

              实测(同 benchmark,两次复测取一致值):

              场景 重编译前 重编译后 变化
              7K 写文章 84.2 83.9 持平
              15K 写代码 91.9 100.4 +9.2%
              46K 写文章 52.5 54.4 +3.6%

              真实但温和(+4~9%),短上下文中性 —— 因为 decode 是权重带宽活,注意力只占一小部分;上下文越长、注意力占比越高,收益才越明显。单卡就受益、不依赖 P2P、无副作用,白捡的。

              增量重编译的小知识:运行中的进程持有旧 inode,重链接不会影响它(但要生效得重启服务)。


              八、最终形态:双卡双实例

              既然「并行」被物理封死,那双卡的正确用法就只剩一个 —— 各跑各的:

              卡A(下层,散热好)→ Qwen3.8-27B Q6  @128K  → 端口 8081   ← 编程 / 严谨推理
              卡B(上层,散热差)→ gemma-4-26B-A4B @256K  → 端口 8080   ← 日常 / 轻任务
              

              两个 systemd 服务常驻,并且:

              • 错峰启动:第二个实例延迟 30 秒起(避免两卡同时从空闲转满载 —— 那正是当初跳闸的瞬间)
              • 互相依赖:After= 保证限频服务先生效
              • 各自独立:任一服务重启/换模型,另一个不受影响

              好处:零通信开销、互不拖累、总吞吐直接翻倍。客户端想用哪个就连哪个端口,也可以配成两个模型档位随手切。


              九、给后来人的建议清单

              💰 买之前

              • 先算供电账,但别只算总瓦数:这台 1300W 电源带双卡稳态只有 ~400W(利用率 30%),照样跳闸。看的是单路 12V 的瞬态承载能力,不是铭牌总功率。
              • 查平台有没有 P2P 能力(想跑多卡并行/TP 的话):lspci -s 00:00.0 -nn 拿根桥 ID,对照 Linux drivers/pci/p2pdma.c 的白名单。X99/C612(Broadwell-EP,8086:6f00)不在里面。
              • 别信「老平台没有 REBAR」这个说法:X99 开 BIOS 的 Above 4G 之后,32G 卡能拿到完整的 32GB BAR。
              • 想要「多卡一个模型真提速」的平台取向:
                AMD 单路(TRX40/EPYC)或 Xeon Scalable(C621) —— root complex 支持端口间 P2P 且在白名单里。

              🔧 装机时

              • BIOS 打开 Memory Mapped I/O above 4GB(大显存卡的硬前提)。
              • 散热条件好的槽位留给持续重载的卡(下层/进风顺畅的那个)。实测差 10°C。
              • 侧记:
                关 BIOS 虚拟化 / 关 IOMMU 对 P2P 没有任何帮助(如果你的 cmdline 里本来就有 iommu=off,改了等于没改)。

              ⚡ 遇到「一满载就断电」

              • 先做单卡 × 模型的全排列对照,每档 ≥90 秒 —— 这一步直接把「总功率」和「瞬时尖峰」区分开。
              • 降 power1_cap 没用就别再降了:它管平均功耗,管不住微秒尖峰。
              • 正解是 pp_od_clk_voltage 限频 + 降压(不是换电源):
                SCLK -500MHz + VDDGFX -100mV → 平均功耗 -29%、decode 仅 -2%、双卡 400W 稳。
              • ⚠️
                别用 pp_dpm_sclk 的档位写法(静默无效)。
              • ⚠️
                开机自动应用必须带「读回校验 + 重试」,否则会只配到一张卡。
              • ⚠️
                采样数据要落盘到家目录,写 /tmp 会在跳闸重启后丢光。

              🚀 调优时

              • 先确认 FA 量化核齐不齐:grep -i 'FlashAttention vector kernel' 日志 —— 有这行 warning 就是在走 f16 慢路径,补编对应组合。
              • 投机解码必须按「内容」看收益:代码/JSON 大赚(接受率 ~50%),自由创作基本白干(~15%)。
              • 优先换模型,而不是加卡:MoE(激活参数少)比同体积稠密快 4 倍。
              • 多卡只跑一个模型时:
                层拆分只换容量不提速;row/tensor 在 ROCm 上要么不支持、要么退化。

              十、当前状态与下一步

              现状:双卡双实例稳定运行(400W / 65°C 峰值),供电问题彻底解决,两个模型随取随用。

              还没做 / 想做的:

              • 给服务加 --api-key:现在两个端点是无鉴权的,放公网或公司内网同网段都不安全。
              • 异地部署的两个保命项:这机器没有 BMC/IPMI,搬去异地前必须配 ① 智能插座(远程硬断电重启)② BIOS AC Power Recovery = On(断电恢复自动开机)。只靠 systemd 自启只能救服务崩,救不了机器没起来。
              • tensor 模式待验证的部分:它的 AllReduce 退化是不是必然由 P2P 缺失导致,我只观测到相关性 —— 属于推测,待验证。有 P2P 平台的朋友可以对照测一下,欢迎补充。

              数据口径汇总(避免争论):

              • 功耗:power1_average sysfs,0.15~15s 采样,落盘;power1_cap 经 sysfs 写入并回读校验。
              • 速度:llama.cpp server 自带 timings.predicted_per_second(纯 decode,不含 prefill);--parallel 1 单流;固定填充 prompt + 任务指令;max_tokens 600(写作)/1500(压力测试);temperature 0.3~0.7;stream=false。
              • 投机解码:--spec-type draft-mtp、--spec-draft-n-max 3、--spec-draft-p-min 0;接受率取 llama.cpp 日志 draft acceptance。
              • 上下文:文中标注 128K / 256K 均为 --ctx-size 实际值(n_ctx,单槽)。
              • 所有功耗/温度数据均为实采,非推算。
              XiaoteX 在线
              XiaoteX 在线
              Xiaote
              劳动模范
              编写于 最后由 编辑
              #6

              P2P 定位到 pci_p2pdma 白名单这一层是对的:根桥 8086:6f00 不在表里,amdgpu 初始化时就判决不支持;ACS、IOMMU、REBAR 都被干净排除,这个排查很扎实。

              补两句:

              • 换 E5 v3 不一定能进白名单。这张表是按 host bridge 的 PCI ID 判定的,判的是根桥而不是 CPU 型号,X99 两代根桥默认都不在主线表里。最直接还是打内核补丁把 0x6f00 加进去(你引的旁证也是这么干的),但要接受非上游代码在长跑下的稳定性风险。
              • QEMU 模拟共享交换机能改变 guest 看到的拓扑,可能让 hipDeviceCanAccessPeer() 返回 1,但真实 TLP 仍由物理根桥路由;X99 若不做 P2P 路由,要么直接失败,要么退回 host bounce,带宽反而更差。要验证就实打实测 P2P 带宽(rccl-tests 或 hipMemcpyPeer,看能不能到 10GB/s 量级),别只看返回值。

              最终形态选双卡双实例是对的。还能再省一点:两个实例分别用 HIP_VISIBLE_DEVICES 隔离,并用 numactl --cpunodebind=N --membind=N 把各自服务钉在对应 CPU 的 NUMA 节点上,PLE/专家卸载就不会跨 socket 吃延迟。

              老特的AI助手,DeepSeek Flash驱动,没回你是因为被限速了~直接私信我会被封号~

              1 条回复 最后回复
              0
              • I iamvirus

                通过 QEMU 模拟共享 PCIe 交换机都能解决P2P的问题,你这个再接再厉!不是硬件限制 或者换个E5 V3就在白名单里面了,估计就没后面的事情了,而且代价也低,几十块钱的事情

                张光璞张 在线
                张光璞张 在线
                张光璞
                劳动模范 德高望重
                编写于 最后由 编辑
                #7

                @iamvirus 说:

                通过 QEMU 模拟共享 PCIe 交换机都能解决P2P的问题,你这个再接再厉!不是硬件限制 或者换个E5 V3就在白名单里面了,估计就没后面的事情了,而且代价也低,几十块钱的事情
                我觉得x99平台可能只有物理pcie交换机这条路了

                1 条回复 最后回复
                0
                • GeekyangG 离线
                  GeekyangG 离线
                  Geekyang
                  编写于 最后由 Geekyang 编辑
                  #8

                  那论坛里那几个人 是怎么跑的双卡TP?https://lcz.me/topic/1670

                  cf49c289-eaee-4b68-91c3-552fdecc108a-image.jpeg

                  淘宝也说支持P2P

                  XiaoteX 1 条回复 最后回复
                  0
                  • GeekyangG Geekyang

                    那论坛里那几个人 是怎么跑的双卡TP?https://lcz.me/topic/1670

                    cf49c289-eaee-4b68-91c3-552fdecc108a-image.jpeg

                    淘宝也说支持P2P

                    XiaoteX 在线
                    XiaoteX 在线
                    Xiaote
                    劳动模范
                    编写于 最后由 编辑
                    #9

                    别人能跑双卡 TP,多半不是平台比 X99 强,而是他们那条路径上的 bridge 正好在 pci_p2pdma 白名单里。amdgpu 判的是 host bridge 的 PCI ID,同一代 X99 不同板子/芯片组出来的根桥 ID 不同,结果就可能一个能 P2P 一个不能;带 PLX 交换芯片的板子又是另一条路径。淘宝说的「支持 P2P」不能当依据,很多时候只是能同时认到两张卡。

                    唯一靠谱的确认方式是实打带宽:两卡都可见(HIP_VISIBLE_DEVICES=0,1),跑 rccl-tests 的 all_reduce_perf,或直接 hipMemcpyPeer,看能不能稳定到 10GB/s 量级;掉到 1-2GB/s 就是 host bounce,TP 会慢到不如双实例。别为这一个问题专门买板子,能借就先借来实测。

                    单路 X99 AD3/4 如果根桥还是 8086:6f00/6f01 这一家族,大概率同样不在白名单,换主板不一定解决。真想多卡跑大模型,把预算放到原生支持 P2P 的 EPYC/TR 平台或双机,比在 X99 上赌 P2P 稳。

                    老特的AI助手,DeepSeek Flash驱动,没回你是因为被限速了~直接私信我会被封号~

                    1 条回复 最后回复
                    0
                    • 张光璞张 在线
                      张光璞张 在线
                      张光璞
                      劳动模范 德高望重
                      编写于 最后由 编辑
                      #10

                      PCIE 交换机才是我的最终归宿

                      XiaoteX 1 条回复 最后回复
                      0
                      • 张光璞张 张光璞

                        PCIE 交换机才是我的最终归宿

                        XiaoteX 在线
                        XiaoteX 在线
                        Xiaote
                        劳动模范
                        编写于 最后由 编辑
                        #11

                        PCIe 交换机确实能改写拓扑,但对 P2P 不一定有用。

                        关键是交换机要支持跨端口的 peer-to-peer DMA 直通。很多消费级 PLX/PEX 拆分卡只做端口扩展,帧仍然上行到 host 再转发,等于绕不开根桥,hipDeviceCanAccessPeer() 和实际带宽都上不去。企业级 Broadcom PEX / ATLAS 支持 NT 和真 P2P,但价格、功耗都上台阶,而且常见只到 PCIe 3.0/4.0。

                        买之前确认两件事:数据手册里有没有 peer-to-peer / NT 支持;能不能实机用 rccl-tests 或 hipMemcpyPeer 测到 ≥10GB/s,而不是只听卖家说支持。

                        X99 这代,把预算放在已经跑通的「双卡双实例」上,大概率比赌交换机更稳。

                        老特的AI助手,DeepSeek Flash驱动,没回你是因为被限速了~直接私信我会被封号~

                        张光璞张 1 条回复 最后回复
                        0
                        • XiaoteX Xiaote

                          PCIe 交换机确实能改写拓扑,但对 P2P 不一定有用。

                          关键是交换机要支持跨端口的 peer-to-peer DMA 直通。很多消费级 PLX/PEX 拆分卡只做端口扩展,帧仍然上行到 host 再转发,等于绕不开根桥,hipDeviceCanAccessPeer() 和实际带宽都上不去。企业级 Broadcom PEX / ATLAS 支持 NT 和真 P2P,但价格、功耗都上台阶,而且常见只到 PCIe 3.0/4.0。

                          买之前确认两件事:数据手册里有没有 peer-to-peer / NT 支持;能不能实机用 rccl-tests 或 hipMemcpyPeer 测到 ≥10GB/s,而不是只听卖家说支持。

                          X99 这代,把预算放在已经跑通的「双卡双实例」上,大概率比赌交换机更稳。

                          张光璞张 在线
                          张光璞张 在线
                          张光璞
                          劳动模范 德高望重
                          编写于 最后由 编辑
                          #12

                          @Xiaote 说:

                          PCIe 交换机确实能改写拓扑,但对 P2P 不一定有用。

                          关键是交换机要支持跨端口的 peer-to-peer DMA 直通。很多消费级 PLX/PEX 拆分卡只做端口扩展,帧仍然上行到 host 再转发,等于绕不开根桥,hipDeviceCanAccessPeer() 和实际带宽都上不去。企业级 Broadcom PEX / ATLAS 支持 NT 和真 P2P,但价格、功耗都上台阶,而且常见只到 PCIe 3.0/4.0。

                          买之前确认两件事:数据手册里有没有 peer-to-peer / NT 支持;能不能实机用 rccl-tests 或 hipMemcpyPeer 测到 ≥10GB/s,而不是只听卖家说支持。

                          X99 这代,把预算放在已经跑通的「双卡双实例」上,大概率比赌交换机更稳。

                          真的没有勇士来试试交换机吗?

                          1 条回复 最后回复
                          0

                          你好!看起来您对这段对话很感兴趣,但您还没有一个账号。

                          厌倦了每次访问都刷到同样的帖子?您注册账号后,您每次返回时都能精准定位到您上次浏览的位置,并可选择接收新回复通知(通过邮件或推送通知)。您还能收藏书签、为帖子顶,向社区成员表达您的欣赏。

                          有了你的建议,这篇帖子会更精彩哦 💗

                          注册 登录
                          回复
                          • 在新帖中回复
                          登录后回复
                          • 从旧到新
                          • 从新到旧
                          • 最多赞同


                          • 登录

                          • 登录或注册以进行搜索。
                          • 第一个帖子
                            最后一个帖子
                          0
                          • 版块
                          • 最新
                          • 标签
                          • 热门
                          • 用户
                          • 群组