多机多卡运行nccl-tests和channel获取

nccl-tests

  • 环境
    • 1. 安装nccl
    • 2. 安装openmpi
    • 3. 单机测试
    • 4. 多机测试
      • mpirun多机多进程
      • 多节点运行nccl-tests
      • channel获取

环境

  • Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-91-generic x86_64)
  • cuda 11.8+ cudnn 8
  • nccl 2.15.1
  • NVIDIA GeForce RTX 4090 *2

1. 安装nccl

#查看cuda版本
nvcc -V

Nvidia官网下载链接 (不过好像需要注册一个Nvidia账户)

根据自己的cuda版本去寻找想要的版本,单击对应行即可显示下载步骤。

在这里插入图片描述
采取 Network Installer即可,我选择了nccl2.15.1+cuda11.8

#配置网络存储库
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt-get update#安装特定版本
sudo apt install libnccl2=2.15.1-1+cuda11.8 libnccl-dev=2.15.1-1+cuda11.8#确认系统nccl版本
dpkg -l | grep nccl

2. 安装openmpi

#apt安装openmpi
sudo apt-get update
sudo apt-get install openmpi-bin openmpi-doc libopenmpi-dev#验证是否安装成功
mpirun --version

3. 单机测试

nccl-test GitHub链接

如何执行测试和相关参数参考readme.md即可,已经描述的很详细了。

NCCL测试依赖于MPI以在多个进程和多个节点上工作。如果你想使用MPI支持编译这些测试,需要将环境变量MPI设置为1,并将MPI_HOME设置为MPI安装的路径。

#克隆该repo
git clone https://github.com/NVIDIA/nccl-tests.git
cd nccl-tests# 编译支持mpi的test
make MPI=1 MPI_HOME=/usr/lib/x86_64-linux-gnu/openmpi

成功后会在build目录下生成可执行文件

在这里插入图片描述

NCCL测试可以在多个进程、多个线程和每个线程上的多个CUDA设备上运行。进程的数量由MPI进行管理,因此不作为参数传递给测试(可以通过mpirun -np n(n为进程数)来指定)。

总的ranks数量(即CUDA设备数,也是总的gpu数量)=(进程数)*(线程数)*(每个线程的GPU数)。

可以先通过nvidia-smi topo -m命令查看机器内拓扑结构,这里是双卡,两个gpu之间连接方式是PIX(Connection traversing at most a single PCIe bridge)
在这里插入图片描述

在 2个 GPU 上运行 ( -g 2 ),扫描范围从 8 字节到 128MB :

./build/all_reduce_perf -b 8 -e 128M -f 2 -g 2

这里-b表示minBytes,-e表示maxBytes,-g表示两张卡,-f表示数据量每次乘2,如开始是8B,往后依次是16,32,64字节…
-g后面的gpu数量不能超过实际的数量,否则会报如下错误- invalid Device ordinal
在这里插入图片描述

单机执行结果如下:
在这里插入图片描述

这里执行all_reduce操作时算法带宽(algbw)和总线带宽(busbw)是一致的,并且都是随着数据量的增大而增大。关于二者的区别可见https://github.com/NVIDIA/nccl-tests/blob/master/doc/PERFORMANCE.md#bandwidth

4. 多机测试

关于mpi的基本了解和使用,可参考这篇文章 DL分布式训练基础之openmpi

mpirun多机多进程

这里使用2个节点(126,127)。 运行mpirun命令的为头节点(这里用126),它是通过ssh远程命令来拉起其他节点(127)的业务进程的,故它需要密码访问其他host

#在126生成RSA公钥,并copy给127即可
ssh-keygen -t rsassh-copy-id -i ~/.ssh/id_rsa.pub  192.168.72.127

如果ssh的端口不是22,可以在mpirun命令后添加参数-mca plm_rsh_args "-p 端口号" ,除此之外,还可以在主节点上编辑以下文件

nano ~/.ssh/config
#添加以下内容
Host 192.168.72.127Port 2233

指定连接到特定主机时使用的端口(例如2233),并确保在执行之前检查并设置~/.ssh/config文件的权限,使其对你的用户是私有
的:

chmod 600 ~/.ssh/config

