四块32GB BAR塞进PCIe Switch:Linux内核模块让P2P性能翻倍
原创四块32GB BAR塞进PCIe Switch:Linux内核模块让P2P性能翻倍
背景:为什么需要四块32GB BAR?
我在组装一台GPU服务器时碰到一个怪问题。四块AMD Radeon AI PRO R9700和两块RTX 3090,全插在Broadcom PEX88096 PCIe switch后面,机器就是起不来。来源:doug.sh 这个switch插在主板的x16槽上,给每张卡8条PCIe lane,卡与卡之间可以直接复制数据,不用经过CPU。这正是我做张量并行推理想要的,AMD ROCm把这种直接通信叫P2P,但只在每张卡整个32 GB都被映射时才启用。我要的其实很简单,给每张卡一个完整的32 GB Resizable BAR。来源:doug.sh
Resizable BAR是BIOS选项,让卡的BAR,也就是CPU物理地址空间里映射到卡内存的那个范围,从默认的256 MB扩展到完整的32 GB。听起来是个小开关,但我试过之后发现,这条路每一步都有坑。来源:doug.sh
为什么非要32 GB?因为ROCm的P2P检测机制要求完整映射,缺一不可。四块卡,每块都要32 GB,少一块都不行。我在HN上说过,我需要四块R9700之间的P2P来做tensor parallel serving,这意味着每张卡都得有32 GB BAR。这是硬需求,不是优化偏好。来源:HN
两重阻碍:BIOS映射失败与Linux窗口分配bug
第一道坎在BIOS。六张卡全插上之后,主板POST卡在白色VGA灯。原因不复杂,每块32 GB BAR在BIOS的地址空间里要占64 GB,因为对齐和保留的关系。四块卡就是256 GB,再加上两块3090的BAR,BIOS那点地址空间根本装不下。而这块主板的BIOS又没有每卡独立的Resizable BAR设置,我想选择性开都做不到。来源:doug.sh
那就让Linux来分配。Linux 7.0下,我的计划是先手动把每块R9700的BAR size寄存器设为32 GB,再移除CPU端口让内核重新扫描,这样内核会从新尺寸出发,重新布局整个switch。但Linux 7.0的bridge window sizing有个bug,报错"can't assign; no space"。内核给switch分配了大约128.6 GB的窗口,可按照Linux的布局方式,四块卡的32 GB BAR加doorbell BAR,总跨度要224 GB。最后只有两块R9700拿到了BAR,剩下的卡什么都没分到。来源:doug.sh
我判断,Linux对switch下游窗口的分配逻辑太保守,没有为32 GB BAR预留足够的空间。doorbell BAR是另一个问题。每块卡的32 GB BAR后面跟一个doorbell BAR,让驱动写寄存器通知卡有新工作。开Resizable BAR时BIOS会把它设为256 MB,Linux却只留2 MB,这又进一步挤压了空间。来源:doug.sh
破解之道:内核模块gpu-rebar-layout
既然内核和BIOS都靠不住,我干脆写了一个内核模块gpu-rebar-layout,在GitHub开源。它调用内核内部API,直接重排switch后面的BAR布局。关键流程是resize加rescan,但有个细节必须注意,必须关闭padding,也就是pad=0,否则布局还是对不齐。来源:doug.sh
模块的resize和rescan流程,配合邮件列表上那个修复sizing bug的补丁系列,才是完整方案。补丁修了内核的分配算法,但光靠它还不够,这块主板仍然需要模块做resize和rescan,而且pad=0不能少。我在HN上确认过,模块确实有效。六张卡全插时BIOS映射不了,Linux窗口太小,只有两块卡拿到BAR,模块绕过了这两个问题。来源:HN
这个模块有个先天弱点,它依赖内核内部实现细节,任何版本更新都可能让它失效。我自己在文章里提醒过,加载前先读README。这不算优雅,但在这个BIOS不给独立BAR设置、内核sizing又保守的世界上,它是我能想到的最实际的办法。来源:doug.sh
性能收益与权衡:P2P让prefill翻倍
收益是实打实的。我实测过,关掉P2P时prefill速度只有开P2P时的一半左右。对张量并行推理来说,prefill是瓶颈阶段,这个2倍加速值得折腾。数字是从我自己机器上跑出来的。来源:HN
代价也不小。每块32 GB BAR实际占用64 GB地址空间,四块卡就是256 GB,BIOS和Linux都得留出这么多空间。如果你不需要P2P,用默认的256 MB BAR就能避开所有麻烦,但卡与卡之间就没法直接复制了,所有数据都要绕道CPU。来源:doug.sh
这个方案有明确的适用场景。它针对的是多GPU推理服务器,尤其是要做张量并行的场景。你要是只跑单卡训练或不需要卡间直接通信,就别碰这个模块,不值得。但如果你真的需要四块卡之间的P2P,那这个模块可能是目前最靠谱的路径。来源:HN
原文:
Fitting Four 32 GB Resizable Bars Behind a PCIe Switch on Linux · 来源:Hacker News
参考来源:
作者:itfan123 值班编辑 · 发布于 2026年11月12日
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123




