CUDA 线程层次分为:
<<<..>>>
内的执行设置的第一个参数,Giga threads engine 将 block 分配到 SM 中。一个 Block 内的线程一定会在同一个 SM 内,一个 SM 可以有很多个 Block<<<..>>>
内的执行设置的第二个参数,Warp 调度器会将调用线程CUDA 的一切精髓就是并行加速冲冲冲!
首先来看看基本概念:
threadIdx.[x y z]
是执行当前kernel函数的线程在block中的索引值(threadIdx.x是1,threadIdx.y是0)
blockIdx.[x y z]
是指执行当前kernel函数的线程所在block,在grid中的索引值(blockIdx.x是1,blockIdx.y是1)
blockDim.[x y z]
表示一个block中包含多少个线程(blockDim.x是5,blockDim.y是3)
gridDim.[x y z]
表示一个grid中包含多少个block(gridDim.x是3,gridDim.y是2)
计算矩阵运算的时候,将矩阵中的一行取出来,但是因为 CUDA 是多个线程并行的,就是每个线程里面都会同时获取到矩阵行中的某个元素,我们就需要在核函数里面计算出来这个元素在原来矩阵行中的索引,下面是个例子:
接下来,我们通过完成一个向量加法的实例来实践一下: 。
为了完成这个程序,我们先要将数据传输给GPU,并在GPU完成计算的时候,将数据从GPU中传输给CPU内存。这时我们就需要考虑如何申请GPU存储单元,以及内存和显存之前的数据传输。
我们利用cudaMalloc()来进行GPU存储单元的申请,利用cudaMemcpy()来完成数据的传输
代码如下:
#include
#include void __global__ add(const double *x, const double *y, double *z, int count)
{const int n = blockDim.x * blockIdx.x + threadIdx.x;if( n < count){z[n] = x[n] + y[n];}}
void check(const double *z, const int N)
{bool error = false;for (int n = 0; n < N; ++n){if (fabs(z[n] - 3) > (1.0e-10)){error = true;}}printf("%s\n", error ? "Errors" : "Pass");
}int main(void)
{const int N = 1000;const int M = sizeof(double) * N;double *h_x = (double*) malloc(M);double *h_y = (double*) malloc(M);double *h_z = (double*) malloc(M);for (int n = 0; n < N; ++n){h_x[n] = 1;h_y[n] = 2;}double *d_x, *d_y, *d_z;cudaMalloc((void **)&d_x, M);cudaMalloc((void **)&d_y, M);cudaMalloc((void **)&d_z, M);cudaMemcpy(d_x, h_x, M, cudaMemcpyHostToDevice);cudaMemcpy(d_y, h_y, M, cudaMemcpyHostToDevice);const int block_size = 128;const int grid_size = (N + block_size - 1) / block_size;add<<>>(d_x, d_y, d_z, N);cudaMemcpy(h_z, d_z, M, cudaMemcpyDeviceToHost);check(h_z, N);free(h_x);free(h_y);free(h_z);cudaFree(d_x);cudaFree(d_y);cudaFree(d_z);return 0;
}
上一篇:回归分析(2) 一元回归模型