GPU编程
GPU结构
每个GPU中有若干个GPC(图形计算簇),每个GPC中又有若干个TPC(Texture Processing cluster), 每个TPC中有若干个SM(Stream Multiprocessor),每个SM中有若干个block,在block中有各种各样的核和寄存器。
在GPU编程中,通常把cpu称作host,把gpu称作device。
计算过程:
- 数据从cpu拷贝到gpu显存中
- 加载GPU程序并运行
- 将运行完后的数据又送回CPU中
CUDA编程
基本结构:
scss
malloc(); |
例如:
reasonml
__global__ void add(int *a, int *b, int *c) |
函数前的标识:
__global__
: 表示在device上执行,从host中调用。它的返回类型必须是void,并且它不会等待函数执行完主线程就会进行下一步。__device__
: 在device上执行,并且从device中调用__host__
: host执行,host调用,默认值
函数中变量类型:
__device__
: grid中所有线程都可以访问__constant__
: 常量内存__shared__
: 只有同一个block中的线程才可以访问
- <<
>>: 调用的基本结构为 grid(网格)->block(块)->thread(线程).例如<<<1, 1>>>代表这个网格中有一个块,这个块中有一个线程。
grid和thread都是dim3型变量,dim3可以看成包含三个整数的结构体。我们可以自由的定义grid或thread为一维、二维或三维,他们的默认值都是1。例如:
mipsasm
dim3 block(3, 3); |
每一个线程都可以用(blockIdx, threadIdx)进行标识,这两个变量都是dim3类型的,因此上面的例子中就可以使用blockIdx.x表示这是第几个block.
变量:
- gridDim: grid维度,dim3型
- blockDim: block维度
- blockIdx:
- threadIdx:
- warpSize: 大小固定为32
每个grid都是在一个SM上的,而SM空间有限,因此每次可以使用的线程是有上限的,一般是1024.
内存分配:
内存分为两种
- 可分配内存: malloc()/new() 操作所得到的内存,这种内存由cpu进行管理,可能被分页机制换下
分页锁定内存: 这种内存受gpu控制,不受cpu调度影响,可以使用dma直接读取
cudaMallocHost(void **ptr, size_t size)
cudaHostAlloc(void **pHost, size_t size, unsigned int flags)
:- cudaHostAllocPortable:多个CPU线程都可访问
- cudaHostAllocWriteCombined:数据传输快,但只允许host写(读速度慢)
- cudaHostAllocMapped:CPU/GPU都可访,属于内存映射
cudaHostRegister( void* ptr, size_tsize, unsigned intflags )
: 可分页内存转换为分页锁定内存
显存分配
- cudaMalloc(): 一维数组,数据连续存储
- cudaMallocPitch(): 二维数组,会自动对齐,可能会浪费部分内存空间
- cudaMalloc3D():三维数组
统一寻址
统一寻址指的是系统自动在host和device之间搬运数据,同时保证host和device都可访问,并且需要进行显式同步。(因为系统会在运行函数时同时进行下一步)
例如:
csharp
__global__ void add(int *ret, int a, int b) |
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment