nccl 源码安装与应用示例 附源码

1, 官方下载网址

    注意,本文并不使用nv预编译的包来安装,仅供参考:

NVIDIA Collective Communications Library (NCCL) | NVIDIA Developer

2,github网址

    这里是nv开源的nccl源代码,功能完整,不需要有任何疑虑:

GitHub - NVIDIA/nccl: Optimized primitives for collective multi-GPU communication

3,文档网址

    这里是官方教程,本文示例是根据其中的example改写的:

Using NCCL — NCCL 2.19.3 documentation

4,源码下载与安装

    4.1,下载

git clone --recursive https://github.com/NVIDIA/nccl.git

    4.2,编译

cd nccl
make -j src.build

或者为了节省编译时间和硬盘空间,可以指定gpu的架构,以sm_70为例:

make -j src.build NVCC_GENCODE="-gencode=arch=compute_70,code=sm_70"

    4.3,打包

安装打包deb的工具:


sudo apt install build-essential devscripts debhelper fakeroot

打包:

make pkg.debian.build
ls build/pkg/deb/

 

    4.4,安装

其中,deb包的文件名中包含了cuda版本号,以自己生成的安装包的名字为准:

sudo dpkg -i  build/pkg/deb/libnccl2_2.19.4-1+cuda12.1_amd64.deb
sudo dpkg -i  build/pkg/deb/libnccl-dev_2.19.4-1+cuda12.1_amd64.deb

5,示例

这里的示例是单机单线程多卡的示例,本文使用了双gpu显卡为例,即,在一个进程中迭代操作两个gpu 显卡,实现 allreduce操作, 四个 float vector, S0,S1,R0,R1,数学效果如下:

R0 = S0 + S1;R[0] = S0[0] + S1[0];

R1 = S0 + S1;R[0] = S0[0] + S1[0];

对应代码,其中 :

sendbuff[0] 是gpu-0 显存里边的要给vector,

sendbuff[1] 是gpu-1 显存里边的要给vector,

实现的数学效果为

显存 recvbuff[0] = sendbuff[0] + sendbuff[1];

显存 recvbuff[1] = sendbuff[0] + sendbuff[1];

    5.1,源代码

