5. PyTorch+NCCL源码编译

ops/2024/9/18 12:28:29/ 标签: pytorch, NCCL, gpu算力, 分布式

系列文章

  • 第1章 多机多卡运行nccl-tests 和channel获取
  • 第2章 多机多卡nccl-tests 对比分析
  • 第3章 使用tcpdump抓取rdma数据包
  • 第5章 PyTorch+NCCL源码编译

目录

  • 系列文章
  • 前言
  • 一、本地环境
  • 二、安装cudnn
  • 三、使用pytorch自带NCCL库进行编译安装
    • 1. 源码编译
    • 2. 查看版本和all_reduce测试
  • 四、 修改NCCL源代码并重新编译后测试,体现出源码更改


前言

从源码编译PyTorch和NCCL,可以实现对NCCL源码进行修改以适应特定需求,并应用于实际的分布式训练中,本文基于torch 2.2.1和nccl 2.19.3描述了一个大致过程,并验证了源码更改的有效性。


一、本地环境

  • Ubuntu 22.04.4 LTS (GNU/Linux 6.5.0-35-generic x86_64)
  • cuda 11.8+ cudnn 8
  • python 3.11
  • torch v2.2.1+ nccl v2.19.3
  • NVIDIA GeForce RTX 4090 *2

二、安装cudnn

下载cudnn包之后打开

cd cudnn-linux-x86_64-8.9.7.29_cuda11-archive
# 复制到指定目录
sudo cp ./include/cudnn*.h /usr/local/cuda/include
sudo cp ./lib/libcudnn* /usr/local/cuda/lib64chmod a+r /usr/local/cuda/include/cudnn*.h
chmod a+r /usr/local/cuda/lib64/libcudnn*

确认已经安装cudnn,除了cudnn_version.h,务必检查同目录下也有cudnn_ops_infer.h文件

cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2

在这里插入图片描述
可以看到对应cudnn版本为8.9.7

pytorchNCCL_56">三、使用pytorch自带NCCL库进行编译安装

1. 源码编译

使用 python setup.py 命令进行源码编译,develop 命令通常在开发过程中使用,以在"开发模式"中安装包,其中对源代码的更改会立即生效而无需重新安装。develop更改为install 就是直接安装。

# 新建conda虚拟环境,取名为nccl2
conda create -n nccl2 python=3.11
conda activate nccl2#下载v2.2.1 源码
git clone --branch v2.2.1 --recursive https://github.com/pytorch/pytorch
cd pytorch      # v2.2.1 # 安装依赖包
pip install -r requirements.txt#以开发模式安装torch,不使用系统nccl,而是torch自带的,位于third party目录下 
MAX_JOBS=32 USE_CUDA=1 USE_NCCL=1 USE_SYSTEM_NCCL=0 python setup.py develop
  • 如下图所示即为开始编译:
    在这里插入图片描述
  • 中途报错如下:貌似是numpy相关的错误
  • pip show numpy | grep Version查看numpy 版本,为2.0.0
    在这里插入图片描述
  • 估计是numpy版本太新,导致一些变量名更改,=> 对numpy降级,实测1.26.3 可行, 之后make clean ,再重新编译在这里插入图片描述
  • 源码编译的过程可能比较久,编译成功后提示如下,说明已经成功安装torch
    在这里插入图片描述

2. 查看版本和all_reduce测试

编译完毕,测试能否用torch,cuda,nccl以及识别出GPU。这里新建了一个version.py

# version.py
import torchprint("torch version",torch.__version__)
print(torch.cuda.is_available(), torch.distributed.is_nccl_available())
print("nccl version:",torch.cuda.nccl.version())
print("cuda version:", torch.version.cuda)       cudnn_version = torch.backends.cudnn.version()
print("cuDNN version:", cudnn_version)
print(torch.cuda.device_count(), torch.cuda.get_device_name(0))

结果如下,可以看到troch和nccl的版本,检测到双卡等。

在这里插入图片描述

执行以下代码,新建test.py, 使用 nccl 作为通信后端,在一个gpu上测试分布式训练中张量的 all_reduce 操作。