这样配置后,当你使用SSH连接到主机192.168.72.127,SSH将使用端口2233,可以减少在‘mpirun‘命令中指定端口的需要。

然后可以进行多节点测试,节点个数对应-np 后的数字,这里新建一个hostfile内容如下,每行一个ip地址就可以

192.168.72.126
192.168.72.127

mpirun -np 2 -hostfile hostfile  -pernode \
bash -c 'echo "Hello from process $OMPI_COMM_WORLD_RANK of $OMPI_COMM_WORLD_SIZE on $(hostname)"'

在这里插入图片描述

多节点运行nccl-tests

运行以下命令,这里对应双机4卡,注意np后面的进程数*单个节点gpu数(-g 指定)=总的gpu数量,即之前提到的等式

总的ranks数量(即CUDA设备数,也是总的gpu数量)=(进程数)*(线程数)*(每个线程的GPU数)。

mpirun -np 2 -pernode \
--allow-run-as-root \
-hostfile hostfile \
-mca btl_tcp_if_include eno2  \
-x NCCL_SOCKET_IFNAME=eno2  \
./build/all_reduce_perf -b 8 -e 128M -f 2 -g 2 -c 0

避免每次命令加–allow-run-as-root

echo 'export OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1' >> ~/.bashrc
echo 'export OMPI_ALLOW_RUN_AS_ROOT=1' >> ~/.bashrc

不添加参数-mca btl_tcp_if_include eno2 的话会报错如下:Open MPI accepted a TCP connection from what appears to be a
another Open MPI process but cannot find a corresponding process entry for that peer.
在这里插入图片描述
eno2替换为自己的网卡接口名称,可通过ifconfig查看。
执行结果如下:
在这里插入图片描述
可以看到,同样的操作,同样的数据量双机比单机慢了不是一点,这里平均总先带宽0.07 GB/s,而前文的单机是3.25.

当然这里使用的是普通的千兆以太网,带宽最高1GB/s,也没有IB网卡等。
之前使用100G的网卡测试的带宽双机是可以达到1.几G,现在100G的网卡接口暂时不能用了就没有测。

channel获取

channel的概念:
nccl中channel的概念表示一个通信路径,为了更好的利用带宽和网卡,以及同一块数据可以通过多个channel并发通信,nccl会使用多channel,搜索的过程就是搜索出来一组channel。

具体一点可以参考以下文章:
如何理解Nvidia英伟达的Multi-GPU多卡通信框架NCCL? - Connolly的回答 - 知乎
https://www.zhihu.com/question/63219175/answer/2768301153

获取channel:
mpirun命令中添加参数-x NCCL_DEBUG=INFO \即可,详细信息就会输出到终端

mpirun -np 2 -pernode \
-hostfile hostfile \
-mca btl_tcp_if_include eno2 \
-x NCCL_SOCKET_IFNAME=eno2  \
-x NCCL_DEBUG=INFO  \
-x NCCL_IGNORE_DISABLED_P2P=1 \
-x CUDA_VISIBLE_DEVICES=0,1 \
./build/all_reduce_perf -b 8 -e 128M -f 2 -g 2 -c 0

执行结果:

 nThread 1 nGpus 2 minBytes 8 maxBytes 134217728 step: 2(factor) warmup iters: 5 iters: 20 agg iters: 1 validation: 0 graph: 0
