nccl 04 nvidia 官方小程序

1,代码重新编辑

为了地毯式地检查结果的正确性,这里修改了代码

主要步骤为

step1:  data_p指向的空间中,分别生成随机数;

step2:  分别拷贝到gpu的sendbuff的显存中;

step3:  通过nccl_all_reduce sum;

step4:  取回 recvbuff中的数据;

step5:  将data_p中的数据 allreduce sum;

step6: 对比 recvbuff中的数据与 data_p中的数据的一致性;


#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <omp.h>// seed_base
// void gen_512(seed, A, start_idx, N)
// gen_512(seed_base+0, A, 0*512, N);  gen_512(seed_base + 1, A+1*512); gen_512(seed_base + 2, A+2*512);     ...    gen_512(seed_base + n, A, , N); ...
#if 1//NN is tile length
#define NN 312
#define MM 156
#define MATRIX_A 0xB5026F5AA96619E9ULL
#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */
#define LM 0x7FFFFFFFULL /* Least significant 31 bits */class thread_mt199937{public:
void srand(unsigned long long seed)
{init_genrand64(seed);
}/* generates a random number on [0, 2^63-1]-interval */
long long genrand64_int63(void)
{return (long long)(genrand64_int64() >> 1);
}/* generates a random number on [0,1]-real-interval */
double genrand64_real1(void)
{return (genrand64_int64() >> 11) * (1.0/9007199254740991.0);
}/* generates a random number on [0,1)-real-interval */
double genrand64_real2(void)
{return (genrand64_int64() >> 11) * (1.0/9007199254740992.0);
}/* generates a random number on (0,1)-real-interval */
double genrand64_real3(void)
{return ((genrand64_int64() >> 12) + 0.5) * (1.0/4503599627370496.0);
}private:
/* The array for the state vector */
unsigned long long mt[NN];
/* mti==NN+1 means mt[NN] is not initialized */
int mti=NN+1;/* initializes mt[NN] with a seed */
void init_genrand64(unsigned long long seed)
{mt[0] = seed;for (mti=1; mti<NN; mti++)mt[mti] =  (6364136223846793005ULL * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
}/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
void init_by_array64(unsigned long long init_key[],unsigned long long key_length)
{unsigned long long i, j, k;init_genrand64(19650218ULL);i=1; j=0;k = (NN>key_length ? NN : key_length);for (; k; k--) {mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ULL))+ init_key[j] + j; /* non linear */i++; j++;if (i>=NN) { mt[0] = mt[NN-1]; i=1; }if (j>=key_length) j=0;}for (k=NN-1; k; k--) {mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ULL))- i; /* non linear */i++;if (i>=NN) { mt[0] = mt[NN-1]; i=1; }}mt[0] = 1ULL << 63; /* MSB is 1; assuring non-zero initial array */
}/* generates a random number on [0, 2^64-1]-interval */
unsigned long long genrand64_int64(void)
{int i;unsigned long long x;static unsigned long long mag01[2]={0ULL, MATRIX_A};if (mti >= NN) { /* generate NN words at one time *//* if init_genrand64() has not been called, *//* a default initial seed is used     */if (mti == NN+1)init_genrand64(5489ULL);for (i=0;i<NN-MM;i++) {x = (mt[i]&UM)|(mt[i+1]&LM);mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)];}for (;i<NN-1;i++) {x = (mt[i]&UM)|(mt[i+1]&LM);mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)];}x = (mt[NN-1]&UM)|(mt[0]&LM);mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)];mti = 0;//printf("LL::\n");}x = mt[mti++];x ^= (x >> 29) & 0x5555555555555555ULL;x ^= (x << 17) & 0x71D67FFFEDA60000ULL;x ^= (x << 37) & 0xFFF7EEE000000000ULL;x ^= (x >> 43);return x;
}};#endif//#define NN 312// multi thread accelerating, to be singleton
class parallel_mt19937{
public:
//    int _base_seed;
void srand(unsigned long long seed)
{_base_seed = seed;
}
void rand_float(float* A, unsigned long len);private:unsigned long long _base_seed = 0;
};//int pmt19937::_base_seed = 0;void parallel_mt19937::rand_float(float* A, unsigned long len)
{#pragma omp parallel{unsigned long block_dim = omp_get_num_threads();unsigned long thid = omp_get_thread_num();if(thid == block_dim -1)std::cout << "Here are " << thid << " threads generating random number ..."<<std::endl;unsigned long tile_count = (len+NN-1)/NN;thread_mt199937 *t_mt_p = new thread_mt199937();// to be singletonfor(unsigned long tile_id=thid; tile_id<tile_count; tile_id+=block_dim){//each tile has a specific seed: (_base_seed + tile_id) to smt19937, to keep consistenceunsigned long tile_seed = _base_seed + tile_id;t_mt_p->srand(tile_seed);//if(thid == 35)                std::cout << "Hello from thread " << thid << std::endl;unsigned long tile_idx_start = tile_id*NN;unsigned long tile_idx_end = (((tile_id+1)*NN) <= len)? (tile_id+1)*NN: len;for(unsigned long idx = tile_idx_start; idx<tile_idx_end; idx++)A[idx] = float(t_mt_p->genrand64_real2());}delete t_mt_p;}
}////#define BUILD_MAIN//
#ifdef BUILD_MAINvoid print_matrix(unsigned long m, unsigned long n, float* A, unsigned long lda)
{for(unsigned long i=m-7; i<m; i++){for(unsigned long j=n-7; j<n; j++){printf("%7.4f ", A[i + j*lda]);}printf("\n");}
}#include <string.h>int main(){unsigned long m = 312*4*32*32*128;unsigned long n = 36;unsigned long lda = m;float* A = nullptr;
printf("LL: 00\n");A = (float*)malloc(lda * n * sizeof(float));//memset(A, 0x7F, lda*n*sizeof(float));
printf("LL:: 01\n");parallel_mt19937 gen_rand;gen_rand.srand(2024);gen_rand.rand_float(A, lda*n);
printf("LL:: 02\n");print_matrix(m, n, A, lda);free(A);return 0;
}#endifvoid init_data_float(float** data_p, int nDev, int size,  unsigned long seed)
{for(int idx=0; idx<nDev; idx++){*(data_p+idx) = nullptr;*(data_p+idx) = (float*)malloc(size*sizeof(float));}parallel_mt19937 gen_rand;for(int idx =0; idx<nDev; idx++){gen_rand.srand(seed+idx);gen_rand.rand_float(*(data_p + idx), size);}}void host_all_reduce_origin(float** sendbuff, int nDev, int size)
{for(int idx=1; idx<nDev; idx++){
#pragma omp paralell forfor(int i=0; i<size; i++)sendbuff[0][i] += sendbuff[idx][i];}
}void check_equal(float** result_recv_data_buff, float* sendbuff_0, int nDev, int size)
{for(int idx=0; idx<nDev; idx++){
#pragma omp paralell forfor(int i=0; i<size; i++){if(result_recv_data_buff[idx][i] != sendbuff_0[i])printf("ERROR: %7.4f != %7.4f  idx=%d, i=%d\n", result_recv_data_buff[idx][i], sendbuff_0[i], idx, i);return;}}
}void free_buff(float** buffArray, int n)
{for(int i=0; i<n; i++){if(buffArray[i] != nullptr){free(buffArray[i]);}}
}//#include <stdlib.h>
#include <stdio.h>
#include "cuda_runtime.h"
#include "nccl.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)int main(int argc, char* argv[])
{ncclComm_t comms[4];//managing 4 devices//int nDev = 4;int nDev = 2;int size = 32*1024*1024*16;int devs[4] = { 0, 1, 2, 3 };float** data_p = (float**)malloc(nDev*sizeof(float*));init_data_float(data_p, nDev, size, 2024);//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((void**)sendbuff + i, size * sizeof(float)));CUDACHECK(cudaMalloc((void**)recvbuff + i, size * sizeof(float)));//CUDACHECK(cudaMemset(sendbuff[i], 1, size * sizeof(float)));CUDACHECK(cudaMemcpy(sendbuff[i], data_p[i], size*sizeof(float), cudaMemcpyHostToDevice));//CUDACHECK(cudaMemset(recvbuff[i], 0, size * sizeof(float)));CUDACHECK(cudaStreamCreate(s+i));}printf("LL:: 04\n");//initializing NCCLNCCLCHECK(ncclCommInitAll(comms, nDev, devs));
printf("LL:: 05\n");//calling NCCL communication API. Group API is required when using//multiple devices per threadNCCLCHECK(ncclGroupStart());for (int i = 0; i < nDev; ++i)NCCLCHECK(ncclAllReduce((const void*)sendbuff[i], (void*)recvbuff[i], size, ncclFloat, ncclSum,comms[i], s[i]));NCCLCHECK(ncclGroupEnd());
printf("LL:: 06\n");
/*LL::
In a sum allreduce operation between k ranks,
each rank will provide an array in of N values,
and receive identical results in array out of N values,
where out[i] = in0[i]+in1[i]+…+in(k-1)[i]
*///synchronizing on CUDA streams to wait for completion of NCCL operationfor (int i = 0; i < nDev; ++i) {CUDACHECK(cudaSetDevice(i));CUDACHECK(cudaStreamSynchronize(s[i]));}
printf("LL:: 07\n");
/*check:
each recvbuff[0] = sendbuff_0[0]+ sendbuff_1[0];
0x01010101 + 0x01010101 = 0x02020202;
*/float** result_recv_data_buff;result_recv_data_buff = (float**)malloc(nDev*sizeof(float*));init_data_float(result_recv_data_buff, nDev, size, 2024+nDev);printf("LL:: 08\n");for(int idx=0; idx<nDev; idx++){cudaMemcpy(result_recv_data_buff[idx], recvbuff[idx], size*sizeof(float), cudaMemcpyDeviceToHost);}printf("LL:: 09\n");host_all_reduce_origin(data_p, nDev, size);printf("LL:: 10\n");
// ditanshi checkcheck_equal(result_recv_data_buff, data_p[0], nDev, size);printf("LL:: 11\n");free_buff(data_p, nDev);free_buff(result_recv_data_buff, nDev);//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;
}

Makefile

EXE := ex_1_1_SingleProcessSingleThreadMultipleDevicesall: $(EXE)INC := -I /usr/local/cuda/include -I /home/hipper/ex_nccl_20240701/local/include/
LD_FLAGS := -L /usr/local/cuda/lib64 -L /home/hipper/ex_nccl_20240701/local/lib -lcudart -lnccl -fopenmp%: %.cppg++ -g $< -o $@ $(INC) $(LD_FLAGS).PHONY: clean
clean:-rm -rf $(EXE)

 

2,编译运行

 

3,问题

显存占用了 7GB 和 8GB,实际数据应该只有2GB,recvbuff 2GB,总共4GB

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

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

相关文章

上海市计算机学会竞赛平台2023年6月月赛丙组选取子段(二)

题目描述 给定一个长度为&#x1d45b;n的序列 &#x1d44e;1,&#x1d44e;2,...,&#x1d44e;&#x1d45b;a1​,a2​,...,an​ &#xff0c;请问多少种方案&#xff0c;能够从中选取一个连续段&#xff0c;使得该子段内所有元素的值都相同&#xff1f; 输入格式 输入共…

掌握 Python 中 isinstance 的正确用法

&#x1f44b; 简介 isinstance() 函数用于判断一个对象是否是一个特定类型或者在继承链中是否是特定类型的实例。它常用于确保函数接收到的参数类型是预期的。 &#x1f4d6; 正文 1 语法 isinstance(object, classinfo) object参数是要检查的对象&#xff1b;classinfo参数…

fifio中wr_ack信号及其用途

Vivado中FIFO IP核的wr_ack信号及其用途。 wr_ack&#xff08;写确认&#xff09;信号的作用&#xff1a; 功能&#xff1a; wr_ack是一个输出信号&#xff0c;用于指示写操作已被FIFO成功接受。当FIFO成功接收并存储了一个数据项时&#xff0c;它会激活wr_ack信号一个时钟周期…

【SpringBoot循环依赖】解决循环依赖

我的项目中&#xff0c;报错&#xff1a; Description:The dependencies of some of the beans in the application context form a cycle:frontIndexController ┌─────┐ | systemConfigService └─────┘Action:Relying upon circular references is discourage…

ingress-nginx部署-helm方式

helm 安装ingress-nginx Ingress-Nginx Controller 支持多种方式安装&#xff1a; 使用heml安装chart使用kubectl apply&#xff0c;使用YAML文件&#xff1b; 详情可参考&#xff1a;https://kubernetes.github.io/ingress-nginx/deploy/ 本文实践使用helm安装ingress-ngi…

【工具推荐】ONLYOFFICE8.1版本编辑器测评——时下的办公利器

文章目录 一、产品介绍1. ONLYOFFICE 8.1简介2. 多元化多功能的编辑器 二、产品体验1. 云端协作空间2. 桌面编辑器本地版 三、产品界面设计1. 本地版本2. 云端版本 四、产品文档处理1. 文本文档&#xff08;Word)2. 电子表格&#xff08;Excel&#xff09;3. PDF表单&#xff0…

如何学习MyBatis 源码

MyBatis 源码分析是一个深入的话题&#xff0c;涉及到框架的内部实现细节。下面是一些基本介绍和指导&#xff1a; 整体认识 MyBatis 源码结构 核心模块&#xff1a;MyBatis 的核心模块包括 Configuration、Executor、StatementHandler、ParameterHandler、ResultSetHandler 等…

【C++ | 继承】|概念、方式、特性、作用域、6类默认函数

继承 1.继承的概念与定义2.继承的方式2.1继承基本特性2.2继承的作用域2.2.1隐藏赋值兼容 派生类的创建和销毁构造函数拷贝构造赋值重载 1.继承的概念与定义 继承是面向对象编程中的一个重要概念。它的由来可以追溯到软件开发中的模块化设计和代码复用的需求。 在软件开发过程…

mq消息堆积

通常情况下&#xff0c;出现消息积压的原因有 mq消费者挂了mq生产者生产消息的速度&#xff0c;大于mq消费者消费消息的速度 当数据量不大时&#xff0c;优化消费者处理逻辑 通过在代码中增加了一些日志&#xff0c;把mq消费者中各个关键节点的耗时都打印出来&#xff0c;发现有…

从零搭建Java酒店预订系统:实战指南_02

第四步,用户注册和登录 创建用户服务接口 在src/main/java目录下创建com.example.hotelbookingsystem.service包,并在该包下创建UserService接口: package com.example.hotelbookingsystem.service;import com.example.hotelbookingsystem.entity.User;public int…

【Android面试八股文】性能优化相关面试题: 什么是内存抖动?什么是内存泄漏?

文章目录 一、什么是内存抖动?内存抖动的问题卡顿OOM(Out Of Memory)二、什么是内存泄漏(Memory Leak)?引用计数法可达性分析法一、什么是内存抖动? 在Java中,每创建一个对象,就会申请一块内存,存储对象信息; 每分配一块内存,程序的可用内存也就少一块; 当程序…

电池企业如何通过部署PLM系统提升自身竞争力

产品生命周期管理&#xff08;PLM&#xff0c;Product Lifecycle Management&#xff09;是一种集成的企业信息化管理解决方案&#xff0c;旨在管理产品从概念设计、研发、生产、使用到退役的整个生命周期。PLM系统通过信息化手段&#xff0c;将企业的各个环节紧密连接在一起&a…

中英双语介绍美国的州:佛罗里达州(Florida)

中文版 佛罗里达州&#xff08;Florida&#xff09;位于美国东南部&#xff0c;因其温暖的气候、丰富的旅游资源和多样化的文化背景而闻名。以下是对佛罗里达州各方面的详细介绍&#xff1a; 人口 截至2020年&#xff0c;美国人口普查数据显示&#xff0c;佛罗里达州的人口约…

什么是协程?协程和线程的区别

文章目录 前置知识应用程序和内核阻塞和非阻塞同步和异步并发和并行IO 发展历史同步编程异步多线程/进程异步消息 回调函数&#xff08;响应式编程&#xff09; 协程协程基本概念go 示例代码协程和线程的区别 个人简介 前置知识 在了解协程前&#xff0c;我们先理解一些相关的…

强化学习原理入门-1绪论

1 绪论 1.1 这是一本什么书 强化学习算法&#xff1f; AlphaGo大胜世界围棋冠军李世石和柯洁事件&#xff0c;核心算法就用到了强化学习算法。 1.2 强化学习解决什么问题 案例1 非线性系统二级倒立摆 案例2 AlphaGo与柯洁的第二局棋 案例3 机器人学习站立 ...... 智能…

数据库被后台爆破如何解决?

在数字化时代&#xff0c;数据库安全成为企业与组织不容忽视的关键环节。其中&#xff0c;“后台爆破”攻击&#xff0c;即通过自动化工具尝试大量的用户名和密码组合&#xff0c;以非法获取数据库访问权限&#xff0c;是常见的安全威胁之一。本文将详细介绍如何识别、防御并解…

websocket使用,spring boot + vite + vue3

websocket使用&#xff0c;spring boot vite vue3 Websocket是什么WebSocket 服务端构建websocket 服务实现处理器pom文件 客户端仓库地址 Websocket是什么 WebSocket 是一种网络传输协议&#xff0c;可在单个 TCP 连接上进行全双工通信&#xff0c;位于 OSI 模型的应用层。…

沙箱在“一机两用”新规下的价值体现

在数字化时代&#xff0c;随着企业信息化建设的深入&#xff0c;数据安全问题愈发凸显其重要性。一机两用新规的出台&#xff0c;旨在通过技术创新和管理手段&#xff0c;实现终端设备的安全可控&#xff0c;确保敏感数据的安全存储与传输。SDC沙箱技术作为一种创新的安全防护手…

springcloud-config服务器,同样的配置在linux环境下不生效

原本在windows下能争取的获取远程配置但是部署到linux上死活都没有内容&#xff0c;然后开始了远程调试&#xff0c;这里顺带讲解下获取配置文件如果使用的是Git源&#xff0c;config service是如何响应接口并返回配置信息的。先说问题&#xff0c;我的服务名原本是abc-abc-abc…

图像基础知识入门【图像概念不同图像格式】

图像基础知识入门【图像概念&不同图像格式】 最近有在处理图像转换&#xff0c;因此稍微补足了一下图像相关知识&#xff0c;特在此记录。下面汇总是我根据自己理解和网上查阅资料而来。如有错误&#xff0c;欢迎大家指正。 1 基础概念 像素/分辨率 像素(Pixel)&#xff…