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-1
  float* 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 buffers
  float** 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 NCCL
  NCCLCHECK(ncclCommInitAll(comms, nDev, devs));

  //calling NCCL communication API. Group API is required when using
  //multiple devices per thread
  NCCLCHECK(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 operation
  for (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 buffers
  for (int i = 0; i < nDev; ++i) {
    CUDACHECK(cudaSetDevice(i));
    CUDACHECK(cudaFree(sendbuff[i]));
    CUDACHECK(cudaFree(recvbuff[i]));
  }

  //finalizing NCCL
  for(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/include

MPI_FLAGS := -I /usr/lib/x86_64-linux-gnu/openmpi/include -L /usr/lib/x86_64-linux-gnu/openmpi/lib -lmpi -lmpi_cxx

EXE := single_thread_allreduce oneServer_multiDevice_multiThread mpi_test

all: $(EXE)

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

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

mpi_test: mpi_test.cpp
	g++ -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,另一个示例

本例是

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Adobe Experience Design安装指南

XD&#xff08;Adobe Experience Design&#xff09;下载链接 https://pan.baidu.com/s/1MVcaE2GB1Q9YpgmgDxUGJw?pwd0531 1.鼠标右击【Adobe XD 55.1(64bit)】压缩包选择&#xff08;win11以上系统需先点击“显示更多选项”&#xff09;【解压到 Adobe XD 55.1(64bit)】。 …

《JVM由浅入深学习【四】 2023-12-24》JVM由简入深学习提升分享

JVM由简入深学习提升分享四 1.JVM中java堆的特点及作用2. JVM中对象如何在堆内存中分配3. JVM堆内存中的对象布局 1.JVM中java堆的特点及作用 是线程共享的一块区域虚拟机启动时就创建了是虚拟机中内存占用很大的一块存放所有的实例对象和数组GC主要的作用区域可分为新生代&am…

关于“Python”的核心知识点整理大全50

目录 python_repos.py 17.1.6 概述最受欢迎的仓库 python_repos.py 17.1.7 监视 API 的速率限制 注意 17.2 使用 Pygal 可视化仓库 python_repos.py 17.2.1 改进 Pygal 图表 python_repos.py 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xf…

09、docker 安装nacos并配置mysql存储配置信息

docker 安装nacos并配置mysql存储配置信息 1、docker启动nacos的各种方式2、Docker安装nacos3、MySQL中新建nacos的数据库4、挂载数据or配置目录5、运行 1、docker启动nacos的各种方式 内嵌derby数据源 docker run -d \ -e PREFER_HOST_MODEhostname \ -e SPRING_DATASOURCE_…

python旅游大数据分析可视化大屏 游客分析+商家分析+舆情分析 计算机毕业设计(附源码)Flask框架✅

毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&#xff0c;点赞、关注不迷路&#xff0c;大家在毕设选题&#xff…

详解静态网页数据获取以及浏览器数据和网络数据交互流程-Python

目录 前言 一、静态网页数据 二、网址通讯流程 1.DNS查询 2.建立连接 3.发送HTTP请求 4.服务器处理请求 5.服务器响应 6.渲染页面 7.页面交互 三、URL/POST/GET 1.URL 2.GET 形式 3.POST 形式 四.获取静态网页数据 1.requests库 点关注&#xff0c;防走丢&am…

Linux vi/vim 教程

文章目录 【 1. vi/vim 的三种模式 】1.1 命令模式1.2 输入模式1.3 底线命令模式 【 2. 实例 】【 3. vim 的其他命令 】 所有的 Unix Like 系统都会内建 vi 文本编辑器&#xff0c;其他的文本编辑器则不一定会存在。目前我们使用比较多的是 vim 编辑器。vim 从 vi 发展出来&am…

深度确定性策略梯度 DDPG

深度确定性策略梯度 DDPG 深度确定性策略梯度 DDPG模型结构目标函数算法步骤适合场景 深度确定性策略梯度 DDPG A2C、A3C 都是在线策略&#xff0c;在与环境交互时&#xff0c;样本参数更新效率低&#xff0c;所以主要是应用在离散空间&#xff0c;计算量没那么大。 DDPG 专用…

aps审核-模电英文稿

模拟电子线路 Analog circuit 需要熟悉课程名&#xff0c;一句话简单概括课程内容&#xff0c;准备一些重点内容介绍。 This course mainly introduces the properties(n.性质) of semiconductors(半导体) and transistors, and then analyzes and masters amplification circ…

算法专题四:前缀和

前缀和 一.一维前缀和(模板)&#xff1a;1.思路一&#xff1a;暴力解法2.思路二&#xff1a;前缀和思路 二. 二维前缀和(模板)&#xff1a;1.思路一&#xff1a;构造前缀和数组 三.寻找数组的中心下标&#xff1a;1.思路一&#xff1a;前缀和 四.除自身以外数组的乘积&#xff…

java企业人事信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web企业人事信息管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为M…

DeepSpeed: 大模型训练框架

背景&#xff1a; 目前&#xff0c;大模型的发展已经非常火热&#xff0c;关于大模型的训练、微调也是各个公司重点关注方向。但是大模型训练的痛点是模型参数过大&#xff0c;动辄上百亿&#xff0c;如果单靠单个GPU来完成训练基本不可能。所以需要多卡或者分布式训练来完成这…

PE解释器之PE文件结构

PE文件是由许许多多的结构体组成的&#xff0c;程序在运行时就会通过这些结构快速定位到PE文件的各种资源&#xff0c;其结构大致如图所示&#xff0c;从上到下依次是Dos头、Nt头、节表、节区和调试信息(可选)。其中Dos头、Nt头和节表在本文中统称为PE文件头(因为SizeOfHeaders…

Nacos设置账号密码

1、控制台设置 # 开启账号密码验证 nacos.core.auth.enabledtrue# 设置账号密码 nacos.core.auth.usernamenacos nacos.core.auth.passwordnacos1232、数据库设置 密码为&#xff1a;nacos&#xff0c;对应加密信息是&#xff1a; $2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2k…

文件分割合并助手

二进制文件合并分割器 时间: 2024.01.03 作者: FlameCyclone 自己写的一个能方便分割合并文件的小工具 使用说明 输出文件名 输出文件名规则前缀文件名开始固定名称序号(10/16进制显示, 宽度以输出最大序号为准)分割范围(16进制显示, 宽度以输出最大范围为准)CRC32校验码…

go语言``反引号用法归纳——多行输出和Tag标签(指定json名称、MySQL名称))

一、多行输出 示例 func main() {str1 : 反引号多行字符串str2 : "双引号" " 多行" " 字符串"//str3 : 单引号" //" 多行" //" 字符串str4 : "双引号\n" " 多行\n" &quo…

xadmin-plus

python之Xadmin-plus是什么&#xff1f; xadmin-plus: xadmin的django3.2版本支持。 Xadmin是一个非常优秀的Django Admin插件&#xff0c;可惜的是已经停止更新。Xadmin-plus对其进行了升级兼容。支持python3.10、Django3.2。 特性 Django Admin直接替换基于Twitter Boots…

Ubuntu22.04安装VTK8.2

1. 安装ccmake 和 VTK 的依赖项&#xff1a; sudo apt-get install cmake-curses-gui sudo apt-get install freeglut3-dev2.下载VTK-8.2.0库 VTK官方网址 自己选择合适的版本进行下载&#xff0c;解压到VTK文件夹下&#xff0c;再新建文件下名为build 3. 配置VTK 进入buil…

BIM 助力世界上最长的双层桥

Bentley 应用程序助力节省时间和成本&#xff0c;提前三年实现了投资回报 连通复杂的高速公路 PT. Wijaya Karya (WIKA) 是一家印度尼西亚的公司&#xff0c;为土建施工行业提供施工、机械和电气服务&#xff0c;该公司承包了印度尼西亚雅加达北部海港路二期工程的设计和建造&…

算法:岛屿的周长

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、问题描述 二、规律总结 总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、问题描述 给定一个包含 0 和 1 的二维网格地图&#x…