CUDA学习(六)之使用共享内存(shared memory)进行归约求和(M个包含N个线程的线程块)
在https://www.cnblogs.com/xiaoxiaoyibu/p/11402607.html中介绍了使用一个包含N个线程的线程块和共享内存进行数组归约求和,
基本思路:
定义M个包含N个线程的线程块时(NThreadX = ((NX + ThreadX - 1) / ThreadX)),全局线程索引需使用tid = blockIdx.x * blockDim.x + threadIdx.x,而在每个线程块中局部线程索引是i = threadIdx.x,
每个线程块只计算一部分求和,求和结果保存在该线程块中的共享内存数组0号元素中,线程结束后将该值赋给对应全局数组(blockIdx.x * blockDim.x)元素中,最后在CPU端使用循环将每个线程块所求和相加,即得到最后结果。
代码如下:
#pragma once
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "device_functions.h" #include <iostream> using namespace std;
const int NX = ; //数组长度
const int ThreadX = ; //线程块大小
//使用shared memory和多个线程块
__global__ void d_SharedMemoryTest(double *para)
{
int i = threadIdx.x; //该线程块中线程索引
int tid = blockIdx.x * blockDim.x + threadIdx.x; //M个包含N个线程的线程块中相对应全局内存数组的索引(全局线程) __shared__ double s_Para[ThreadX]; //定义固定长度(线程块长度)的共享内存数组
if (tid < NX) //判断全局线程小于整个数组长度NX,防止数组越界
s_Para[i] = para[tid]; //将对应全局内存数组中一段元素的值赋给共享内存数组
__syncthreads(); //(红色下波浪线提示由于VS不识别,不影响运行)同步,等待所有线程把自己负责的元素载入到共享内存再执行下面代码 for (int index = ; index < blockDim.x; index *= ) //归约求和
{
__syncthreads();
if (i % ( * index) == )
{
s_Para[i] += s_Para[i + index];
}
} if (i == ) //求和完成,总和保存在共享内存数组的0号元素中
para[blockIdx.x * blockDim.x + i] = s_Para[i]; //在每个线程块中,将共享内存数组的0号元素赋给全局内存数组的对应元素,即线程块索引*线程块维度+i(blockIdx.x * blockDim.x + i) } //使用shared memory和多个线程块
void s_ParallelTest()
{
double *Para;
cudaMallocManaged((void **)&Para, sizeof(double) * NX); //统一内存寻址,CPU和GPU都可以使用 double ParaSum = ;
for (int i = ; i<NX; i++)
{
Para[i] = (i + ) * 0.01; //数组赋值
ParaSum += Para[i]; //CPU端数组累加
} cout << " CPU result = " << ParaSum << endl; //显示CPU端结果
double d_ParaSum; int NThreadX = ((NX + ThreadX - ) / ThreadX);
cout << " 线程块大小 :" << ThreadX << " 线程块数量 :" << NThreadX << endl; d_SharedMemoryTest << < NThreadX, ThreadX >> > (Para); //调用核函数(M个包含N个线程的线程块) cudaDeviceSynchronize(); //同步 for (int i=; i<NThreadX; i++)
{
d_ParaSum += Para[i*ThreadX]; //将每个线程块相加求的和(保存在对应全局内存数组中)相加求和
} cout << " GPU result = " << d_ParaSum << endl; //显示GPU端结果 } int main() { s_ParallelTest(); system("pause");
return ;
}
结果如下(CPU和GPU结果一致):
CUDA学习(六)之使用共享内存(shared memory)进行归约求和(M个包含N个线程的线程块)的更多相关文章
- linux内核剖析(十一)进程间通信之-共享内存Shared Memory
共享内存 共享内存是进程间通信中最简单的方式之一. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程 ...
- 进程间通信之-共享内存Shared Memory--linux内核剖析(十一)
共享内存 共享内存是进程间通信中最简单的方式之中的一个. 共享内存是系统出于多个进程之间通讯的考虑,而预留的的一块内存区. 共享内存同意两个或很多其他进程訪问同一块内存,就如同 malloc() 函数 ...
- CUDA学习(五)之使用共享内存(shared memory)进行归约求和(一个包含N个线程的线程块)
共享内存(shared memory)是位于SM上的on-chip(片上)一块内存,每个SM都有,就是内存比较小,早期的GPU只有16K(16384),现在生产的GPU一般都是48K(49152). ...
- Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式 ...
- 【CUDA 基础】5.2 共享内存的数据布局
title: [CUDA 基础]5.2 共享内存的数据布局 categories: - CUDA - Freshman tags: - 行主序 - 列主序 toc: true date: 2018-0 ...
- 【CUDA 基础】5.0 共享内存和常量内存
title: [CUDA 基础]5.0 共享内存和常量内存 categories: - CUDA - Freshman tags: - 共享内存 - 常量内存 toc: true date: 2018 ...
- 【转载】Linux进程间通信(六):共享内存 shmget()、shmat()、shmdt()、shmctl()
来源:https://www.cnblogs.com/52php/p/5861372.html 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相 ...
- 共享内存shared pool (3):Library cache
Shared pool物理层面上由许多内存块(chunck)组成.从逻辑功能划分,Shared pool主要由三部分组成:Library cache,Dictionary cache和Control ...
- python学习笔记——多进程中共享内存Value & Array
1 共享内存 基本特点: (1)共享内存是一种最为高效的进程间通信方式,进程可以直接读写内存,而不需要任何数据的拷贝. (2)为了在多个进程间交换信息,内核专门留出了一块内存区,可以由需要访问的进程将 ...
- CUDA学习(四)之使用全局内存进行归约求和(一个包含N个线程的线程块)
问题:使用CUDA进行数组元素归约求和,归约求和的思想是每次循环取半. 详细过程如下: 假设有一个包含8个元素的数组,索引下标从0到7,现通过3次循环相加得到这8个元素的和,使用一个间隔变量,该间隔变 ...
随机推荐
- 洛谷$P2053\ [SCOI2007]$修车 网络流
正解:网络流 解题报告: 传送门$QwQ$ 一个很妙的建图,,,说实话我麻油想到$QwQ$ 考虑对每个工人建$n$个点,表示这是他修的倒数第$i$辆车,就可以算出影响是$t\cdot i$,然后对每辆 ...
- (四)注册登录--重用Django
一.使用已有登录功能 (1)进入Lib\sitepackages\django\contrib\admin\templates\registration下,将对应模板,复制到项目template模板中 ...
- ENS使用指南系列之一 [ 注册 .eth 域名详细教程 ]
ENS 域名系统中目前支持三种顶级域名,分别是 .eth .xyz .luxe.其中, .eth 是 ENS 系统的原生域名,是由一系列智能合约控制的去中心化的域名,另外两种是从互联网域名中接入的,要 ...
- 【原创】(十六)Linux内存管理之CMA
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- JUnit 5和Selenium基础(二)
使用Selenium内置的PageFactory实现页面对象模式 在这一部分中,将通过Selenium的内置PageFactory支持类来介绍Page Object模式的实现.PageFactory提 ...
- NETCore下IConfiguration和IOptions的用法
NETCore下IConfiguration和IOptions的用法 https://www.cnblogs.com/RainingNight/p/strongly-typed-options-con ...
- git查看远程仓库和本地的区别
git diff 你可以用 git diff 来比较项目中任意两个版本的差异. $ git diff master..test 上面这条命令只显示两个分支间的差异,如果你想找出 master , te ...
- 聊一聊 InnoDB 引擎中的索引类型
索引对数据库有多重要,我想大家都已经知道了吧,关于索引可能大家会对它多少有一些误解,首先索引是一种数据结构,并且索引不是越多越好.合理的索引可以提高存储引擎对数据的查询效率. 形象一点来说呢,索引跟书 ...
- mysql 添加/删除列(column)
1.添加 格式:alter table 表名 add column 列名 列的数据类型;示例alter table test4 add column addr text; 2.删除 格式: alter ...
- 痞子衡嵌入式:ARM Cortex-M内核那些事(3.2)- 安全模块看特性(M23/33/35P)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ARM Cortex-M功能模块,不过侧重点是三款安全特性处理器. ARM Cortex-M处理器家族发展至今(2020),已有8代产品 ...