CUDA 学习(十一)、共享内存
来源:互联网 发布:mysql中if exists用法 编辑:程序博客网 时间:2024/05/29 09:48
一、概述
共享内存实际上是可受用户控制的一级缓存。每个SM 中的一级缓存与共享内存一个64KB 的内存段。在开普勒架构的设备中,根据应用程序的需要,每个线程可以配置为16KB 的一级缓存或共享内存。而在费米架构的设备中,可以根据喜好选择16KB 或 48 KB 的一级缓存或共享内存。早期的费米架构的硬件(计算能力为1.x)中只有固定的16KB 共享内存而没有一级缓存。共享内存的延迟极低,大约有1.5 TB/s 的带宽,远远高于全局内存的190GB/s, 但是它的速度只有寄存器的1/10。
实际上,仅看带宽数据,共享内存的带宽为1.5 TB/s,全局内存的带宽最高为190 GB/s,比率为7:1 。换言之,有效使用共享内存有可能获得7倍的加速比。毫无疑问,共享内存是所有关心性能的CUDA 程序员应该认真掌握的一个概念。
然而,GPU 执行的是一个内存加载/ 存储模型,即所有的操作都要在指令载入寄存器之后才能执行。因此,加载数据到共享内存与加载数据到寄存器中不同,只有当数据重复利用,全局内存合并,或线程之间有共享数据时使用共享内存才更合适。否则,将数据直接从全局内存加载到寄存器性能会更好。
二、共享内存存储体
共享内存是基于存储体切换的架构(bank-switched architecture)。在费米架构设备上有32个存储体,而在G200与G80 的硬件上只有16个存储体。每个存储体可以存放4个字节大小的数据,足以用来存储一个单精度的浮点型数据,或者一个标准的32位的整型数。开普勒架构的设备还引入了64位宽的存储体,使双精度的数据无须再跨越两个存储体。无论有多少线程发起操作,每个存储体每个周期只执行一次操作。因此,如果线程束中的每个线程访问一个存储体,那么所有线程的操作都可以在一个周期内同时执行。此时无须顺序地访问,因为每个线程访问的存储体在共享内存中都是独立的,互不影响。
注意,线程访问共享内存需要排队等待,当一个线程访问共享内存时,线程束中的其他线程将阻塞闲置。这方面一个很重要的问题就是延迟并没有因为切换到另一个线程而得到隐藏,事实上我们将整个SM都阻塞了。由于SM 会处于闲置状态直到存储体请求被满足,因此,存储体冲突应尽可能地避免。
bank冲突:最糟糕的情形就是所有的线程都对同一个存储体执行写操作,这将导致对同一存储体顺序进行32次访问操作。典型地,当跨服超过32时,就会发生多个线程访问同一个存储体。当跨幅以二的幂次倍减少时,也会发生这种情况,连续的轮询将导致更多的存储体冲突。
三、避免存储体冲突
通过将数据集以每行32个元素方式在共享内存中进行划分,然后线程以列的方式进行访问,我们可以获得零存储体冲突的内存访问。
- CUDA 学习(十一)、共享内存
- CUDA学习--内存处理之共享内存(3)
- CUDA入门学习(三):共享内存与线程同步
- [CUDA]共享内存
- CUDA总结:共享内存
- CUDA学习笔记十一
- CUDA学习笔记(6) 共享内存与全局内存
- CUDA 学习(九)、CUDA 内存
- cuda《学习笔记三》——共享内存和同步
- CUDA学习: 共享存储器
- CUDA 共享内存的动态分配
- CUDA 共享内存 bank conflict
- CUDA 共享内存 bank conflict
- CUDA编程(七)共享内存与Thread的同步
- CUDA编程(七)共享内存与Thread的同步
- 《GPU高性能编程CUDA实战》学习笔记(十一)
- CUDA 学习(二十一)、优化策略6: 资源竞争
- GPU(CUDA)学习日记(十三)------ CUDA内存简介
- 3.java设计模式(读书笔记)适配器模式
- (一)RecyclerView简单使用总结
- 如何给magento的产品分类创建一个自定义属性?
- Linux入门:常用命令:rpm、yum
- 帮助命令
- CUDA 学习(十一)、共享内存
- php请求url过长改用curl
- 打开文件练习
- android:includeFontPadding的使用:清除TextView字体周边空白
- oracle表的创建及管理 主键自增 外键等
- 转载获取路径C#中AppDomain.CurrentDomain.BaseDirectory与Application.StartupPath的区别
- js中cookie使用详细讲解
- WinSock2.h(109) : error C2011: 'fd_set' : 'struct' type redefinition
- 导致MyEclipse内存不足的原因分析及解决办法