在做具体操作之前我们来了解下ACS,ACS是指PCI访问控制服务(PCI Access Control Service),是一种在启用VT-d(I/O虚拟化技术)时用于控制PCI设备访问权限的机制,属于BIOS芯片组配置中的选项,用于限制不同PCI设备之间的直接通信,防止未授权访问。
我们看到上述介绍以后了解到P2P流量会有限制需要绕行Root Complex,GPU之间无法直接通信且RDMA网卡与GPU之间也无法通过网卡与 GPU 之间无法直接通过GDR通信。
1.关闭ACS优势
我们在GPU场景下关闭ACS以后具有以下优势P2P通信带宽提升5-15%
虚拟化延迟降低5-15%
NCCL_ALLREDUCE性能提升:
- 小消息(8KB-1MB):提升3-8%
- 大消息(>100MB):提升1-3%
虚拟化GPU性能提升:
- TensorFlow训练:加速2-7%
- CUDA内核启动延迟:减少5-15%
- VRAM访问延迟:改善3-10%
DMA事务延迟:降低10-20%但是我们在关闭ACS前还是需要建议做些充分的测试,确保应用兼容性和进行对应的风险评估
2.查询ACS是否开启
我可以使用命令查询当前ACS是否开启lspci -vvv | grep -i "acsctl"
可以看到我返回的都是SrcValid-,说明当前环境已经关闭了ACS
ACSCtl: SrcValid- TransBlk- ReqRedir- CmpltRedir- UpstreamFwd- EgressCtrl- DirectTrans-如果没有关闭会显示SrcValid+
3.如何关闭ACS
接下来我们就看看如何关闭ACS,关闭ACS需要我们做几块地方,不同的平台可能有一些不同,下面就是我收集整理的关闭ACS的方法,如果没有bios权限可以使用3.3的方法,但是不能确保成功。3.1.BIOS中关闭ACS
在所有方法中还是最推荐在bios里面进行修改,这样避免侵入设备配置空间,导致错误修改,或者修改了不该修改的地方导致不稳定的情况出现。
进入bios,一般在高级->主板配置->北桥->IIO配置->VT-d->ACS控制器,然后选择Disable3.2.内核参数绕过
这种配置有局限性,主要是在/etc/default/grub文件添加iommu=pt然后整个grub中相关配置如下
GRUB_CMDLINE_LINUX="iommu=pt"然后更新grub并重启
sudo update-grub3.3.使用setpci修改
修改PCI设备的配置空间寄存器,包括ACS能力寄存器,修改后重启失效
读取当前值
sudo setpci -s <PCI地址> <ACS能力寄存器偏移>.w写入新值
sudo setpci -s <PCI地址> <ACS能力寄存器偏移>.w=<新值>我们可以使用脚本进行遍历修改
lspci -nn | grep -iE "nvidia|gpu" | awk '{print $1}' | while read -r bus; do
echo ">>> 处理 GPU: $bus"
pos=0x100 # 扩展能力起始位置
found=0
while (( pos < 0x1000 )); do
# 读取 16 位能力 ID
cap_id_hex=$(setpci -s "$bus" $(printf "0x%x" $pos).w 2>/dev/null)
if [ -z "$cap_id_hex" ]; then
break
fi
cap_id=$(( 16#$cap_id_hex & 0xFFFF ))
# 读取下一个能力指针(偏移 +2,16 位,但按字节计算需乘注意事项)
# 实际扩展能力头格式:能力 ID (2B) + 能力版本+下一能力指针 (2B)
# 其中下一能力指针是 12 位?不对,标准是 16 位中的低 12 位是偏移,高 4 位是版本。
# 简便方法:直接读取下一能力指针的原始 16 位值,然后取低 12 位(实际偏移 = 值 & 0xFFF)
next_ptr_hex=$(setpci -s "$bus" $(printf "0x%x" $((pos+2))).w 2>/dev/null)
if [ -z "$next_ptr_hex" ]; then
break
fi
next_ptr=$(( 16#$next_ptr_hex ))
next_off=$(( next_ptr & 0xFFF )) # 低 12 位是下一能力偏移
if (( cap_id == 0x000D )); then
echo "找到 ACS 能力: $bus @ 0x$(printf %x $pos)"
# ACS 控制寄存器在能力偏移 + 0x06,16 位宽
ctrl_off=$((pos + 0x06))
setpci -s "$bus" $(printf "0x%x" $ctrl_off).w=0x0000
if [ $? -eq 0 ]; then
echo "$bus : ACS 禁用成功!"
else
echo "$bus : ACS 禁用失败"
fi
found=1
break
fi
if (( next_off == 0 )) || (( next_off <= pos )); then
break
fi
pos=$next_off
done
if (( found == 0 )); then
echo "$bus : 未找到 ACS 能力(可能不支持)"
fi
done另外需要注意以下设备不要进行修改,避免引起系统或和硬件不稳定
1.PCIe根端口/桥接器
2.系统芯片组设备
3.USB/SATA控制器
内容版权声明:除非注明,否则皆为本站原创文章。
转载注明出处:https://sulao.cn/post/1163
评论列表