#test.pyimport os
import torch
import torch.distributed as distos.environ['MASTER_ADDR'] = 'localhost'
os.environ['MASTER_PORT'] = '29500'
dist.init_process_group("nccl", rank=0, world_size=1)
x = torch.ones(6)if torch.cuda.is_available():y = x.cuda()dist.all_reduce(y)print(f"cuda allreduce result: {y}")   

结果如下:

在这里插入图片描述

NCCL_135">四、 修改NCCL源代码并重新编译后测试,体现出源码更改

修改 pytorch-2.2.1/third_party/nccl/nccl/src/collectives.cc 文件后,重新编译,

原代码如下,文件内包含了all_gather,all_reduce等各个集合通信操作,29行开始是All_Reduce的相关定义

/************************************************************************** Copyright (c) 2015-2023, NVIDIA CORPORATION. All rights reserved.** See LICENSE.txt for license information************************************************************************/#include "argcheck.h" // Need some checks here since we access comm
#include "collectives.h"
#include "enqueue.h"
#include "nccl.h"NCCL_API(ncclResult_t, ncclAllGather, const void* sendbuff, void* recvbuff, size_t sendcount,ncclDataType_t datatype, ncclComm_t comm, cudaStream_t stream);
ncclResult_t ncclAllGather(const void* sendbuff, void* recvbuff, size_t sendcount,ncclDataType_t datatype, ncclComm_t comm, cudaStream_t stream) {// Just pass the size of one message and not the total bytes sent/received.constexpr nvtxPayloadSchemaEntry_t AllGatherSchema[] = {{0, NVTX_PAYLOAD_ENTRY_TYPE_SIZE, "Message size [bytes]"}};size_t msgsize = sendcount * ncclTypeSize(datatype);NVTX3_FUNC_WITH_PARAMS(AllGather, AllGatherSchema, msgsize)struct ncclInfo info = { ncclFuncAllGather, "AllGather",sendbuff, recvbuff, sendcount, datatype, ncclSum, 0, comm, stream, /* Args */ALLGATHER_CHUNKSTEPS, ALLGATHER_SLICESTEPS };return ncclEnqueueCheck(&info);
}NCCL_API(ncclResult_t, ncclAllReduce, const void* sendbuff, void* recvbuff, size_t count,ncclDataType_t datatype, ncclRedOp_t op, ncclComm* comm, cudaStream_t stream);
ncclResult_t ncclAllReduce(const void* sendbuff, void* recvbuff, size_t count,ncclDataType_t datatype, ncclRedOp_t op, ncclComm* comm, cudaStream_t stream) 
{struct NvtxParamsAllReduce {size_t bytes;ncclRedOp_t op;};// Just pass the size of one message and not the total bytes sent/received.static constexpr nvtxPayloadSchemaEntry_t AllReduceSchema[] = {{0, NVTX_PAYLOAD_ENTRY_TYPE_SIZE, "Message size [bytes]"},{0, NVTX_PAYLOAD_ENTRY_NCCL_REDOP, "Reduction operation", nullptr, 0,offsetof(NvtxParamsAllReduce, op)}};NvtxParamsAllReduce payload{count * ncclTypeSize(datatype), op};NVTX3_FUNC_WITH_PARAMS(AllReduce, AllReduceSchema, payload)struct ncclInfo info = { ncclFuncAllReduce, "AllReduce",sendbuff, recvbuff, count, datatype, op, 0, comm, stream, /* Args */ALLREDUCE_CHUNKSTEPS, ALLREDUCE_SLICESTEPS };return ncclEnqueueCheck(&info);
}

修改ncclAllReduce函数, 将内部全部注释掉,加一句 return ncclSystemError;