#
# Using devicesRank  0 Group  0 Pid 685547 on      nccl4 device  0 [0xcd] NVIDIA GeForce RTX 4090Rank  1 Group  0 Pid 685547 on      nccl4 device  1 [0xcf] NVIDIA GeForce RTX 4090Rank  2 Group  0 Pid 1728006 on      nccl5 device  0 [0xcd] NVIDIA GeForce RTX 4090Rank  3 Group  0 Pid 1728006 on      nccl5 device  1 [0xcf] NVIDIA GeForce RTX 4090
nccl4:685547:685547 [0] NCCL INFO Bootstrap : Using eno2:10.112.205.39<0>
nccl4:685547:685547 [0] NCCL INFO NET/Plugin : No plugin found (libnccl-net.so), using internal implementation
nccl4:685547:685547 [0] NCCL INFO cudaDriverVersion 12020
NCCL version 2.15.1+cuda11.8
nccl4:685547:685563 [0] NCCL INFO NET/IB : No device found.
nccl4:685547:685563 [0] NCCL INFO NET/Socket : Using [0]eno2:10.112.205.39<0>
nccl4:685547:685563 [0] NCCL INFO Using network Socket
nccl4:685547:685564 [1] NCCL INFO Using network Socket
nccl5:1728006:1728006 [0] NCCL INFO cudaDriverVersion 12020
nccl5:1728006:1728006 [0] NCCL INFO Bootstrap : Using eno2:10.112.57.233<0>
nccl5:1728006:1728006 [0] NCCL INFO NET/Plugin : No plugin found (libnccl-net.so), using internal implementation
nccl5:1728006:1728014 [0] NCCL INFO NET/IB : No device found.
nccl5:1728006:1728014 [0] NCCL INFO NET/Socket : Using [0]eno2:10.112.57.233<0>
nccl5:1728006:1728014 [0] NCCL INFO Using network Socket
nccl5:1728006:1728015 [1] NCCL INFO Using network Socket
nccl5:1728006:1728015 [1] NCCL INFO NCCL_IGNORE_DISABLED_P2P set by environment to 1.
nccl4:685547:685564 [1] NCCL INFO NCCL_IGNORE_DISABLED_P2P set by environment to 1.
nccl4:685547:685563 [0] NCCL INFO Channel 00/02 :    0   1   2   3
nccl4:685547:685563 [0] NCCL INFO Channel 01/02 :    0   1   2   3
nccl4:685547:685563 [0] NCCL INFO Trees [0] 1/2/-1->0->-1 [1] 1/-1/-1->0->2
nccl4:685547:685564 [1] NCCL INFO Trees [0] -1/-1/-1->1->0 [1] -1/-1/-1->1->0
nccl5:1728006:1728014 [0] NCCL INFO Trees [0] 3/-1/-1->2->0 [1] 3/0/-1->2->-1
nccl5:1728006:1728015 [1] NCCL INFO Trees [0] -1/-1/-1->3->2 [1] -1/-1/-1->3->2
nccl5:1728006:1728014 [0] NCCL INFO Channel 00/0 : 1[cf000] -> 2[cd000] [receive] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Channel 00/0 : 3[cf000] -> 0[cd000] [receive] via NET/Socket/0
nccl5:1728006:1728014 [0] NCCL INFO Channel 01/0 : 1[cf000] -> 2[cd000] [receive] via NET/Socket/0
nccl5:1728006:1728014 [0] NCCL INFO Channel 00 : 2[cd000] -> 3[cf000] via SHM/direct/direct
nccl5:1728006:1728014 [0] NCCL INFO Channel 01 : 2[cd000] -> 3[cf000] via SHM/direct/direct
nccl4:685547:685564 [1] NCCL INFO Channel 00/0 : 1[cf000] -> 2[cd000] [send] via NET/Socket/0
nccl5:1728006:1728015 [1] NCCL INFO Channel 00/0 : 3[cf000] -> 0[cd000] [send] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Channel 01/0 : 3[cf000] -> 0[cd000] [receive] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Channel 00 : 0[cd000] -> 1[cf000] via SHM/direct/direct
nccl4:685547:685563 [0] NCCL INFO Channel 01 : 0[cd000] -> 1[cf000] via SHM/direct/direct
nccl4:685547:685564 [1] NCCL INFO Channel 01/0 : 1[cf000] -> 2[cd000] [send] via NET/Socket/0
nccl5:1728006:1728015 [1] NCCL INFO Channel 01/0 : 3[cf000] -> 0[cd000] [send] via NET/Socket/0
nccl4:685547:685564 [1] NCCL INFO Connected all rings
nccl4:685547:685564 [1] NCCL INFO Channel 00 : 1[cf000] -> 0[cd000] via SHM/direct/direct
nccl4:685547:685564 [1] NCCL INFO Channel 01 : 1[cf000] -> 0[cd000] via SHM/direct/direct
nccl5:1728006:1728014 [0] NCCL INFO Connected all rings
nccl4:685547:685563 [0] NCCL INFO Connected all rings
nccl5:1728006:1728015 [1] NCCL INFO Connected all rings
nccl5:1728006:1728015 [1] NCCL INFO Channel 00 : 3[cf000] -> 2[cd000] via SHM/direct/direct
nccl5:1728006:1728015 [1] NCCL INFO Channel 01 : 3[cf000] -> 2[cd000] via SHM/direct/direct
nccl4:685547:685563 [0] NCCL INFO Channel 00/0 : 2[cd000] -> 0[cd000] [receive] via NET/Socket/0
nccl5:1728006:1728014 [0] NCCL INFO Channel 00/0 : 0[cd000] -> 2[cd000] [receive] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Channel 01/0 : 2[cd000] -> 0[cd000] [receive] via NET/Socket/0
nccl5:1728006:1728014 [0] NCCL INFO Channel 01/0 : 0[cd000] -> 2[cd000] [receive] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Channel 00/0 : 0[cd000] -> 2[cd000] [send] via NET/Socket/0
nccl5:1728006:1728014 [0] NCCL INFO Channel 00/0 : 2[cd000] -> 0[cd000] [send] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Channel 01/0 : 0[cd000] -> 2[cd000] [send] via NET/Socket/0
nccl5:1728006:1728014 [0] NCCL INFO Channel 01/0 : 2[cd000] -> 0[cd000] [send] via NET/Socket/0
nccl4:685547:685563 [0] NCCL INFO Connected all trees
nccl4:685547:685563 [0] NCCL INFO threadThresholds 8/8/64 | 32/8/64 | 512 | 512
nccl4:685547:685563 [0] NCCL INFO 2 coll channels, 2 p2p channels, 2 p2p channels per peer
nccl5:1728006:1728014 [0] NCCL INFO Connected all trees
nccl5:1728006:1728014 [0] NCCL INFO threadThresholds 8/8/64 | 32/8/64 | 512 | 512
nccl5:1728006:1728014 [0] NCCL INFO 2 coll channels, 2 p2p channels, 2 p2p channels per peer
nccl4:685547:685564 [1] NCCL INFO Connected all trees
nccl4:685547:685564 [1] NCCL INFO threadThresholds 8/8/64 | 32/8/64 | 512 | 512
nccl4:685547:685564 [1] NCCL INFO 2 coll channels, 2 p2p channels, 2 p2p channels per peer
nccl5:1728006:1728015 [1] NCCL INFO Connected all trees
nccl5:1728006:1728015 [1] NCCL INFO threadThresholds 8/8/64 | 32/8/64 | 512 | 512
nccl5:1728006:1728015 [1] NCCL INFO 2 coll channels, 2 p2p channels, 2 p2p channels per peer
nccl4:685547:685563 [0] NCCL INFO comm 0x55aec4722370 rank 0 nranks 4 cudaDev 0 busId cd000 - Init COMPLETE
nccl4:685547:685564 [1] NCCL INFO comm 0x55aec472e1e0 rank 1 nranks 4 cudaDev 1 busId cf000 - Init COMPLETE
nccl5:1728006:1728014 [0] NCCL INFO comm 0x557f5e599d40 rank 2 nranks 4 cudaDev 0 busId cd000 - Init COMPLETE
nccl5:1728006:1728015 [1] NCCL INFO comm 0x557f5e5a5f20 rank 3 nranks 4 cudaDev 1 busId cf000 - Init COMPLETE
nccl4:685547:685547 [0] NCCL INFO comm 0x55aec4722370 rank 0 nranks 4 cudaDev 0 busId cd000 - Destroy COMPLETE
nccl5:1728006:1728006 [0] NCCL INFO comm 0x557f5e599d40 rank 2 nranks 4 cudaDev 0 busId cd000 - Destroy COMPLETE
nccl4:685547:685547 [0] NCCL INFO comm 0x55aec472e1e0 rank 1 nranks 4 cudaDev 1 busId cf000 - Destroy COMPLETE
nccl5:1728006:1728006 [0] NCCL INFO comm 0x557f5e5a5f20 rank 3 nranks 4 cudaDev 1 busId cf000 - Destroy COMPLETE

