[4]CUDA中的向量计算与并行通信模式

CUDA中的向量计算与并行通信模式

  • 本节开始,我们将利用GPU的并行能力,对其执行向量和数组操作
  • 讨论每个通信模式,将帮助你识别通信模式相关的应用程序,以及如何编写代码

1.两个向量加法程序

  • 先写一个通过cpu实现向量加法的程序
  • 如下所示,向量相加实际上是模仿GPU的写法,在GPU中,tid 代表特定的某个线程的ID。
  • 如果你的cpu是双核的,可以在每个核心上运行一个线程,分别将tid初始化为0和1,然后每次循环的时候+2,这样的话可以实现一个核激素那偶数元素的和,一个核计算基数元素的和,通过两个线程的实现并行计算
#include "stdio.h"
#include<iostream>
//Defining Number of elements in Array
#define N	5
//Defining vector addition function for CPU
void cpuAdd(int *h_a, int *h_b, int *h_c) {int tid = 0;	while (tid < N){h_c[tid] = h_a[tid] + h_b[tid];tid += 1;}
}int main(void) {int h_a[N], h_b[N], h_c[N];//Initializing two arrays for additionfor (int i = 0; i < N; i++) {h_a[i] = 2 * i*i;h_b[i] = i;}//Calling CPU function for vector additioncpuAdd (h_a, h_b, h_c);//Printing Answerprintf("Vector addition on CPU\n");for (int i = 0; i < N; i++) {printf("The sum of %d element is %d + %d = %d\n", i, h_a[i], h_b[i], h_c[i]);}return 0;
}

在这里插入图片描述

  • 而总所周知,NVIDIA GPU包含多个块,每个块又包含多个线程,因此可以通过GPU实现更多线程并行计算向量的和,最大程度提高速度
  • 可以将代码修改为核函数如下:
#include "stdio.h"
#include<iostream>
#include <cuda.h>
#include <cuda_runtime.h>//Defining number of elements in Array
#define N	5//Defining Kernel function for vector addition
__global__ void gpuAdd(int* d_a, int* d_b, int* d_c) {//Getting block index of current kernelint tid = blockIdx.x;	// handle the data at this indexif (tid < N)d_c[tid] = d_a[tid] + d_b[tid];
}int main(void) {//定义主机数组变量int h_a[N], h_b[N], h_c[N];//定义设备指针变量int* d_a, * d_b, * d_c;//分配显卡内存cudaMalloc((void**)&d_a, N * sizeof(int));cudaMalloc((void**)&d_b, N * sizeof(int));cudaMalloc((void**)&d_c, N * sizeof(int));//Initializing Arraysfor (int i = 0; i < N; i++) {h_a[i] = 2 * i * i;h_b[i] = i;}// Copy input arrays from host to device memorycudaMemcpy(d_a, h_a, N * sizeof(int), cudaMemcpyHostToDevice);cudaMemcpy(d_b, h_b, N * sizeof(int), cudaMemcpyHostToDevice);//设置内核参数为5个块,每个块一个线程 ,并像核函数传递参数gpuAdd << <N, 1 >> > (d_a, d_b, d_c);//将计算结果从显卡拷贝到主机cudaMemcpy(h_c, d_c, N * sizeof(int), cudaMemcpyDeviceToHost);printf("Vector addition on GPU \n");//Printing result on consolefor (int i = 0; i < N; i++) {printf("The sum of %d element is %d + %d = %d\n", i, h_a[i], h_b[i], h_c[i]);}//Free up memorycudaFree(d_a);cudaFree(d_b);cudaFree(d_c);return 0;
}

在这里插入图片描述

  • 以上可以发现,通过GPU并行运算,或者多个线程的并行计算,明显的减少了数组的处理时间。比起CPU上的串行计算,提高了吞吐率
  • 在此说一下吞吐量的含义:只对网络、设备端口、虚电路或者其他设施,单位时间内成功的传送数据的数量(以比特、字节、分贝等测量)

2. 对比CPU代码和GPU代码的延迟

  • CPU的加法程序和GPU的加法程序都是以一个模块化的方式来编写的
  • N的值较小时,看不出cpu与GPU的差异,但是当N值很大时,会发现两者计算效率的显著差异
  • 下边将展示如何为并行计算计时并对两者时间进行比较
clock_t start_d = clock();printf("Doing GPU Vector add\n");gpuAdd << <N, 1 >> > (d_a, d_b, d_c);cudaThreadSynchronize();clock_t end_d = clock();double time_d = double(end_d - start_d) / CLOCKS_PER_SEC;printf("No of elements in Array: %d \n Device time %f second \n Host time %f second \n ",N, time_d, time_h);

3. 对向量的每个元素进行平方

  • 前边调用内核函数时启用了N个块,每个块一个线程执行计算;另一种也可以只启动1个块,块里边有N个线程,淡然也可以启用N个块,每个块M个线程
  • 下边通过启用一个块中的N个线程来执行向量每个元素的平方运算
