【发布时间】:2015-10-15 21:55:33
【问题描述】:
我是 GPU 编程的新手(在 C 语言中相当生疏),所以这可能是一个相当基本的问题,我的代码中有一个明显的错误。我想要做的是获取一个二维数组并找到每一行的每一列的总和。因此,如果我有一个包含以下内容的二维数组:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 2 4 6 8 10 12 14 16 18
我想得到一个包含以下内容的数组:
45
45
90
到目前为止,我的代码没有返回正确的输出,我不知道为什么。我猜这是因为我没有正确处理内核中的索引。但可能是我没有正确使用内存,因为我从一个过度简化的一维示例中调整了它,CUDA Programming Guide(第 3.2.2 节)为初学者在 1和二维数组。
我的错误尝试:
#include <stdio.h>
#include <stdlib.h>
// start with a small array to test
#define ROW 3
#define COL 10
__global__ void collapse( int *a, int *c){
/*
Sum along the columns for each row of the 2D array.
*/
int total = 0;
// Loop to get total, seems wrong for GPUs but I dont know a better way
for (int i=0; i < COL; i++){
total = total + a[threadIdx.y + i];
}
c[threadIdx.x] = total;
}
int main( void ){
int array[ROW][COL]; // host copies of a, c
int c[ROW];
int *dev_a; // device copies of a, c (just pointers)
int *dev_c;
// get the size of the arrays I will need
int size_2d = ROW * COL * sizeof(int);
int size_c = ROW * sizeof(int);
// Allocate the memory
cudaMalloc( (void**)&dev_a, size_2d);
cudaMalloc( (void**)&dev_c, size_c);
// Populate the 2D array on host with something small and known as a test
for (int i=0; i < ROW; i++){
if (i == ROW - 1){
for (int j=0; j < COL; j++){
array[i][j] = (j*2);
printf("%i ", array[i][j]);
}
} else {
for (int j=0; j < COL; j++){
array[i][j] = j;
printf("%i ", array[i][j]);
}
}
printf("\n");
}
// Copy the memory
cudaMemcpy( dev_a, array, size_2d, cudaMemcpyHostToDevice );
cudaMemcpy( dev_c, c, size_c, cudaMemcpyHostToDevice );
// Run the kernal function
collapse<<< ROW, COL >>>(dev_a, dev_c);
// copy the output back to the host
cudaMemcpy( c, dev_c, size_c, cudaMemcpyDeviceToHost );
// Print the output
printf("\n");
for (int i = 0; i < ROW; i++){
printf("%i\n", c[i]);
}
// Releasae the memory
cudaFree( dev_a );
cudaFree( dev_c );
}
输出:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 2 4 6 8 10 12 14 16 18
45
45
45
【问题讨论】:
-
我以前从未使用过 CUDA,但是查看代码和链接的文档,我怀疑您要么缺少那个 blockDim 东西,要么可能是 collapse i> 应该有一个签名 collapse(int[ROW][COL] a, int[ROW] c) 然后使用 a[threadIdx.x][threadIdx.y]
-
or a[threadIdx.y][threadIdx.x] 不知道哪个去哪了,没看完整文档
-
另外,如果它真的创建了 ROW 次 COL 线程,你不需要在那个内核内部循环,它会被调用 30 次。每次调用只需添加一个。在这一点上,你当然会遇到线程安全的问题......
-
@BuellaGábor 是的,我确实完全错过了我的代码中的
blockIdx。我最初认为它会创建ROWxCOL线程,正如您在上一条评论中所建议的那样,这导致了很多混乱,但事实并非如此,它会创建<<<number_of_blocks, number_of_threads_per_block>>> -
好吧,我删除了我的答案,因为它是错误的,并且具有误导性
标签: c arrays indexing cuda nvidia