首页 > 解决方案 > CUDA 索引 blockDim.y 始终为 1

问题描述

我正在尝试用共享内存解决二维拉普拉斯方程。但是一件奇怪的事情是 blockDim.y 的值总是 1。有人可以帮我吗?

主机代码

checkCudaErrors(cudaMalloc((void**)&d_A, h*h * sizeof(float)));
checkCudaErrors(cudaMalloc((void**)&d_out, h*h * sizeof(float)));
checkCudaErrors(cudaMemcpy(d_A, A, h*h * sizeof(float), cudaMemcpyHostToDevice));
dim3 blockSize = (BLOCK_SIZE, BLOCK_SIZE);
dim3 gridSize = ((h+BLOCK_SIZE-1)/BLOCK_SIZE, (h + BLOCK_SIZE - 1) / BLOCK_SIZE);

LaplaceDifference << <gridSize, blockSize >> > (d_A, h, d_out);
checkCudaErrors(cudaMemcpy(B, d_out, h*h * sizeof(float), cudaMemcpyDeviceToHost));

内核代码

int idx = blockIdx.x*blockDim.x + threadIdx.x;
int idy = blockIdx.y*blockDim.y + threadIdx.y;


__shared__ float A_ds[BLOCK_SIZE + 2][BLOCK_SIZE + 2];

int n = 1;
//Load data in shared memory
int halo_index_left = (blockIdx.x - 1)*blockDim.x + threadIdx.x;
int halo_index_right = (blockIdx.x + 1)*blockDim.x + threadIdx.x;
int halo_index_up = (blockIdx.y - 1)*blockDim.y + threadIdx.y;
int halo_index_down = (blockIdx.y + 1)*blockDim.y + threadIdx.y;

A_ds[n + threadIdx.y][n + threadIdx.x] = A[idy * h +idx];

if (threadIdx.x >= blockDim.x - n) {
    A_ds[threadIdx.y + n][threadIdx.x - (blockDim.x - n)] = (halo_index_left < 0) ? 0 : A[idy*h + halo_index_left];
}
if (threadIdx.x < n) {
    A_ds[threadIdx.y + n][blockDim.x + n + threadIdx.x] = (halo_index_right >= h) ? 0 : A[idy*h + halo_index_right];
}
if (threadIdx.y >= blockDim.y - n) {
    A_ds[threadIdx.y - (blockDim.y - n)][threadIdx.x+n] = (halo_index_up < 0) ? 0 : A[halo_index_up*h + idx];
}
if (threadIdx.y < n) {
    A_ds[blockDim.y + n + threadIdx.y][threadIdx.x + n] = (halo_index_down >= h) ? 0 : A[halo_index_down*h + idx];
}


__syncthreads();

P[idy*h + idx] = 0.25*(A_ds[threadIdx.y + n - 1][threadIdx.x + n] + A_ds[threadIdx.y + n + 1][threadIdx.x + n] + A_ds[threadIdx.y + n][threadIdx.x + n - 1] + A_ds[threadIdx.y + n][threadIdx.x + n + 1]);

标签: cuda

解决方案


(我花了很长时间寻找一个骗子,但找不到。)

dim3变量是在 CUDA 头文件中定义的特定数据类型vector_types.h

它提供了几个构造函数。以下是此变量的构造函数的几个有效用法:

dim3 grid(gx, gy, gz);

dim3 grid = dim3(gx, gy, gz);

你所展示的:

dim3 blockSize = (BLOCK_SIZE, BLOCK_SIZE);

不会按您期望的方式工作。

dim3由于等号右侧没有任何用法,编译器将使用其他方法来处理那里的内容。这不是语法错误,因为从 C++ 语言的角度来看,在这种形式下使用括号和逗号都是合法的。

希望您了解括号在 C++ 中的工作原理。我不会尝试描述逗号运算符,您可以在此处此处阅读有关它的内容。最终效果是编译器将对这两个表达式中的每一个进行求值(一个在逗号的左侧,一个在右侧),并且它会将整个表达式的值作为对右侧表达式的求值产生的值来求值。所以这:

(BLOCK_SIZE, BLOCK_SIZE)

变成这样:

BLOCK_SIZE

这显然是一个标量,而不是多维的。

当您将标量分配给 dim3 变量时:

dim3 blockSize = BLOCK_SIZE;

您最终会得到一个具有以下维度的 dim3 变量:

(BLOCK_SIZE, 1, 1)

修复您所拥有的一种方法如下:

dim3 blockSize = dim3(BLOCK_SIZE, BLOCK_SIZE);
                 ^^^^

推荐阅读