基本原理
ID排列顺序
一个线程需要两个内置的坐标变量来唯一表示(blockidx, threadidx),它们都是dim3的类型,blockidx指明线程在block中的位置,threadidx中的位置。
以上两者都包含三个值: x, y, z
逻辑顺序为:x > y > z
举例:dim3 grid(3,2) block(5, 3)

每个GPU有多个MP,通过L1/L2缓存访问全局内存 Gloabl Memory
GPU内存类型
可编程内存
寄存器
共享内存的访问冲突
常量内存
纹理内存
全局内存
全局内存对齐访问
GPU缓存

基本知识
GPU全局内存分配释放
Host内存属于CPU内存,传输速度比普通CPU内存快很多
统一(Unified)内存分配释放

CPU与GPU内存同步拷贝

CPU与GPU内存异步拷贝

共享内存

#include
#include
typedef double FLOAT;
__global__ void sum(FLOAT *x) // 定义核函数,在device上运行
{
int tid = threadIdx.x; // threadIdx.x 为内置变量,自带的
x[tid] += 1;
}
int main()
{
int N = 32; // 准备开32个线程
int nbytes = N * sizeof(FLOAT); // 准备开的内存空间
FLOAT *dx = NULL, *hx = NULL; // dx->device, hx->host
int i;
/* allocate GPU mem */
cudaMalloc((void **)&dx, nbytes); // device上开辟内存
if (dx == NULL) { // 如果 dx 为空 分配内存失败
printf("couldn't allocate GPU memory\n");
return -1;
}
/* alllocate CPU host mem: memory copy is faster than malloc */
hx = (FLOAT *)malloc(nbytes); // 开辟普通内存
if (hx == NULL) {
printf("couldn't allocate CPU memory\n");
return -2;
}
/* init */
printf("hx original: \n");
for (i = 0; i < N; i++) {
hx[i] = i; // 向量初始化
printf("%g\n", hx[i]);
}
/* copy data to GPU */
// cudaMemcpy(dx, hx, nbytes, cudaMemcpyHostToDevice);
cudaMemcpy(dx, hx, nbytes, cudaMemcpyHostToDevice);
/* call GPU */
// grid_size 设置为 1,block_size 设置为 N,表示一维的线程
sum<<<1, N>>>(dx); // 传入参数 dx,表示GPU上的内存
/* let GPU finish */
cudaDeviceSynchronize(); // 等 GPU 线程全部跑完,等同步
/* copy data from GPU */
cudaMemcpy(hx, dx, nbytes, cudaMemcpyDeviceToHost); // GPU上的内存copy到CPU上
printf("\nhx from GPU: \n");
for (i = 0; i < N; i++) {
printf("%g\n", hx[i]);
}
// 释放内存
cudaFree(dx);
free(hx);
return 0;
}
#include
#include
#include "aux.h"
typedef double FLOAT;
__global__ void sum(FLOAT *x)
{
int tid = threadIdx.x;
x[tid] += 1;
}
int main()
{
int N = 3200000;
int nbytes = N * sizeof(FLOAT);
FLOAT *dx = NULL, *hx = NULL, *h2x = NULL;
int i;
/* allocate GPU mem */
cudaMalloc((void **)&dx, nbytes);
if (dx == NULL) {
printf("couldn't allocate GPU memory\n");
return -1;
}
/* alllocate CPU host mem: memory copy is faster than malloc */
cudaMallocHost((void **)&h2x, nbytes);
hx = (FLOAT *)malloc(nbytes);
if (hx == NULL) {
printf("couldn't allocate CPU memory\n");
return -2;
}
if (h2x == NULL) {
printf("couldn't allocate h2x CPU memory\n");
return -2;
}
// start time
double td = get_time();
/* init */
for (i = 0; i < N; i++) {
hx[i] = i;
}
/* copy data to GPU */
cudaMemcpy(dx, hx, nbytes, cudaMemcpyHostToDevice);
/* call GPU */
sum<<<1, N>>>(dx);
/* let GPU finish */
cudaDeviceSynchronize();
td = get_time()-td;
/* copy data from GPU */
cudaMemcpy(hx, dx, nbytes, cudaMemcpyDeviceToHost);
printf("普通内存 hx Time: %e \n", td);
td = get_time();
/* init */
for (i = 0; i < N; i++) {
h2x[i] = i;
}
/* copy data to GPU */
cudaMemcpy(dx, h2x, nbytes, cudaMemcpyHostToDevice);
/* call GPU */
sum<<<1, N>>>(dx);
/* let GPU finish */
cudaDeviceSynchronize();
td = get_time()-td;
/* copy data from GPU */
cudaMemcpy(h2x, dx, nbytes, cudaMemcpyDeviceToHost);
printf("host内存 h2x Time: %e \n", td);
cudaFree(dx);
cudaFreeHost(h2x);
free(hx);
return 0;
}

可以看到host内存比CPU普通内存快一个数量级向上。
CUDA程序架构以及硬件映射

GPU流式多处理器
Warp技术细节
资源限制
Thread),单指令多线程的架构,基本的执行单元是线程束 warp,包含32个线程。
* 线程束中的线程同时从同一程序地址执行,但是可能具有不同的行为,比如遇到了分支结构,一些可能进入分支,一些可能不执行,只有死等。
* GPU规定线程束中所有的线程在同一周期执行相同的指令,线程束分化会导致性能的下降。