CUDA在多个数据上合并了一个warp

时间:2015-11-10 15:44:02

标签: c++ cuda

我有一个关于合并cuda访问的基本问题。

例如,我有一个32个元素的数组和32个线程,每个线程访问一个元素。

__global__ void co_acc ( int A[32], int B[32] ) {
    int inx = threadIdx.x + (gridDim.x * blockDim.x);
    B[inx] = A[inx]
}

现在,我想知道:如果我有32个线程,但是有64个元素的数组,每个线程必须复制2个元素。为了保持合并访问,我应该转移 我拥有的线程数的数组访问索引。 例如:ID为0的线程将访问A[0]A[0+32]。我对这个假设是对的吗?

__global__ void co_acc ( int A[64], int B[64] ) {
    int inx = threadIdx.x + (gridDim.x * blockDim.x);
    int actions = 64/blockDim.x;
    for ( int i = 0; i < actions; ++i )
        B[inx+(i*blockDim.x)] = A[inx+(i*blockDim.x)]
}

1 个答案:

答案 0 :(得分:2)

  

为了保持合并访问,我应该将数组访问的索引移动我拥有的线程数。例如:ID为0的线程将访问A [0]和A [0 + 32]。我对这个假设是对的吗?

是的,这是一种正确的方法。

严格来说,它不是 而是可以:只要warp请求中的所有线程都在同一个内部(对齐),任何内存访问都将被合并128字节的行。这意味着你可以置换线程索引,你的访问仍然会被合并(但是为什么你做的很简单时会很复杂)。

另一个解决方案是让每个线程加载int2

__global__ void co_acc ( int A[64], int B[64] ) {
    int inx = threadIdx.x + (gridDim.x * blockDim.x);

    reinterpret_cast<int2*>(B)[inx] = reinterpret_cast<int2*>(A)[inx];
}

这是(在我看来)更简单和更清晰的代码,可能提供稍微更好的性能,因为这可能会减少编译器发出的指令数量和内存请求之间的延迟(免责声明:I没有尝试过。)

  

注意:正如Robert Crovella在评论中提到的,如果你真的使用了32个线程的线程块,那么你可能会严重低估GPU的容量。