最佳实践
场景一:首次使用 - 单机多卡通信
问题: "我刚配置了多卡环境,想验证 MCCL 是否正常工作"
解决步骤:
# 1. 确认 MCCL 安装
export LD_LIBRARY_PATH=/usr/local/musa/lib:$LD_LIBRARY_PATH
/usr/local/musa/bin/mccl_version
# 2. 单机验证
cd mccl/mccl-test/
./all_reduce_perf -b 1M -e 1024M -f 2 -g 1
# 3. 多卡验证(8 卡)
./all_reduce_perf -b 1M -e 1024M -f 2 -g 8
预期结果: 输出带宽和延迟数据,验证多卡通信正常
场景二:多机分布式训练
问题: "需要在多台服务器上进行分布式训练"
解决步骤:
# 1. 配置 hostfile
# openmpi 配置文件
cat > hostfile_with_openmpi << EOF
node1_ip slots=4
node2_ip slots=4
EOF
# 2. 多机验证
mpirun --allow-run-as-root \
--mca btl_tcp_if_include bond0 \
-hostfile ./hostfile_with_openmpi \
-x LD_LIBRARY_PATH=/usr/local/musa/lib:/usr/local/lib \
-x MCCL_PROTO=Simple \
-x MCCL_NET_SHARED_BUFFERS=0 \
-x MCCL_ALGO=Ring \
-x MCCL_IB_GID_INDEX=3 \
./all_reduce_perf -b 1M -e 1024M -f 2 -g 8
预期结果: 跨节点带宽达到预期水平
场景三:只想使用特定网络接口
问题: "服务器有多个网卡,想指定使用特定接口"
解决步骤:
# 指定 IP 网络接口
export MCCL_SOCKET_IFNAME=eth0
# 或指定 IB 接口
export MCCL_IB_HCA=mlx5_0
场景四:InfiniBand 配置问题
问题: "IB 网络报错,无法正常通信"
解决步骤:
# 1. 检查 IB 状态
ibstat
# 2. 检查 IB 是否可用
ib_write_bw -a
# 3. 检查内存锁定限制
ulimit -l
# 如果是 unlimited,则正常;否则需要设置
sudo echo "* soft memlock unlimited" >> /etc/security/limits.conf
sudo echo "* hard memlock unlimited" >> /etc/security/limits.conf
场景五:性能不理想
问题: "AllReduce 带宽远低于预期"
排查步骤:
# 1. 启用调试信息
export MCCL_DEBUG=WARN
# 2. 导出拓扑信息
export MCCL_TOPO_DUMP_FILE=/tmp/mccl-topo.xml
# 3. 如需观察环境变量生效情况,可切换到 INFO 日志
export MCCL_DEBUG=INFO
优化策略:
| 问题 | 诊断 | 优化方向 |
|---|---|---|
| 带宽低 | 检查是否使用 P2P 或 IB | 启用 GPU Direct |
| 延迟高 | 检查算法选择 | 设置 MCCL_ALGO 环境变量 |
| 启动慢 | 初始化时间过长 | 使用 mcclCommInitRankScalable |
场景六:容器环境使用
问题: "在 Docker 容器中运行 MCCL"
解决步骤:
# 启动容器时添加必要参数
docker run --rm \
--gpus all \
--shm-size=1g \
--ulimit memlock=-1 \
-v /usr/local/musa:/usr/local/musa \
my_image
注意:
--shm-size=1g:增加共享内存大小--ulimit memlock=-1:取消内存锁定限制
场景七:MPI 多进程应用初始化
问题: "多进程初始化 MCCL 通信器"
解决步骤:
#include <mpi.h>
#include <mccl.h>
int main(int argc, char* argv[]) {
MPI_Init(&argc, &argv);
int worldRank, worldSize;
MPI_Comm_rank(MPI_COMM_WORLD, &worldRank);
MPI_Comm_size(MPI_COMM_WORLD, &worldSize);
// 设置 GPU 设备
musaSetDevice(worldRank % ngpus);
// 获取唯一 ID
mcclUniqueId id;
if (worldRank == 0) {
mcclGetUniqueId(&id);
}
MPI_Bcast(&id, sizeof(id), MPI_BYTE, 0, MPI_COMM_WORLD);
// 初始化通信器
mcclComm_t comm;
mcclCommInitRank(&comm, worldSize, id, worldRank);
// 执行通信操作...
mcclCommDestroy(comm);
MPI_Finalize();
return 0;
}
场景八:单线程管理多 GPU
问题: "单线程管理多张 GPU 卡"
解决步骤:
// 必须使用 Group API
mcclGroupStart();
for (int i = 0; i < nDev; ++i) {
mcclAllReduce(sendbuff[i], recvbuff[i], size,
mcclFloat, mcclSum, comms[i], streams[i]);
}
mcclGroupEnd();
// 在 GroupEnd 之后同步
for (int i = 0; i < nDev; ++i) {
musaStreamSynchronize(streams[i]);
}
注意: 单线程多卡 必须使用 mcclGroupStart 与 mcclGroupEnd,否则可能死锁
场景九:使用 MUSA Graph
问题: "想用 MUSA Graph 优化 MCCL 操作"
解决步骤:
musaGraph_t graph;
musaStreamBeginCapture(stream);
// MCCL 操作会被捕获
mcclAllReduce(sendbuff, recvbuff, count,
mcclFloat, mcclSum, comm, stream);
musaStreamEndCapture(stream, &graph);
// 多次执行 Graph
musaGraphExec_t instance;
musaGraphInstantiate(&instance, graph, NULL, NULL, 0);
for (int i = 0; i < iterations; i++) {
musaGraphLaunch(instance, stream);
}
musaStreamSynchronize(stream);