ps:这是英伟达二面面的一道相关CUDA的题目。《NVIDIA CUDA编程指南》第57页开始

         在合并访问这里,不要跟shared memory的bank conflict搞混淆了,这里很重要。

         global memory没有被缓存(面试答错了!),因此,使用正确的存取模式来获得最大的内存带宽,更为重要,尤其是如何存取昂贵的设备内存device
memory。

         首先,设备device有能力,在一个单一指令下,从global memory中读取32-bit, 64-bit, 128-bit字进入寄存器register。
         分配如下:


__device__ type device[32];

type data = device[tid];

编译一个单一加载指令,type必须是sizeof(type) = 4、8 或者 16 这样的,

                                            而且要求内置类型像float2 或 float4 一样的自动完成的。
对于结构、大小和队列要求可以通过编译器强制使用队列指定的__align__(8) 或 __align__(16),
例如


struct __align(8)__{

float a;

float b;

};

//或者是

struct __align(16)__{
float a;
float b;

float c;
};

对于结构 > 16字节的,编译器生成几个加载指令,来保证它生成最低数量的指令,这样的结构应该用__align__(16)定义

例如:


struct __align(16)__{
float a;
float b;

float c

float d

float e;

};

//!被编译成两个128-bit的加载指令,而不是5个32-bit加载指令

其次,全局内存地址同时被每线程的一个half-warp访问(执行读和写指令)时,应该排列好,以便内存的存取可以结合进入一个接近单一的,排列好的内存存取。

         它意味着,在每一个half-warp中,在half-warp中的第N个线程应该访问该地址。


HalfWarpBaseAddress + N

这里,HalfWarpBaseAddress  是类型 type* ,而 type 应该符合之前讨论过的大小和队列要求。
         HalfWarpBaseAddress应该排列成16 * sizeof ( type ) 字节,例如16 * sizeof ( type ) 的倍数。
 任何一个驻留在全局内存BaseAddress的变量的地址,或者一个来自 D.5 或 E.8 部分内存分配规则返回的地址,问题被排列成至少256个字节,以此来满足内存队列的约束,

HalfWarpBaseAddress - BaseAddress 应该是 16 * sizeof ( type ) 的倍数

注意:如果一个half-warp满足了上面的所有需求,那么每线程的内存访问被联合了,即使half-warp的一些线程实际上没有访问内存。

建议:对于整个warp满足这个需求,而不是分开的,半个半个的。
            因为未来的设备将默认为必要的要求。
示例:联合的 64-bit 访问会比联合的 32-bit 访问内存带宽低一点,
            联合的128-bit访问会比联合的32-bit访问内存带宽要低很多。
  

 
一个公共的全局内存访问样式是,当每个带有线程ID tid 的线程访问位于一个数组的一个元素时,元素的地址位于类型 type* 的 BaseAddress,使用以下地址

BaseAddress + tid

为了获得内存的联合,type 必须符合之前讨论过的大小和队列的要求。

如果 type 的结构 > 16字节,它应该被分成几个满足要求的结构,并且数据应该在内存中被划分成关于这些结构的几个数组,而不是一个类型 type* 的单一数组。
另一个公共的全局内存访问样式是,
当带有索引 (tx, ty) 的每条线程访问地址位于类型 type* 的BaseAddress 和宽度 width 的2D数组的一个元素使用以下地址:

BaseAddress + width * ty + tx

在这样的情况下,获得 half-warp 的所有块线程的内存结合,只有当

a. 块线程的宽度是一半warp大小的倍数
b. width 是16 的倍数
特别是,这意味着,宽度不是16的倍数的数组将被更高效地访问,如果它实际上分配是宽度被传入到最接近16的倍数而且,它的列因此被填充了。
cudaMallocPitch() 和 cuMemAllocPitch() 函数和在D.5和E.8 部分描述的相关内存拷贝的函数,使开发人员能够编写非硬件独立的代码,来分配遵循这些约束的数组。