NCCL_API(ncclResult_t, ncclAllReduce, const void* sendbuff, void* recvbuff, size_t count,ncclDataType_t datatype, ncclRedOp_t op, ncclComm* comm, cudaStream_t stream);ncclResult_t ncclAllReduce(const void* sendbuff, void* recvbuff, size_t count,ncclDataType_t datatype, ncclRedOp_t op, ncclComm* comm, cudaStream_t stream) 
{// struct NvtxParamsAllReduce {//   size_t bytes;//   ncclRedOp_t op;// };// // Just pass the size of one message and not the total bytes sent/received.// static constexpr nvtxPayloadSchemaEntry_t AllReduceSchema[] = {//   {0, NVTX_PAYLOAD_ENTRY_TYPE_SIZE, "Message size [bytes]"},//   {0, NVTX_PAYLOAD_ENTRY_NCCL_REDOP, "Reduction operation", nullptr, 0,//     offsetof(NvtxParamsAllReduce, op)}// };// NvtxParamsAllReduce payload{count * ncclTypeSize(datatype), op};// NVTX3_FUNC_WITH_PARAMS(AllReduce, AllReduceSchema, payload)// struct ncclInfo info = { ncclFuncAllReduce, "AllReduce",//   sendbuff, recvbuff, count, datatype, op, 0, comm, stream, /* Args *///   ALLREDUCE_CHUNKSTEPS, ALLREDUCE_SLICESTEPS };// return ncclEnqueueCheck(&info);return ncclSystemError;
}

每次修改pytorch中nccl源码,要使之生效需要进行重新编译,先删除原有编译文件再重新编译

#删除原有nccl相关的
rm -r ./build/nccl*#重新编译
MAX_JOBS=32 USE_CUDA=1 USE_NCCL=1 USE_SYSTEM_NCCL=0  python setup.py develop#运行测试文件,看看有没有报错
python test.py

在这里插入图片描述

如图:报错ncclSystemError,体现出了源码的更改。
以后就可以按照这种方法修改nccl源码,使之与pytorch集成,将修改后的nccl应用于实际的分布式训练中了。

关于nccl源码及大致的总体流程,推荐一个大佬的文章,写的比较详细,令我受益匪浅。
https://blog.csdn.net/kidgin7439/category_11998768.html


http://www.ppmy.cn/ops/55070.html

相关文章

Karabiner-Elements 设置mac键盘

软件下载地址: Karabiner-Elements 修改键盘位置,但是重启后,就消失了。 {"description": "New Rule (change left_shiftcaps_lock to page_down, right_shiftcaps_lock to left_commandmission_control)","manip…

Linux—进程与计划管理

目录 一、程序 二、进程 1、什么是进程 2、进程的特点 3、进程、线程、携程 3.1、进程 3.2、线程 3.3、携程 三、查看进程信息 1、ps -aux 2、ps -elf 3、top ​3.2、输出内容详解 3.2.1、输出第一部分解释 3.2.2、输出第二部分解释 4、pgrep 5、pstree 四、进…

非NVIDIA联盟——如UALink(超加速器链接)联盟和UXL基金会等组织发起反击

随着NVIDIA可能面临法国反垄断监管机构的指控,非NVIDIA联盟——如UALink(超加速器链接)联盟和UXL基金会等组织——正据报道发起反击,大幅增加在专用ASIC开发上的努力。 据《工商时报》报道,相关的半导体知识产权&…

HTML5的多线程技术:Web Worker API

Web Workers API 是HTML5的一项技术,它允许在浏览器后台独立于主线程运行脚本,即允许进行多线程处理。这对于执行密集型计算任务特别有用,因为它可以防止这些任务阻塞用户界面,从而保持网页的响应性和交互性。Web Workers在自己的…

什么是中间件?常见中间件有哪些?

中间件是什么 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即…

字符串知识点

API API和API帮助文档 API:目前是JDK中提供的各种功能的Java类。 这些类将底层的实现封装了起来,我们不需要关心这些类是如何实现的,只需要学习这些类如何使用即可。 API帮助文档:帮助开发人员更好的使用API和查询API的一个工具。 String概…

《企业实战分享 · 常用运维中间件》

📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 近期刚转战 CSDN,会严格把控文章质量,绝不滥竽充数,如需交流&#xff…

【Linux】多线程(一万六千字)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 文章目录 前言 线程的概念 线程的理解(Linux系统为例) 在Linux系统里如何保证让正文部分的代码可以并发的去跑呢? 为什么要有多进程呢? 为…

充分利用智慧校园人事系统,提升党政职务管理

智慧校园人事系统中的党政职务管理功能,是专为高校及教育机构设计的,旨在高效、精确地处理与党政职务相关的各类事务,包括职务任命、任期管理、职责分配、考核评估等,以信息化手段促进党务及行政工作的透明化、规范化。 该模块首先…

python selenium 下载

查看浏览器版本 下载地址: 新版本下载地址 https://googlechromelabs.github.io/chrome-for-testing/ 历史版本也可以用这个下载地址 http://chromedriver.storage.googleapis.com/index.html 找到对应的版本 126.0.xxx 下载

使用Vue CLI创建Vue项目并使用Vue Router进行基本配置的步骤

步骤 1: 安装 Vue CLI 首先,确保你的电脑上已经安装了Node.js和npm。然后,通过以下命令安装Vue CLI(如果已经安装,请跳过此步骤): npm install -g vue/cli步骤 2: 创建新的Vue项目 使用Vue CLI创建一个新…

HMM,EM算法(Expectation-Maximization Algorithm) VAE)以及KL散度

