NVIDIA CUDA 高度并行处理器编程(二):数据并行执行习题

NVIDIA CUDA 高度并行处理器编程(二):数据并行执行习题

  1. 如果一 CUDA 设备的一个 SM 能容纳 1536 个线程和 4 个线程块,下面那种线程块配置使得一个 SM 中能容纳最多的线程?
    a. 每个线程块 128 个线程
    b. 每个线程块 256 个线程
    c. 每个线程块 512 个线程
    d. 每个线程块 1024 个线程
    答:c, 一个 SM 容纳 3 个线程块,共 1536 个线程。

  2. 向量加法中,假定向量长度是 2000, 每个线程产生一个输出元素,每个线程块包含 512 个线程。网格中有多少线程?
    a. 2000
    b. 2024
    c. 2048
    d. 2096
    答:c, ceil(2000/512)= 2048

  3. 上一问题中,对向量长度的边界检查会造成多少数量的 warp 产生分支多样性?
    a. 1
    b. 2
    c. 3
    d. 6
    答:a,最后一个 warp 中的线程一部分满足 if 条件,一部分不满足,warp 内会产生两条控制流路径,即分支多样性。

  4. 编写一个对大小为 400x900 的图片处理函数,用一个线程处理一个像素,线程块为正方形,如何设置网格和线程块的维度,才能使每个线程块包含尽可能多的线程?
    答:网格维度 13x29,线程块维度 32x32.

  5. 上一问设置中,会产生多少个空闲的线程?
    答:16928+28416-16*28 = 26,048

  6. 8个线程组成一个线程块,8个线程执行同一段代码,各个线程所需时间为:2.0, 2.3, 3.0, 2.8, 2.4, 1.9, 2.6, 和 2.9,其余时间等待到达同步点。所有线程用来等待同步点的时间栈总执行时间的百分比为多少?
    答:执行最长时间为 3.0 s,其余线程都要等到 3.0 s,用 3 分别减去所有执行时间,然后相加除以总执行时间和。

  7. 当一个 CUDA 程序员说在一个 kernel 函数中,每个线程块只有 32 个线程时,便能省去__syncthreads() 指令,这样对吗?
    答:表面上是这样的,因为 warp 中的线程时同步执行的。但这样可能会出现问题,最好还是加上。
    参考

  8. 我准备用分块矩阵乘法处理 1024x1024 的矩阵,使用网格大小 32x32,每个线程块有 512 个线程,每个线程处理一个元素,你觉得我行吗?
    答:我不行,总共 1024x512 个线程,但有 1024x1024 个数,每个线程得处理两个元素才行,处理一个不行。

  9. 下面的 kernel 函数用来处理分块矩阵,为了处理分块,一个新手 CUDA 程序员编写了如下的 kernel 函数,用来转置每个分块矩阵。分块的大小为BLOCK_WIDTH*BLOCK_WIDTH, 矩阵 A 的每个维度都是 BLOCK_WIDTH 的倍数,BLOCK_WIDTH的值为1~20, kernel 代码如下所示:

dim3 blockDim(BLOCK_WIDTH,BLOCK_WIDTH);
dim3 gridDim(A_width/blockDim.x,A_height/blockDim.y);
BlockTranspose<<<gridDim, blockDim>>>(A, A_width, A_height);
__global__ void
BlockTranspose(float* A_elements, int A_width, int A_height)
{
    
    
	__shared__ float blockA[BLOCK_WIDTH][BLOCK_WIDTH];
	int baseIdx=blockIdx.x * BLOCK_SIZE + threadIdx.x;
	baseIdx += (blockIdx.y * BLOCK_SIZE + threadIdx.y) * A_width;
	blockA[threadIdx.y][threadIdx.x]=A_elements[baseIdx];
	A_elements[baseIdx]=blockA[threadIdx.x][threadIdx.y];
}

a. BLOCK_WIDTH取什么值能保证 kernel 函数在设备上正确执行?
因为没有使用 __syncthreads(),所以每个线程块最多有 warpsize 个线程,所以 BLOCK_WIDTH 应该为 1~5。大于5的都不行。
b.如果对于所有BLOCK_WIDTH值都不能执行,请修改代码使其能执行。

__shared__ float blockA[BLOCK_WIDTH][BLOCK_WIDTH];

blockA[threadIdx.y][threadIdx.x]=A_elements[baseIdx]

之间加 __syncthreads()。

参考

猜你喜欢

转载自blog.csdn.net/weixin_45773137/article/details/124897806