#include "stdio.h"
#include<iostream>
#include <cuda.h>
#include <cuda_runtime.h>
//Defining number of elements in Array
#define N	5
//Kernel function for squaring number
__global__ void gpuSquare(float *d_in, float *d_out) {//Getting thread index for current kernelint tid = threadIdx.x;	// handle the data at this indexfloat temp = d_in[tid];d_out[tid] = temp*temp;
}int main(void) {//Defining Arrays for hostfloat h_in[N], h_out[N];//Defining Pointers for devicefloat *d_in, *d_out;// allocate the memory on the gpucudaMalloc((void**)&d_in, N * sizeof(float));cudaMalloc((void**)&d_out, N * sizeof(float));//Initializing Arrayfor (int i = 0; i < N; i++) {h_in[i] = i;}//Copy Array from host to devicecudaMemcpy(d_in, h_in, N * sizeof(float), cudaMemcpyHostToDevice);//Calling square kernel with one block and N threads per blockgpuSquare << <1, N >> >(d_in, d_out);//Coping result back to host from device memorycudaMemcpy(h_out, d_out, N * sizeof(float), cudaMemcpyDeviceToHost);//Printing result on consoleprintf("Square of Number on GPU \n");for (int i = 0; i < N; i++) {printf("The square of %f is %f\n", h_in[i], h_out[i]);}//Free up memorycudaFree(d_in);cudaFree(d_out);return 0;
}

在这里插入图片描述

  • 需注意

    • 每当使用这种方式启动N个线程并行的时候,需要注意每个块的最大线程不超过 5121024
    • 现在所有计算能力/显卡算力在 3.0 - 7.5 的GPU卡,每个块最大1024个线程
    • 如果N是2000,而你的GPU卡线程的最大数量是512,那么不能写成 << <12 000 > >>,而应该使用<< <4,500 > >>,应该理性的选择合适数量的块和每个块具有的线程数量

4. 并行通信模式

  • 当多个线程并行执行时,它们遵循一定的通信模式,知道它们在显存里哪里输入,哪里输出

4.1 映射

  • 一对一操作,每个线程或任务读取单一输入,产生单一输出,就是Map模式
d_out[i] = d_in[i] * 2

4.2 收集

  • 此模式下,每个线程或者任务,具有多个输入,并产生单个输出,保存到存储器的单一位置,即Gather模式:
out[i] = (in[i-1] + in[i] + in[i+1]) / 3

4.3 分散式

  • Scatter 模式,线程或者任务读取单一输入,单项存储器产生多个输出,比如数组排序:
out[i-1] += 2 * in[i] and out[i+1] += 3 * in[i]

4.4 蒙版

  • 当线程或者任务要从数组中读取固定形状的相邻元素时,这叫stencil模式,在图像处理中非常有用。比如想用一个3X3或者5X5的窗口进行滑动滤波
  • 代码类似Gather

4.5 转置

  • 当想要输入矩阵行主序,输出矩阵想要列主序,或者有一个结构数组(SoA),想转换成一个数组结构(AoS),它是特别有用的。Transpose模式如下:
out[i+j*128] = in[j + i*128]

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

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

相关文章

软件设计:基于 python 代码快速生成 UML 图

1. 官方文档 PlantUML Language Reference Guide Comate | 百度研发编码助手 百度 Comate (Coding Mate Powered by AI) 是基于文心大模型的智能代码助手&#xff0c;结合百度积累多年的编程现场大数据和外部优秀开源数据&#xff0c;可以生成更符合实际研发场景的优质代码。…

GBDT、XGBoost、LightGBM算法详解

文章目录 一、GBDT (Gradient Boosting Decision Tree) 梯度提升决策树1.1 回归树1.2 梯度提升树1.3 Shrinkage1.4 调参1.5 GBDT的适用范围1.6 优缺点 二、XGBoost (eXtreme Gradient Boosting)2.1 损失函数2.2 正则项2.3 打分函数计算2.4 分裂节点2.5 算法过程2.6 参数详解2.7…

oracle中insert all的用法

1、简述 使用insert into语句进行表数据行的插入&#xff0c;但是oracle中有一个更好的实现方式&#xff1a;使用insert all语句。 insert all语句是oracle中用于批量写数据的 。insert all分又为 无判断条件插入有判断条件插入有判断条件插入分为 Insert all when... 子句 …

利用 MongoDB Atlas 进行大模型语义搜索和RAG

节前&#xff0c;我们星球组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

基于英飞凌BGT60LTR11AIP E6327芯片具低功耗的脉冲多普勒操作模式常用于汽车应用的雷达上

芯片特征&#xff1a; 60 GHz收发器MMIC&#xff0c;带一个发射器和一个接收器单元封装天线&#xff08;AIP&#xff09;&#xff08;6.73.30.56 mm3)低功耗的脉冲多普勒操作模式自主模式用于运动和运动方向的集成检测器运动检测信号的直接输出目标检测范围的15个可配置阈值检测…

Android14之Binder调试(二百一十一)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

2024年5月20日优雅草蜻蜓API大数据服务中心v2.0.4更新

