我正在编写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];
但我认为这不是完全正确或最佳的方式。任何人都可以提出更好的建议吗?
答案 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
。这样的观察是有用的,如果您将索引i
和j
解释为移植代码中的线程索引,那么您将在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代码扩展到非单一大小的块网格的情况。