最后就是上图中的带宽展示,这里没有放上去。

以上就是双机4卡nccl执行的一个过程,后续计划结合nccl和nccl-tests的源代码分析一下总体流程,重点是channel部分

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/466370.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu Desktop - Screenshot (截图工具)

Ubuntu Desktop - Screenshot [截图工具] 1. Search your computer -> Screenshot -> Lock to Launcher2. gnome-screenshot3. System Settings -> Keyboard -> ShortcutsReferences 1. Search your computer -> Screenshot -> Lock to Launcher 2. gnome-s…

BUGKU-WEB 滑稽

题目描述 没啥好说的&#xff0c;直接启动场景吧&#xff1a; 解题思路 花里胡哨的界面&#xff08;js效果&#xff09;&#xff0c;有啥用呢&#xff1f;直接看源码吧&#xff08;ctrlu&#xff09;&#xff1a; 相关工具 略 解题步骤 ctrlu&#xff0c;发现在注释中直…

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱1(附带项目源码)

效果演示 文章目录 效果演示系列目录前言人物和视角基本控制简单的背包系统和物品交互绘制背包UI脚本控制 源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中&#xff0c;我们将…

Go高级并发模式

Go对并发提供了强大的原生支持&#xff0c;本文讨论Go的高级并发模式&#xff0c;理解这些并发模式&#xff0c;可以帮助我们编写高效的Go应用程序。原文: Advanced Concurrency Patterns in Go "并发不是并行&#xff0c;但使并行成为可能。" —— Rob Pike 本文将深…

