在CUDA中读取带线程的数组

时间:2012-11-22 11:05:42

标签: cuda gpu

我想知道是否可能,以及在CUDA中使用线程从数组中读取单元格的最佳方法是什么。为了简化我的意思,这是一个例子:

我有一个数组:{1,2,3,4,5,6,...}我希望每个线程主要根据其大小读取数组的n个单元格。

我一直在尝试一些事情,但它似乎没有用,所以如果有人能指出一种(正确的)方法,那就太好了。

谢谢。

2 个答案:

答案 0 :(得分:3)

通常,您希望连续的线程读取连续的数组索引。这样做会导致“合并”的内存事务。想一想的简单方法是,如果32个线程在物理上并行运行,并且它们都负载,那么如果所有32个负载都落入同一个高速缓存行,那么可以执行单个内存访问来填充高速缓存行而不是32个单独的。

所以你要做的是让每个线程访问{(1}}个被线程数量跨越的单元格,如下所示(假设输入数据在n数组float中)

data

如果您的算法要求每个线程读取int idx = blockDim.x * blockIdx.x + threadIdx.x; int stride = blockDim.x * gridDim.x; for (int i = idx; i < numElements; i += stride) { float element = data[i]; process(element); } 个连续的数据元素,那么您将会产生非合并的负载,这将会更加昂贵。在这种情况下,我会考虑重新设计算法,因此不需要这种类型的访问。

答案 1 :(得分:0)

你需要:

  

线程必须查看n个下一个数字

所以你可以使用:

#define N 2
#define NTHREAD 1024
#define ARRAYSIZE N*NTHREAD

// develop the kernel as:
__global__ void accessArray(int *array){
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    int startId = tid*N;

    // access thread's stride
    for(int i=0; i<N; i++){
        array[startId+i]=tid;
    }
}
// call the kernel by:
accessArray<<<NTHREAD/256, 256>>>(d_array);

转储array并检查您的线程是否正常工作。

完整代码:

#include <cuda.h>
#include <stdio.h>


#define N 2
#define NTHREAD 1024
#define ARRAYSIZE N*NTHREAD

// develop the kernel as:
__global__ void accessArray(int *array){
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    int startId = tid*N;

    // access thread's stride
    for(int i=0; i<N; i++){
        array[startId+i]=tid;
    }
}

int  main()
{
    int h_array[ARRAYSIZE];
    int *d_array;
    size_t memsize= ARRAYSIZE * sizeof(float);

    for (int i=0; i< ARRAYSIZE; i++) {
        h_array[i] = 0;
    }

    cudaMalloc(&d_array, memsize);
    cudaMemcpy(d_array, h_array, memsize,  cudaMemcpyHostToDevice);

    accessArray<<<NTHREAD/256, 256>>>(d_array);
    cudaMemcpy(h_array, d_array, memsize,  cudaMemcpyDeviceToHost);

    for (int i=0; i<ARRAYSIZE; i++)
        printf("A[%d] => %d\n",i,h_array[i]);

    cudaFree(d_array);
}