#include <stdlib.h>
#include <stdio.h>
#include "cuda_runtime.h"
#include "nccl.h"
#include <time.h>
#include <sys/time.h>#define CUDACHECK(cmd) do {                         \cudaError_t err = cmd;                            \if (err != cudaSuccess) {                         \printf("Failed: Cuda error %s:%d '%s'\n",       \__FILE__,__LINE__,cudaGetErrorString(err)); \exit(EXIT_FAILURE);                             \}                                                 \
} while(0)#define NCCLCHECK(cmd) do {                         \ncclResult_t res = cmd;                           \if (res != ncclSuccess) {                         \printf("Failed, NCCL error %s:%d '%s'\n",       \__FILE__,__LINE__,ncclGetErrorString(res)); \exit(EXIT_FAILURE);                             \}                                                 \
} while(0)void  get_seed(long long &seed)
{struct timeval tv;gettimeofday(&tv, NULL);seed = (long long)tv.tv_sec * 1000*1000 + tv.tv_usec;//only second and usecond;printf("useconds:%lld\n", seed);
}void  init_vector(float* A, int n)
{long long seed = 0;get_seed(seed);srand(seed);for(int i=0; i<n; i++){A[i] = (rand()%100)/100.0f;}
}void print_vector(float* A, float size)
{for(int i=0; i<size; i++)printf("%.2f ", A[i]);printf("\n");
}void vector_add_vector(float* sum, float* A, int n)
{for(int i=0; i<n; i++){sum[i] += A[i];}
}int main(int argc, char* argv[])
{ncclComm_t comms[4];printf("ncclComm_t is a pointer type, sizeof(ncclComm_t)=%lu\n", sizeof(ncclComm_t));//managing 4 devices//int nDev = 4;int nDev = 2;//int size = 32*1024*1024;int size = 16*16;int devs[4] = { 0, 1, 2, 3 };float** sendbuff_host = (float**)malloc(nDev * sizeof(float*));float** recvbuff_host = (float**)malloc(nDev * sizeof(float*));for(int dev=0; dev<nDev; dev++){sendbuff_host[dev] = (float*)malloc(size*sizeof(float));recvbuff_host[dev] = (float*)malloc(size*sizeof(float));init_vector(sendbuff_host[dev], size);init_vector(recvbuff_host[dev], size);}//sigma(sendbuff_host[i]); i = 0, 1, ..., nDev-1float* result = (float*)malloc(size*sizeof(float));memset(result, 0, size*sizeof(float));for(int dev=0; dev<nDev; dev++){vector_add_vector(result, sendbuff_host[dev], size);printf("sendbuff_host[%d]=\n", dev);print_vector(sendbuff_host[dev], size);}printf("result=\n");print_vector(result, size);//allocating and initializing device buffersfloat** sendbuff = (float**)malloc(nDev * sizeof(float*));float** recvbuff = (float**)malloc(nDev * sizeof(float*));cudaStream_t* s = (cudaStream_t*)malloc(sizeof(cudaStream_t)*nDev);for (int i = 0; i < nDev; ++i) {CUDACHECK(cudaSetDevice(i));CUDACHECK(cudaMalloc(sendbuff + i, size * sizeof(float)));CUDACHECK(cudaMalloc(recvbuff + i, size * sizeof(float)));CUDACHECK(cudaMemcpy(sendbuff[i], sendbuff_host[i], size*sizeof(float), cudaMemcpyHostToDevice));CUDACHECK(cudaMemcpy(recvbuff[i], recvbuff_host[i], size*sizeof(float), cudaMemcpyHostToDevice));CUDACHECK(cudaStreamCreate(s+i));}//initializing NCCLNCCLCHECK(ncclCommInitAll(comms, nDev, devs));//calling NCCL communication API. Group API is required when using//multiple devices per threadNCCLCHECK(ncclGroupStart());printf("blocked ncclAllReduce will be calleded\n");fflush(stdout);for (int i = 0; i < nDev; ++i)NCCLCHECK(ncclAllReduce((const void*)sendbuff[i], (void*)recvbuff[i], size, ncclFloat, ncclSum, comms[i], s[i]));printf("blocked ncclAllReduce is calleded nDev =%d\n", nDev);fflush(stdout);NCCLCHECK(ncclGroupEnd());//synchronizing on CUDA streams to wait for completion of NCCL operationfor (int i = 0; i < nDev; ++i) {CUDACHECK(cudaSetDevice(i));CUDACHECK(cudaStreamSynchronize(s[i]));}for (int i = 0; i < nDev; ++i) {CUDACHECK(cudaSetDevice(i));CUDACHECK(cudaMemcpy(recvbuff_host[i], recvbuff[i], size*sizeof(float), cudaMemcpyDeviceToHost));}for (int i = 0; i < nDev; ++i) {CUDACHECK(cudaSetDevice(i));CUDACHECK(cudaStreamSynchronize(s[i]));}for(int i=0; i<nDev; i++) {printf("recvbuff_dev2host[%d]=\n", i);print_vector(recvbuff_host[i], size);}//free device buffersfor (int i = 0; i < nDev; ++i) {CUDACHECK(cudaSetDevice(i));CUDACHECK(cudaFree(sendbuff[i]));CUDACHECK(cudaFree(recvbuff[i]));}//finalizing NCCLfor(int i = 0; i < nDev; ++i)ncclCommDestroy(comms[i]);printf("Success \n");return 0;
}

    5.2,编译

    参考Makefile中的如下一条:

single_thread_allreduce: single_thread_allreduce.cpp
    g++ -g $< -o $@ $(LD_FLAGS)

Makefile:

LD_FLAGS := -lnccl -L/usr/local/cuda/lib64 -lcudart -I/usr/local/cuda/includeMPI_FLAGS := -I /usr/lib/x86_64-linux-gnu/openmpi/include -L /usr/lib/x86_64-linux-gnu/openmpi/lib -lmpi -lmpi_cxxEXE := single_thread_allreduce oneServer_multiDevice_multiThread mpi_testall: $(EXE)single_thread_allreduce: single_thread_allreduce.cppg++ -g $< -o $@ $(LD_FLAGS)oneServer_multiDevice_multiThread: oneServer_multiDevice_multiThread.cppg++ -g $< -o $@ $(LD_FLAGS) $(MPI_FLAGS)mpi_test: mpi_test.cppg++ -g $< -o $@ $(LD_FLAGS) $(MPI_FLAGS).PHONY: clean
clean:-rm $(EXE)

    5.3,运行

 这里没有使用 mpi,故可以直接编译运行

make && ./single_thread_allreduce

    5.4,效果

 稍微注释一下上图:

实现了数学目标:

R0 = S0 + S1;R[0] = S0[0] + S1[0];

R1 = S0 + S1;R[0] = S0[0] + S1[0];