android中实现设备尺寸适配

1、引言 设备尺寸适配的重要性想必就不用我多说了&#xff0c;在我发布的历史文章中我曾谈过Qt中的设备尺寸适配问题&#xff0c;那这里我就来教大家如何在android中做设备尺寸适配。在android中设备尺寸适配的方式有好几种&#xff0c;但我喜欢的还是使用获取设备真实尺寸然后…

就业|高校毕业生就业信息小程序|基于微信小程序的高校毕业生就业信息的设计与实现(源码+数据库+文档)

高校毕业生就业信息小程序目录 目录 基于微信小程序的高校毕业生就业信息的设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户小程序模块 2、用户信息管理 2、职位招聘管理 3、公司信息管理 4、论坛信息管理 四、数据库设计 1、实体ER图 五、核心代码 …

C语言学习记录

牛牛的第二个整数_牛客题霸_牛客网 (nowcoder.com) 注意输入的格式&#xff0c;%d空格%d空格%d

数据结构第十四天(树的存储/双亲表示法)

目录 前言 概述 接口&#xff1a; 源码&#xff1a; 测试函数&#xff1a; 运行结果&#xff1a; 往期精彩内容 前言 孩子&#xff0c;一定要记得你的父母啊&#xff01;&#xff01;&#xff01; 哈哈&#xff0c;今天开始学习树结构中的双亲表示法&#xff0c;让孩…

C++重新入门-C++ 函数

函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数&#xff0c;即主函数 main() &#xff0c;所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的&#xff0c;但在逻辑上&#xff0c;划分通常…

【JAVA-Day76】Java线程解析:三态和五态

Java线程解析&#xff1a;三态和五态 《Java线程状态深度解析&#xff1a;三态和五态探秘 &#x1f60e;》摘要引言一、什么是三态 &#x1f60a;二、什么是五态 &#x1f603;三、五态之间如何转变3.1 新建状态转换到运行状态3.2 运行状态转换到阻塞状态3.3 运行状态转换到等待…

为什么Python是数据科学家的首选语言

这篇文章全面探讨了Python作为数据科学领域首选语言的原因。从Python的历史、特性&#xff0c;到在数据科学中的应用实例&#xff0c;再到与其他数据科学语言的比较&#xff0c;以及在实际企业中的应用&#xff0c;我们深入剖析了Python的优势与挑战&#xff0c;最后对Python的…

【原创 附源码】Flutter安卓及iOS海外登录--Facebook登录最详细流程

最近接触了几个海外登录的平台&#xff0c;踩了很多坑&#xff0c;也总结了很多东西&#xff0c;决定记录下来给路过的兄弟坐个参考&#xff0c;也留着以后留着回顾。更新时间为2024年2月12日&#xff0c;后续集成方式可能会有变动&#xff0c;所以目前的集成流程仅供参考&…