热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Cuda中Globalmemory中coalescing例程解释

Globalmemory是cuda中最常见的存储类型,又叫做Devicememory,位于Host主机区域上,它的生命周期是在整个Grid
Global memory是cuda中最常见的存储类型,又叫做Device memory,位于Host主机区域上,它的生命周期是在整个Grid里面,大约具有500个cycle latency。在cuda并行程序中,尽量用Coalesing accessing的策略来最大化带宽bandwidth。什么是Coalesing accessing呢?如图所示:







当半个Warp的16个threads在一次memory transaction中coalesced时,Global memory中的带宽得到了最大的利用。其中,需要注意的是,Device在一次transaction中,从global memory中可以一次读取32-bit,64-bit,128-bit,例如

64 bytes - each thread reads a word: int, float, …

128 bytes - each thread reads a double-word: int2, float2, …

32 bytes (compute capability 1.2+) - each thread reads a short  int.

下面有两个实例来说明Global memory中的coalescing问题:

1)float3型Uncoalesced

__global__ void accessFloat3(float3 *d_in,
float3* d_out)
{
int index = blockIdx.x * blockDim.x + threadIdx.x;
float3 a = d_in[index];
a.x += 2;
a.y += 2;
a.z += 2;
d_out[index] = a;
}







在这段代码中,float3有12个bytes,不等于要求的4,8,16 bytes,半个warp读取3个64bytes中非连续区域,如图:







有三种方法可以解决这个问题

1:使用shared memory,也叫做3-step approach

假如每个block中使用256个threads,这样一个thread block需要 sizeof(float3)*256 bytes的share memory空间,每个thread读取3个单独的float型,这实质上是指讲输入定义为float型,在核函数里面讲读取在share memory中的float变量转换为float3型并进行操作,最后再转换成float型输出,如图;






代码如下:



如果不好理解的话,假设我们的blockDim=4,取4个float3型变量,我们会发现,每一个thread中输入操作(输出操作一样)为:

Thread 0:

S_data[0]=g_in[0]; S_data[4]=g_in[4]; S_data[8]=g_in[8];

Thread 1:
S_data[1]=g_in[1]; S_data[5]=g_in[5]; S_data[9]=g_in[9];
Thread 2:
S_data[2]=g_in[2]; S_data[6]=g_in[6]; S_data[10]=g_in[10];
Thread 3:
S_data[3]=g_in[3]; S_data[7]=g_in[7]; S_data[11]=g_in[11];
可以看出,对于每个thread同一时刻(similar step)的数据读入,地址均是连续,这样就达到了coalescing。
2)使用数组的结构体(SOA)来取代结构体的数组(AOS)




3)使用alignment specifiers

__align__(X), where X = 4, 8, or 16

struct __align__(16) {float x; float y;  float z; };

尽管这损失了比较多的空间:



2)第二个实例:矩阵转置 Matrix Transpose.

一般做法:Uncoalesced Transpose,GMEM为Global memory



我们发现一般的做法,在写output时,地址是不连续的,即uncoalesced,因此我们利用shared memory存储输入数据,根据转置的关系,来实现coalescing,SMEM为shared memory,如下图:



代码如下:

__global__ void transpose(float *odata, float *idata, int width, int height)

{

__shared__ float block[BLOCK_DIM*BLOCK_DIM];

unsigned int xBlock = blockDim.x * blockIdx.x;

unsigned int yBlock = blockDim.y * blockIdx.y;

unsigned int xIndex = xBlock + threadIdx.x;

unsigned int yIndex = yBlock + threadIdx.y;

unsigned int index_out, index_transpose;

if (xIndex

{

unsigned int index_in = width * yIndex + xIndex;

unsigned int index_block = threadIdx.y * BLOCK_DIM + threadIdx.x;

block[index_block] = idata[index_in];

index_transpose = threadIdx.x * BLOCK_DIM + threadIdx.y;

index_out = height * (xBlock + threadIdx.y) + yBlock + threadIdx.x;

}

__syncthreads();

if (xIndex

odata[index_out] = block[index_transpose];

程序的逻辑关系有时还挺绕的,我们以一个4*4矩阵为例,将逻辑关系展示如下:



设dim3 gridDim(4,1), dim3 blockDim(1,4),以橙色block为例,如输入数据时,将其放入到sharememory中,代码体现在:

unsigned int index_in = width * yIndex + xIndex;
unsigned int index_block = threadIdx.y * BLOCK_DIM + threadIdx.x;
block[index_block] = idata[index_in];
接下来的代码实际上是将block的区域给换了,如左下图所示,block换成了一列四种不同颜色的,最终转置的矩阵如右下图所示,从图示可以看出,最终结果的坐标系Height、Width、blockIdx.x、blockIdx.y均对位变换了,这时我们只需要找threadIdx.x'、threadIdx.y'与threadIdx.x、threadIdx.y之间的关系,其实可以看出,一个block里面的坐标系没有发生变换,则threadIdx.x'=threadIdx.x,threadIdx.y'=threadIdx.y,所以代码如下:
index_transpose = threadIdx.x * BLOCK_DIM + threadIdx.y;
index_out = height * (xBlock + threadIdx.y) + yBlock + threadIdx.x;
odata[index_out] = block[index_transpose];

总体来说,Global memory中coalescing就是保证其在数据读取或者写入时,使用连续的地址,且地址所存储的变量尺寸为32、64、128 bit,我们常常使用share memory来解决coalescing问题。





推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • LeetCode笔记:剑指Offer 41. 数据流中的中位数(Java、堆、优先队列、知识点)
    本文介绍了LeetCode剑指Offer 41题的解题思路和代码实现,主要涉及了Java中的优先队列和堆排序的知识点。优先队列是Queue接口的实现,可以对其中的元素进行排序,采用小顶堆的方式进行排序。本文还介绍了Java中queue的offer、poll、add、remove、element、peek等方法的区别和用法。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • 本文介绍了OpenStack的逻辑概念以及其构成简介,包括了软件开源项目、基础设施资源管理平台、三大核心组件等内容。同时还介绍了Horizon(UI模块)等相关信息。 ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
author-avatar
Rain雨露Dew
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有