Я предполагаю, что код, который вы хотите портировать на 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;
}
Пожалуйста, добавьте свой собственный CUDA проверку ошибок в смысле What is the canonical way to check for errors using the CUDA runtime API?. Кроме того, вы можете расширить вышеуказанный код CUDA на случай блочных сеток нестандартных размеров.
Проблема, которую вы описываете выше (попарная конкатенация символов), кажется совершенно отличной от той, что иллюстрируется циклами 'for'. В последнем случае кажется, что перед внутренним циклом вы сталкиваетесь с операцией [all-prefix-sum] (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html). – JackOLantern