Cuda常用概念及注意点
线程的索引计算
只需要知并行线程的初始索引,以及如何确定递增的量值,我们希望每个并行线程从不同的索引开始,因此就需要对线程索引和线程块索引进行线性化,每个线程的其实索引按照以下公式来计算:
int tid = threadIdx.x + blockIdx.x * blockDim.x;
线程块数量限制:65536
线程块中线程数量限制:512
共享内存和同步
共享内存
__share__添加到变量声明,使得声明的变量驻留在共享内存中。cuda c编译器对共享内存中的变量和普通变量采用不同的处理策略,对于GPU启动的每个线程块,cuda c都将创建该变量的一个副本。线程块中的所有线程都会共享这块内存。但线程却无法看到也不能修改其他线程块的变量副本。这是同一个线程块中的不同线程进行通信和协作的基础。
共享内存缓冲区驻留在物理gpu上,访问时延极低。
同步
__syncthreads();对线程块中的线程进行同步。线程发散的容易出现,使得部分场景下的线程同步很有必要。
线程发散:当某些线程需要执行一些指令,而其他线程不需要执行时,这种情况叫做线程发散。在正常环境中,发散的分支会使得某些线程处于空闲状态,而其他线程将执行线程中的代码。在__syncthreads()情况中,线程发散造成的结果有些糟糕,cuda架构将确保,除非线程块中所有的线程都执行了同步操作,否则没有任何线程可以执行同步操作之后的指令。
常量内存与事件
常量内存:NVIDIA提供64k的常量内存,有效减少内存宽带。__constant__ 将变量的访问限制为只读。
从主机内存复制到GPU上的常量内存,使用方法cudaMemcpyToSymbol()进行复制。
性能提升原因
(1)对常量内存的单次操作可以广播到其他邻近线程,节约15次的读写操作;
当处理常量内存时,NVIDIA硬件将单次内存读取操作广播到每个半线程束。
(2)常量内存的数据将缓存起来,因此对相同地址的连续访问不会产生额外的内存通信量。
线程束:warp
在cuda架构中,线程束指的是一个包含32个线程的集合,这些个线程被编制在一起,并且以步调一致(LockStep)的形式执行,在程序中的每一行,线程束中的每个线程都将在不同的数据上执行相同的命令。
事件API
cuda的事件本质上其实就是一个时间戳,这个时间戳就是在用户指定的时间上记录的。获得一个时间戳只有两个步骤:创建一个事件,记录一个事件。
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start, 0);
// gpu执行操作
...
cudaEventRecord(stop, 0);
cudaEventSynchronize(stop);
cudaEventDestroy(start);
cudaEventDestroy(stop);
文理内存(Texture Memory)
简介:
与常量内存类似,只读,缓存在芯片上,减少对内存的请求,并提供更高效的内存带宽。专门为在内存访问模式中存在大量空间局部性(special locality)的图形应用程序而设计。在某个计算应用程序中,这意味着一个线程读取的位置可能与邻近线程读取的位置非常接近。纹理内存专门为加速这种内存访问模式。
纹理存储器中的数据是以一维、二维或者三维数组的形式存储在显存中,可以通过缓存加速访问,并且可以声明大小比常量存储器要大得多。在kernel中访问纹理存储器的操作称为纹理拾取。将显存中的数据和纹理参考系关联的操作,称为将数据和纹理绑定。显存中可以绑定到纹理的数据有两种,分别是普通的线性存储器和cuda数组。
使用步骤:
(1)需要将输入的数据声明为texture类型的引用;声明变量在gpu上;
(2) gpu中分配内存,通过cudaBindTexture()将变量绑定到内存缓冲区。告诉cuda运行时两件事情:
- 我们希望将指定的缓冲区作为纹理来使用;
- 我们希望将纹理引用作为纹理的“名字”。
(3)启动核函数,读取核函数中的纹理时,需要通过特殊的函数来告诉GPU将读取请求转发到纹理内存而不是标准的全局内存,使用编译器内置函数:tex1Dfetch();
(4)释放缓冲区,清除与纹理的绑定,cudaUnbindTexture();
流
页锁定内存
页锁定主机内存,固定内存,不可分页内存,OS将不会对这块内存分页并且交换到磁盘上。从而确保该内存始终驻留在物理内存中。OS可以安全的使某个应用程序访问该内存的物理地址,这块内存将不会被破坏或者重新定位。
- malloc分配的是标准的、可分页的主机内存;
- cudaHostAlloc将分配页锁定的主机内存。
建议:仅对cudaMemcpy()调用的源内存或者目标内存,才能使用页锁定内存,并且在不需要使用他们时,立即释放。
流
支持设备重叠功能的设备,支持设备重叠功能的GPU能够在执行一个CUDA C核函数的同时,还能在设备和主机之间进行复制操作。
一些新的GPU设备同时支持核函数和两次的复制操作,一次是从主机到设备,一次是从设备到主机。在任何支持内存复制和核函数的执行相互重叠的设备上,当使用多个流时,应用程序的整体性能都能得到提升。
判断设备是否支持计算与内存复制操作的重叠:
int main( void ) {
cudaDeviceProp prop;
int whichDevice;
HANDLE_ERROR( cudaGetDevice(&whichDevice) );
HANDLE_ERROR( cudaGetDeviceProperties(&prop, whichDevice) );
if(!prop.deviceOverlap) {
printf("Device will not handle overlaps");
return 0;
}
}
多GPU系统上的CUDA C
零拷贝内存:可以在cuda C核函数中,直接访问这种类型的主机内存,由于这种内存不需要复制到GPU,因此称为零拷贝内存。通过cudaHostAlloc进行分配,最后一个参数采用:cudaHostAllocMapped.
判断设备是否支持映射主机内存:
int main( void ) {
cudaDeviceProp prop;
int whichDevice;
HANDLE_ERROR( cudaGetDevice(&whichDevice) );
HANDLE_ERROR( cudaGetDeviceProperties(&prop, whichDevice) );
if(prop.canMapHostMemory != 1) {
printf("Device can not map memory");
return 0;
}
}
当输入内存和输出内存都只是用一次时,那么在独立GPU上使用零拷贝内存将带来性能提升。
判断某个GPU时集成的还是独立:
cudaGetDeviceProperties()获取属性结构体,该结构中的域:integrated,如果是设备是集成GPU,该值为true,否则为false。
注意:多GPU场景下,每个gpu如果都要运行gpu程序的话,都需要主机cpu启动单独的线程进行资源控制,都有对应自己的线程。
《Programming Massively Parallel Processors: a Hands-On Approach》
Cuda常用概念及注意点的更多相关文章
- 【PS技巧】常用概念和功能操作
常用概念 1.画布大小与图像大小 画布大小是图像背景的大小,即画纸.图像大小是当前编辑的图层的所有对象大小,即画纸上的画. 常用功能操作 1.打开和新建功能 打开图片:Ctrl+O或双击工作区 图片垂 ...
- Python--多线程、多进程常用概念
一.常用概念 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成. 线程 线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干 ...
- NetApp 存储的常用概念普及
NetApp 存储的常用概念和命令1. Volume 和qtree卷(volume)是filer 上的一个基本空间单位,它可以是基于aggr划出的灵活卷(flexvol),也可以是直接由物理盘组成的传 ...
- 007-elasticsearch5.4.3【一】概述、Elasticsearch 访问方式、Elasticsearch 面向文档、常用概念
一.概述 Elasticsearch 是一个开源的搜索引擎,建立在一个全文搜索引擎库 Apache Lucene™ 基础之上. Elasticsearch 也是使用 Java 编写的,它的内部使用 L ...
- Solr入门之(3)常用概念说明(持续补充):
由于solr底层使用lucene,所以很多概念与lucene相同,下面是几个常用的概念: * Document:一个要进行索引的单元,相当于数据库的一行纪录,任何想要被索引的数据,都必须转化为Docu ...
- NSIS打包(一)常用概念简介
1.NSIS简介 官网:http://sourceforge.net/projects/nsis/ 维基百科: http://zh.wikipedia.org/wiki/Nullsoft%E8%85% ...
- python的常用概念
常用的概念 主体字符串 主体列表 内置函数和方法的区别 映射表 引用 迭代器: 1. 字典:单步遍历迭代器 2. 文件:逐行读取的迭代器
- CUDA基本概念
CUDA计算模型 CUDA中计算分为两部分,串行部分在Host上执行,即CPU,而并行部分在Device上执行,即GPU. 相比传统的C语言,CUDA增加了一些扩展,包括了库和关键字. CUDA代码提 ...
- G-sensor概述及常用概念整理【转】
本文转载自:http://www.jianshu.com/p/d471958189a0?nomobile=yesG 本文对G-sensor进行整理,先介绍G-sensor的一些基本概念,再具体讲解BO ...
随机推荐
- Java知识日常收集整理001Java获取变量的数据类型的实现方法
一.具体情况区分 对于简单类型变量,是无法直接获得变量类型的:要想获取,必须自定义函数进行返回. 对于包装类型变量,是可以直接获得的,变量名称.getClass().getName(); 二.代码实现 ...
- P5664 Emiya 家今天的饭
题面 link 前言 去年把我做自闭的一道题,看了一眼题面,发现只有 t1 有点思路,结果写到一半发现自己读错题了,又只能花时间来重构,结果后面的暴力一点都没写(主要是自己当时不会) 然后,这道题还因 ...
- Azure内容审查器之羞羞图审查
上一篇 Azure 内容审查器之文本审查我们已经介绍了如果使用Azure进行文字内容的审核.对于社区内容,上传的图片是否含有羞羞内容也是需要过虑的.但是最为一般开发者自己很难实现这种级别的智能识别.但 ...
- IntelliJ IDEA 调试 Java 8 Stream,实在太香了!
前段时间,栈长发布了一篇关于 Java 8 Optional.map 的实用文章,留言区就有的人说 Java 8 的语法糖不方便调试,还要视情况使用. 留言区也有人说 IntelliJ IDEA 早已 ...
- 《穷查理年鉴》诚实 & 希望 & 勇气 & 失败 & 改变(关于美好)
诚实 013.自欺是最常见的欺骗. 038.毫无顾忌进行欺骗的人是无所畏惧的. 043.问心无愧者永无所惧. 068.诚实的人从欺诈人手中得到的买卖,我们从争论中得到真理. 134.没有欺骗就没有信任 ...
- day56 Pyhton 前端Jquery08
前端 内容回顾: -BOM -jquery介绍 -jquery下载和引入方式 npm install jquery -jquery的选择器 -基本选择器 -通配符选择器 - id选择器 - 类选择器 ...
- pytest文档59-运行未提交git的用例(pytest-picked)
前言 我们每天写完自动化用例后都会提交到 git 仓库,随着用例的增多,为了保证仓库代码的干净,当有用例新增的时候,我们希望只运行新增的未提交 git 仓库的用例. pytest-picked 插件可 ...
- v-model数据绑定分析
v-model数据绑定分析 v-model是Vue提供的指令,其主要作用是可以实现在表单<input>.<textarea>及<select>等元素以及组件上创建双 ...
- 【xenomai内核解析】系列文章大纲
xenomai内核解析 本博客为本人学习linux实时操作系统框架xenomai的一些记录,主要剖析xenomai内核实现,以及与linux相关的知识.方便读者定位具体文章,现列出本博客大纲,后续会陆 ...
- Java改写重构第2版第一个示例
写在前面 <重构:改善既有代码的设计>是一本经典的软件工程必读书籍.作者马丁·福勒强调重构技术是以微小的步伐修改程序. 但是,从国内的情况来而论,"重构"的概念表里分离 ...