2014-02-10 2 views
-1

Я пишу CUDA ядра и потоки выполняют следующие задачи:операция массива с помощью CUDA ядра

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

Пусть Я массив целых чисел п и я имею два индекса я и 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

Проблема, которую вы описываете выше (попарная конкатенация символов), кажется совершенно отличной от той, что иллюстрируется циклами 'for'. В последнем случае кажется, что перед внутренним циклом вы сталкиваетесь с операцией [all-prefix-sum] (http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html). – JackOLantern

ответ

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; 
} 

Пожалуйста, добавьте свой собственный CUDA проверку ошибок в смысле What is the canonical way to check for errors using the CUDA runtime API?. Кроме того, вы можете расширить вышеуказанный код CUDA на случай блочных сеток нестандартных размеров.

Смежные вопросы