【并行计算-CUDA开发】有关CUDA当中global memory如何实现合并访问跟内存对齐相关的问题的更多相关文章

  1. 【CUDA开发】CUDA面内存拷贝用法总结

    [CUDA开发]CUDA面内存拷贝用法总结 标签(空格分隔): [CUDA开发] 主要是在调试CUDA硬解码并用D3D9或者D3D11显示的时候遇到了一些代码,如下所示: CUdeviceptr g_ ...

  2. 【并行计算-CUDA开发】CUDA shared memory bank 冲突

    CUDA SHARED MEMORY shared memory在之前的博文有些介绍,这部分会专门讲解其内容.在global Memory部分,数据对齐和连续是很重要的话题,当使用L1的时候,对齐问题 ...

  3. 【并行计算-CUDA开发】CUDA bank conflict in shared memory

    http://hi.baidu.com/pengkuny/item/c8070b388d75d481b611db7a 以前以为 shared memory 是一个万能的 L1 cache,速度很快,只 ...

  4. 【并行计算-CUDA开发】CUDA存储器模型

    CUDA存储器模型 除了执行模型以外,CUDA也规定了存储器模型(如图2所示)和一系列用于主控CPU与GPU间通信的不同地址空间.图中红色的区域表示GPU片内的高速存储器,橙色区域表示DRAM中的的地 ...

  5. 【并行计算-CUDA开发】CUDA ---- Warp解析

    Warp 逻辑上,所有thread是并行的,但是,从硬件的角度来说,实际上并不是所有的thread能够在同一时刻执行,接下来我们将解释有关warp的一些本质. Warps and Thread Blo ...

  6. 【并行计算-CUDA开发】CUDA软件架构与Nvidia硬件对应关系

    前面扯了很多,不过大多都是在讲CUDA 在软体层面的东西:接下来,虽然Heresy 自己也不熟,不过还是来研究一下硬体的部分吧-毕竟要最佳化的时候,好像还是要大概知道一下相关的东西的.这部分主要参考资 ...

  7. 【并行计算-CUDA开发】CUDA并行存储模型

    CUDA并行存储模型 CUDA将CPU作为主机(Host),GPU作为设备(Device).一个系统中可以有一个主机和多个设备.CPU负责逻辑性强的事务处理和串行计算,GPU专注于执行高度线程化的并行 ...

  8. 【CUDA开发】CUDA从入门到精通

    CUDA从入门到精通(零):写在前面 在老板的要求下,本博主从2012年上高性能计算课程开始接触CUDA编程,随后将该技术应用到了实际项目中,使处理程序加速超过1K,可见基于图形显示器的并行计算对于追 ...

  9. 【CUDA开发】CUDA编程接口(一)------一十八般武器

    子曰:工欲善其事,必先利其器.我们要把显卡作为通用并行处理器来做并行算法处理,就得知道CUDA给我提供了什么样的接口,就得了解CUDA作为通用高性能计算平台上的一十八般武器.(如果你想自己开发驱动,自 ...

随机推荐

  1. windows 切换git远程仓库地址后 git push 提示Authentication failed

    git切换远程分支: 方法一: git remote set-url origin 你新的远程仓库地址 方法二: git remote rm origin git remote add origin ...

  2. Codeforces Round #589 (Div. 2) A. Distinct Digits

    链接: https://codeforces.com/contest/1228/problem/A 题意: You have two integers l and r. Find an integer ...

  3. 使用yum命令出错:SyntaxError: invalid syntax 由于用户取消而退出

    详见: https://blog.csdn.net/qq_24880013/article/details/90731617 必须修改的两个yum配置文件: 因为yum使用python2,因此替换为p ...

  4. BZOJ 2346: [Baltic 2011]Lamp Dijkstra

    不难发现如果一个边的方向改变,就一定不会改回来(这样肯定不是最短路). 所以就直接建双向边,边权为 $0$ 代表不改变,边权为 $1$ 代表改变,跑一个最短路即可. #include <bits ...

  5. IDEA checkout Git 分支 弹出 Git Checkout Problem

    1. 本地分支切换的时候(例如A切到B),会弹出来Restore workspace on branch switching 对话框,如果选择是的话,在切换分支的时候,你在当前分支(A)所做的一些还未 ...

  6. C/C++程序基础-C++与C有什么不同

    1:C和C++的联系和区别? 答:C是一个结构化语言,它的重点在于算法和数据结构.对于语言本身而言,C是C++的子集.C程序的设计首先要考虑的是如何通过一个过程,对输入进行运算处理,得到输出.对于C+ ...

  7. 数据结构-用C++实现一个二叉树,递归方法中序遍历

    1:二叉排序树,又称二叉树.其定义为:二叉排序树或者空树,或者是满足如下性质的二叉树. (1)若它的左子树非空,则左子树上所有节点的值均小于根节点的值. (2)若它的右子树非空,则右子树上所有节点的值 ...

  8. eclipse异常:Exception in thread ""http-bio-8080"-exec-5" java.lang.OutOfMemoryError: PermGen space

    用eclipse运行项目,最烦的就是非代码错误.现在这个异常信息,表示的是tomcat启动内存溢出.试过的最简单的办法就是eclipse->project->clean->clean ...

  9. caps lock 映射成 esc,右Ctrl映射右移

    xmodmap -e 'clear Lock' -e 'keycode 0x42 = Escape' xmodmap -e 'clear Lock' -e 'keycode 105= Right'

  10. Flume-Replicating Channel Selector 单数据源多出口

    使用 Flume-1 监控文件变动,Flume-1 使用 Replicating Channel Selector 将变动内容传递给 Flume-2,Flume-2 负责存储到 HDFS.同时 Flu ...