HMM,EM算法(Expectation-Maximization Algorithm) VAE)以及KL散度 最大化对数似然(或称为最大化对数似然函数)是在统计学中用来估计模型参数的一种常用方法。其基本思想是找到一组参数值,使得在…

Java中的数据结构选择指南

Java中的数据结构选择指南 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们来探讨在Java中如何选择适合的数据结构以提高代码效率和性能。 1. 简介 在…

【Spring】springSecurity

1、概述 1.1定义和用途 Spring Security为基于Spring的企业应用系统提供声明式的安全访问控制解决方案。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC、DI(控制反转和依赖注入)和AOP(面向切面编程&…

如何找BMS算法、BMS软件的实习

之前一直忙,好久没有更新了,今天就来写一篇文章来介绍如何找BMS方向的实习,以及需要具备哪些条件,我的实习经历都是在读研阶段找的,读研期间两段的实习经历再加上最高影响因子9.4分的论文,我的秋招可以说是…

基于Java中的SSM框架实现计算机类考研院校推荐系统项目【项目源码+论文说明】

基于Java中的SSM框架实现计算机类考研院校推荐系统演示 摘要 在互联网时代人们获取信息的方式变得非常快捷,登录网站搜索就能快速查找到相关的信息,但是网络上面的信息数量非常庞大,有很多信息虽然和自己搜索的相关,但并不是自己…

AI视频生成:引领视觉内容创作的新纪元

AI视频生成:引领视觉内容创作的新纪元 AI视频生成的兴起与应用 在数字时代,视频内容的需求迅速增长。从社交媒体平台上的短视频到商业广告,视频已经成为传达信息和吸引观众的主要手段之一。然而,制作高质量的视频需要大量的时间…

第一后裔The First Descendant延迟、卡顿、无法联机?

The First Descendant第一后裔游戏中还设计了多种辅助攻击手段,它们如同角色手中的魔法,为战斗增添了无数可能性。这些辅助攻击手段或能造成范围伤害,或能减速敌人,甚至能召唤出强大的支援力量。最近有玩家反映,遇到了…

平衡二叉查找树和多路查找树

平衡二叉查找树 普通平衡二叉查找树 平衡二叉树定义是按照有序排列成树状,左子树数据大于右子树,任意节点的左右子树高度不能大于1 优点:可以保证绝对的平衡 缺点:当进行删除节点和新增节点,树进行自平衡的时候&…

解密Eureka UNKNOWN状态:服务注册的隐形守护者

🌐 解密Eureka UNKNOWN状态:服务注册的隐形守护者 在微服务架构中,Eureka作为Netflix开源的服务发现框架,扮演着服务注册与发现的核心角色。然而,在Eureka的Dashboard上,我们有时会遇到服务状态显示为UNKN…