我想知道是否可能,以及在CUDA中使用线程从数组中读取单元格的最佳方法是什么。为了简化我的意思,这是一个例子:
我有一个数组:{1,2,3,4,5,6,...}我希望每个线程主要根据其大小读取数组的n个单元格。
我一直在尝试一些事情,但它似乎没有用,所以如果有人能指出一种(正确的)方法,那就太好了。
谢谢。
答案 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);
}