v2.0.4更新 v2.0.4更新 2024年5月20日优雅草蜻蜓API大数据服务中心v2.0.4更新-增加ai绘画接口增加淘宝联想词接口底部增加联系方式 更新日志 底部增加联系方式 增加ai绘画接口 增加淘宝联想词接口 增加用户中心充值提示 用户中心内页颜色改版完成 截图 部分具体更新接口信…

【NLP】词性标注

词 词是自然语言处理的基本单位&#xff0c;自动词法分析就是利用计算机对词的形态进行分析&#xff0c;判断词的结构和类别。 词性&#xff08;Part of Speech&#xff09;是词汇最重要的特性&#xff0c;链接词汇和句法 词的分类 屈折语&#xff1a;形态分析 分析语&#…

k8s 1.24.x之后如果rest 访问apiserver

1.由于 在 1.24 &#xff08;还是 1.20 不清楚了&#xff09;之后&#xff0c;下面这两个apiserver的配置已经被弃用 了&#xff0c;简单的说就是想不安全的访问k8s是不可能了&#xff0c;所以只能走安全的访问方式也就是 https://xx:6443了&#xff0c;所以需要证书。 - --ins…

Git系列:git rm 的高级使用技巧

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

【go项目01_学习记录15】

重构MVC 1 Article 模型1.1 首先创建 Article 模型文件1.2 接下来创建获取文章的方法1.3 新增 types.StringToUint64()函数1.4 修改控制器的调用1.5 重构 route 包1.6 通过 SetRoute 来传参对象变量1.7 新增方法&#xff1a;1.8 控制器将 Int64ToString 改为 Uint64ToString1.9…

【数据结构】栈和队列的相互实现

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持&#xff01; 1.用栈实现队列 当队列中进入这些元素时&#xff0c;相应的栈1中元素出栈顺序与出队列相反&#xff0c;因此我们可以使用两个栈来使元素的出栈顺序相同&#xff1b; 通过将栈1元素出栈&#xff0c;再…

Databend 倒排索引的设计与实现

倒排索引是一种用于全文搜索的数据结构。它的主要功能是将文档中的单词作为索引项&#xff0c;映射到包含该单词的文档列表。通过倒排索引&#xff0c;可以快速准确地定位到与查询词相匹配的文档列表&#xff0c;从而大幅提高查询性能。倒排索引在搜索引擎、数据库和信息检索系…

前端 CSS 经典:3D 渐变轮播图

前言&#xff1a;无论什么样式的轮播图&#xff0c;核心 JS 实现原理都差不多。所以小伙伴们&#xff0c;还是需要了解一下核心 JS 实验原理的。 效果图&#xff1a; 实现代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta chars…

MySQL —— 复合查询

一、基本的查询回顾练习 前面两章节整理了许多关于查询用到的语句和关键字&#xff0c;以及MySQL的内置函数&#xff0c;我们先用一些简单的查询练习去回顾之前的知识 1. 前提准备 同样是前面用到的用于测试的表格和数据&#xff0c;一张学生表和三张关于雇员信息表 雇员信息…

优化数据查询性能:StarRocks 与 Apache Iceberg 的强强联合

Apache Iceberg 是一种开源的表格格式&#xff0c;专为在数据湖中存储大规模分析数据而设计。它与多种大数据生态系统组件高度兼容&#xff0c;相较于传统的 Hive 表格格式&#xff0c;Iceberg 在设计上提供了更高的性能和更好的可扩展性。它支持 ACID 事务、Schema 演化、数据…

leetcode-设计LRU缓存结构-112

题目要求 思路 双链表哈希表 代码实现 struct Node{int key, val;Node* next;Node* pre;Node(int _key, int _val): key(_key), val(_val), next(nullptr), pre(nullptr){} };class Solution { public: unordered_map<int, Node*> hash; Node* head; Node* tail; int …

普源DHO924示波器OFFSET设置

一、简介 示波器是电子工程师常用的测量工具之一&#xff0c;能够直观地显示电路信号的波形和参数。普源DHO924是一款优秀的数字示波器&#xff0c;具有优异的性能和易用性。其中OFFSET功能可以帮助用户调整信号的垂直位置&#xff0c;使波形更清晰易读。本文将详细介绍DHO924…

声音转文本(免费工具)

声音转文本&#xff1a;解锁语音技术的无限可能 在当今这个数字化时代&#xff0c;信息的传递方式正以前所未有的速度进化。从手动输入到触控操作&#xff0c;再到如今的语音交互&#xff0c;技术的发展让沟通变得更加自然与高效。声音转文本&#xff08;Speech-to-Text, STT&…

爬虫学习--12.MySQL数据库的基本操作(下)

MySQL查询数据 MySQL 数据库使用SQL SELECT语句来查询数据。 语法&#xff1a;在MySQL数据库中查询数据通用的 SELECT 语法 SELECT 字段1&#xff0c;字段2&#xff0c;……&#xff0c;字段n FROM table_name [WHERE 条件] [LIMIT N] 查询语句中你可以使用一个或者多个表&…