使用CUDA内核的数组操作

时间:2014-02-10 12:43:10

标签: c cuda nvidia

我正在编写CUDA内核,并且线程正在执行以下任务:

for example i have array of [1, 2, 3, 4] then I want answer [12, 13, 14, 23, 24, 34]

假设我有一个包含n个整数的数组,我有两个索引i和j。

C语言的简单解决方案将是:

k=0;
for (i = 0; i < n - 1; i++)
    for(j = i+1; j < n-1 ; j++)
       { new_array[k] = array[i]*10 + array[j];
          k++;
        }

在CUDA,我试过运气:

for(i = threadIdx.x + 1; i < n-1; i++ )
    new_array[i] = array[threadIdx.x] * 10 + array[i];

但我认为这不是完全正确或最佳的方式。任何人都可以提出更好的建议吗?

1 个答案:

答案 0 :(得分:1)

我假设您想要移植到CUDA的代码如下:

#include <stdio.h>
#define N 7

int main(){

    int array[N] = { 1, 2, 3, 4, 5, 6, 7};
    int new_array[(N-1)*N/2] = { 0 };

    int k=0;
    for (int i = 0; i < N; i++)
        for(int j = i+1; j < N; j++)
        { 
            new_array[k] = array[i]*10 + array[j];
            k++;
        }

    for (int i = 0; i < (N-1)*N/2; i++) printf("new_array[%d] = %d\n", i, new_array[i]);

return 0;

}

您可能需要注意,您可以将内部循环重新设为

for (int i = 0; i < N; i++)
    for(int j = i+1; j < N; j++)
        new_array[i*N+(j-(i+1))-(i)*(i+1)/2] = array[i]*10 + array[j];

通过直接使用索引k来避免显式定义索引变量i*N+(j-(i+1))-(i)*(i+1)/2。这样的观察是有用的,如果您将索引ij解释为移植代码中的线程索引,那么您将在2d线程索引和所需索引之间建立映射访问您必须定义的__global__函数中的目标数组。

因此,移植的代码是

#include <stdio.h>
#define N 7

__global__ void kernel(int* new_array_d, int* array_d) {

    int i = threadIdx.x;
    int j = threadIdx.y;

    if (j > i) new_array_d[i*N+(j-(i+1))-(i)*(i+1)/2] = array_d[i]*10 + array_d[j];
}

int main(){

    int array[N] = { 1, 2, 3, 4, 5, 6, 7};
    int new_array[(N-1)*N/2] = { 0 };

    int* array_d;       cudaMalloc((void**)&array_d,N*sizeof(int));
    int* new_array_d;   cudaMalloc((void**)&new_array_d,(N-1)*N/2*sizeof(int));

    cudaMemcpy(array_d,array,N*sizeof(int),cudaMemcpyHostToDevice);

    dim3 grid(1,1);
    dim3 block(N,N);
    kernel<<<grid,block>>>(new_array_d,array_d);

    cudaMemcpy(new_array,new_array_d,(N-1)*N/2*sizeof(int),cudaMemcpyDeviceToHost);

    for (int i = 0; i < (N-1)*N/2; i++) printf("new_array[%d] = %d\n", i, new_array[i]);

    return 0;
}

请在What is the canonical way to check for errors using the CUDA runtime API?的意义上添加您自己的CUDA错误检查。此外,您可能希望将上述CUDA代码扩展到非单一大小的块网格的情况。