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,一经查实,立即删除!

相关文章

掌握 Python 中 isinstance 的正确用法

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

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

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

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

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

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

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

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

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

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

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

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

在数字化时代&#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…

如何实现电子签名签章功能?

随着技术的发展&#xff0c;传统的纸质合同签署方式逐渐暴露出效率低下、存储不便和安全性不足等问题。为了解决这些问题&#xff0c;电子签署服务为用户提供了一个安全、高效、环保的合同管理解决方案。 电子合同管理与签署平台的核心功能 1、用户管理&#xff1a;平台提供用…

怎么永久禁止win10系统自动更新?一键屏蔽系统自动更新

现在 Windows 10 系统是很多办公用户的主力操作系统&#xff0c;可是 Windows 系统会自动更新&#xff0c;这会严重影响系统稳定性。因为微软虽然以提供更新为服务&#xff0c;但并不是每次更新它都是安全的。 接下来和我一起看看如何使用联想开发的小工具一键屏蔽系统自动更新…

MQTT协议详述

MQTT 概述 消息队列遥测传输&#xff08;英语&#xff1a;Message Queuing Telemetry Transport&#xff0c;缩写&#xff1a;MQTT&#xff09;&#xff0c;是基于发布&#xff08;Publish&#xff09;/订阅&#xff08;Subscribe&#xff09;范式的消息协议&#xff0c;位于…

为什么80%的码农都做不了架构师?

文章目录 一、技术广度和深度的要求1.1 技术广度1.2 技术深度 二、全局视角和系统思维2.1 全局视角2.2 系统思维 三、沟通能力和团队合作3.1 沟通能力3.2 团队合作 四、业务理解和需求分析4.1 业务理解4.2 需求分析 五、持续学习和创新能力5.1 持续学习5.2 创新能力 六、总结 &…

【UML用户指南】-25-对高级行为建模-时间和空间

目录 1、概念 2、时间 3、位置 4、常用建模技术 4.1、对定时约束建模 4.2、对对象的分布建模 分布式系统是这样一个系统&#xff0c;它的构件可以物理地分布在各个结点上。 为了表达对实时系统和分布式系统建模的需要&#xff0c;UML 提供了定时标记、时间表达式、定时约…

抛弃 Neofetch?众多优秀替代方案等你体验!

目录 抛弃 Neofetch&#xff1f;众多优秀替代方案等你体验Neofetch 的替代品FastfetchscreenFetchmacchina 抛弃 Neofetch&#xff1f;众多优秀替代方案等你体验 NeoFetch 是用 Bash 3.2 编写的命令行系统信息工具&#xff0c;该项目的主要开发人员已将 GitHub 存储库存档&…

民生银行收大额罚单:信用卡中心一同被罚,管理层如何施救?

民生银行的2024年&#xff0c;再添变故。 近日&#xff0c;国家金融监管总局宁波分局公布了数则行政处罚信息公开表。内容显示&#xff0c;民生银行&#xff08;SH:600016、HK:01988&#xff09;宁波分行、民生银行信用卡中心宁波分中心因多项违法违规事实&#xff0c;共计被处…

JVM原理(八):JVM虚拟机工具之基础故障工具

这里主要介绍监视虚拟机运行状态和进行故障处理的工具 1. jsp:虚拟机进程状况工具 jsp命令格式&#xff1a; jsp [options] [hostid] jps远程查询虚拟机进程状态 2. jstat:虚拟机统计信息监视工具 jstat命令格式&#xff1a; jstat [option vmid [interval [s|ms] [count]…

LP-SCADA系统在智能制造中的作用是什么?

在企业思考如何提升产线自动化时&#xff0c;往往考虑到的都是从硬件设备下手&#xff0c;但其实作为“大脑”存在的软件系统更是必不可少&#xff0c;尤其是当产线中的自动化设备越来越多&#xff0c;产生的数据也越来越多&#xff0c;大量数据需要人工进行整理时&#xff0c;…

论文阅读YOLO-World: Real-Time Open-Vocabulary Object Detection

核心&#xff1a; 开放词汇的实时的yolo检测器。重参数化的视觉语言聚合路径模块Re-parameterizable VisionLanguage Path Aggregation Network (RepVL-PAN)实时核心&#xff1a;轻量化的检测器离线词汇推理过程重参数化 方法 预训练方案&#xff1a;将实例注释重新定义为区域…