GPU
cuda核心:
1: 线程组层次结构
2:共享存储器
3:屏蔽同步
基本概念:
1:GPU专为计算密集,高度并行化的计算而设计,GPU的设计使更多的晶体管用于数据处理,而非数据缓存和流控制
2:并行计算,很多个数据元素同时执行一个程序,如果其计算密度高(数学计算和存储器运算的比比率),而所有的数据元素都运行同一个kernel,对精密流控制的要求不高,因此,如果计算密度高,可通过计算隐藏存储器的访问延迟,而不必要使用较大的数据缓存;数据并行编程模型,以数据为中心;
3:程序员定义的kernel --C函数,在调用时,允许N个不同的cuda的线程并行的执行N次,这个与C函数顺序执行的相反;定义Kernel使用 _global描述符,并且每次kernel调用的cuda线程数使用<<<..>>>语法来指定;
4:执行kernel的每一个线程都有一个唯一的id号,该id号和内建threadIdx变量相关联
线程层次:
1:为了方便起见,threadIdx是一个3维向量,使用一维,二维,三维的thread index 目的是为了从一个一维,二维,或者三维的线程块中唯一的标识一个线程;这也很自然的为存取不同维度的元素提供了方便;
2:线程id和线程索引彼此之间有着直接的关联:对于一维的块,它们是相同的,对于大小为(dx,dy)的二维块,线程索引为(x,y)的线程id是(x + y * dx),对于大小为(dx,dy,dz)的三维块,线程索引为(x,y,z)的线程id是(x+yDx+zDx,Dy);
3:为了协调内存访问,同一个块内的线程能通过sharememory共享数据和同步执行来互相合作;使用_syncthreads来同步同一块内线程的访问
4:为了有效的协作,sharememory作为低延迟内存集成在每个多处理器核心中,比较像 L1 Cache,_syncthreads 是轻量级的函数,并且一个块内的所有线程都驻留在同一个多处理内核中。因此,每个block的线程数受到多处理器核心以及内存资源的限制。在当前的 GPU上,一个线程块至多能包含512个线程
5:然而,同一个kernel能被多个相同大小的线程块执行,因此总的线程数等于每块的线程数乘于块的数量,这些块被组织为一个一维或二微的线程块网格(grid),grid的维度由<<< ...>>>的第一个参数指定,在grid中的每个线程块能用一维或者二维的内建blockIdx变量表示,线程块的维度和内建的 BlockDim变量相关联
6:我们随意的将 线程block大小选为16*16(256个线程)并且创建了一个有足够块的线程网格,可将每个线程作为一个矩阵元素(细粒度)
7:线程块必须被独立的执行,它必须能够以任意顺序执行,并行或者顺序执行;这种独立性允许线程块被多个核心以任意的顺序调度执行,从而使程序员写出在可伸缩的代码
8:一个网格内的线程块数量通常是由所处理的数据大小限定的,而不是由系统中的处理器数量决定的,前者可能远远超过后者的数量。
内存层次:
1:cuda线程在执行时可以从多个内存空间中存取数据;每个线程有一个私有的local memory,每个线程块都有一share memory,该内存区对块内所有线程可见并且和块内的线程有相同的生存区,所有的线程都能存取全局内存(global memory)
2:有两种能被所有线程存取的只读内存空间: constant 和 texture 内存空间。全局,常量,纹理内存空间经过优化能使用于不同的用途,。纹理存储器也为某些特殊的数据格式提供了不同的寻址模式以及数据过滤; 3:对于同一个应用程序启动的内核而言,全局、固定和纹理存储器空间都是持久稳定的;也就是说,程序不结束,相应的数据就在相应的存储空间中;主机和设备: cuda编程模型也假定主机和设备各自维护它们自己的DRAM,分别叫host memory,和device memory。因此一个应用程序可以通过调用Cuda运行时函数来管理全局,常量,和纹理内存空间。包含设备内存的分配和重新分配,也包含主机和设备的内存传输;主机执行线性的指令,设备执行并行指令;
阅读(4018) | 评论(0) | 转发(0) |