对于一维案例,我已经非常了解 CUDA 中全局内存的整个合并访问要求。
但是我对二维情况有点卡住了(也就是说,我们有一个二维网格,由二维块组成)。
假设我有一个向量in_vector
,并且在我的内核中我想以合并的方式访问它。像这样:
__global__ void my_kernel(float* out_matrix, float* in_vector, int size)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
// ...
float vx = in_vector[i]; // This is good. Here we have coalesced access
float vy = in_vector[j]; // Not sure about this. All threads in my warp access the same global address. (See explanation)
// ...
// Do some calculations... Obtain result
}
在我对这种 2D 案例的理解中,块内的线程以列为主的方式“排列”。例如:假设一个 (threadIdx.x, threadIdx.y) 符号:
- 第一个扭曲是:(0, 0), (1, 0), (2, 0), ..., (31, 0),
- 第二个扭曲将是:(0, 1), (1, 1), (2, 1), ..., (31, 1),
- 等等...
在这种情况下,调用in_vector[i]
给了我们一个合并的访问,因为同一个 warp 中的每个连续线程都将访问连续的地址。然而调用in_vector[j]
似乎是一个坏主意,因为每个连续线程将访问全局内存中的相同地址(例如,warp 0 中的所有线程都将访问 in_vector[0],这将给我们 32 个不同的全局内存请求)
我理解正确吗?如果是这样,我怎样才能使用合并访问全局内存in_vector[j]
?