6,另一个示例

本例是

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

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

相关文章

侯捷C++ 2.0 新特性

关键字 nullptr and std::nullptr_t auto 一致性初始化&#xff1a;Uniform Initialization 11之前&#xff0c;初始化方法包括&#xff1a;小括号、大括号、赋值号&#xff0c;这让人困惑。基于这个原因&#xff0c;给他来个统一&#xff0c;即&#xff0c;任何初始化都能够…

C#编程-使用条件构造

使用条件构造 作判定是人的基本能力。判定也是可收编进程序。这有助于确定程序执行指令的顺序。 您可用条件构造来控制程序的流程。条件构造允许您基于被求职的表达式的结果来执行选定语句。 可以包含在C#程序中的各种条件构造是: if…else 构造switch…case 构造if…else构…

git 如何撤销历史某次merge

git&#xff0c;如何 撤销某一次历史提交或merge&#xff0c;并保留该版本的后续提交&#xff1f; 场景1&#xff1a; 你有两个功能迭代版本的分支&#xff0c;一个是 15 号上线&#xff0c;一个是25号上线。5号的时候产品突然说&#xff0c;这两个版本一起上&#xff0c;然后…

【LabVIEW FPGA入门】创建第一个LabVIEW FPGA程序

本教程仅以compactRIO&#xff08;FPGA-RT&#xff09;举例 1.系统配置 1.1软件安装 FPGA-RT 1. LabVIEW Development System (Full or Professional) 2. LabVIEW Real-Time Module 3. LabVIEW FPGA Module 4. NI-RIO drivers 1.2硬件配置 1.使用线缆连接CompactRIO至主机…

软件测试/测试开发丨Pytest结合数据驱动

安装yaml pip install pyyaml pytest结合数据驱动yaml 工程目录结构 数据准备 读取excel文件 openpyxl库的安装 openpyxl库的操作 pytest结合csv实现数据驱动 csv文件介绍 pytest结合json实现数据驱动 最后感谢每一个认真阅读我文章的人&#xff0c;礼尚往来总是要有的&…

Jmeter实现分布式并发

Jmeter实现分布式并发&#xff0c;即使用远程机执行用例。 环境&#xff1a; VMware Fusion Windows系统是win7。 操作过程 1、Master在jmeter.properties添加remote_hosts 2、Slave在jmeter.properties添加server_port 同时把remote_hosts修改为和主机&#xff08;Master…

matlab生成列是0-255渐变的图像

图像大小&#xff1a;640512 8位灰度图 %% 生成图像 %大小&#xff1a;640*512 %类型&#xff1a;灰度图 %灰度值&#xff1a;列按照0-255渐变&#xff0c;故命名为column shade。 clc,clear all,close all; %输入的图 imadouble(imread(lenna2.bmp));%原图 imargb2gray(ima)…

ubuntu系统没有网络图标的解决办法

参考文章:https://blog.csdn.net/qq_56922632/article/details/132309643 1. 执行关闭网络服务的命令&#xff0c;关闭网络服务sudo service NetworkManager stop2. 删除网络的状态文件sudo rm /var/lib/NetworkManager/NetworkManager.state3. 修改网络的配置文件sudo vi /etc…

SpringBoot—支付—支付宝

一、流程 二、沙箱操作 1.用支付宝账号登录【开放控制平台】创建应用获取 appid 2.选择沙箱模拟环境 3.沙箱应用-》获取appid(一个appid绑定一个收款支付宝账户) 4.利用开发助手工具生成RSA2密钥 公钥&#xff1a;传给支付宝平台 私钥&#xff1a;配置代码中&#xff0c;…

基于simiulink的flyback反激型电路建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 Flyback反激型电路的基本原理 4.2 Flyback反激型电路的数学建模 4.3 Flyback反激型电路的仿真方法 5.完整工程文件 1.课题概述 flyback反激型电路建模与仿真。反激变换器在开关管导通时电源将电能…

opencv期末练习题(3)附带解析

创建黑色画板&#xff0c;并支持两种画图功能 import mathimport cv2 import numpy as np """ 1. 创建一个黑色画板 2. 输入q退出 3. 输入m切换画图模式两种模式&#xff0c;画矩形和画圆形。用户按住鼠标左键到一个位置然后释放就可以画出对应的图像 "&qu…

第三百四十一回

文章目录 1. 概念介绍2. 使用方法与主要功能2.1 使用方法2.2 主要功能 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取App自身信息"相关的内容&#xff0c;本章回中将介绍一个三方包:open_setting.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念…