Сведение массива CUDA к сумме элементов. Как передать ответ с устройства на хост и на печать?

Я пытаюсь уменьшить массив до суммы его элементов, используя CUDA. У меня возникли проблемы с передачей суммы, рассчитанной на устройстве, обратно на хост, чтобы ее можно было распечатать.

это вывод, который я получаю:

содержимое массива: 33 36 27 15 43 35 36 42 49 21

Уменьшенная сумма элементов массива = 4204303

уменьшенная сумма явно неверна.

вот мой код.

#include <stdio.h>
#include <cuda.h>

#define N 10

__global__ void reduce(int *g_idata, int *g_odata);
void random_ints (int *a, int n);

int main( void ) {
    int a[N], b[N]; // copies of a, b, c
    int *dev_a, *dev_b; // device copies of a, b, c
    int size = N * sizeof( int ); // we need space for 512 integers

    // allocate device copies of a, b, c
    cudaMalloc( (void**)&dev_a, size );
    cudaMalloc( (void**)&dev_b, size );

    //a = (int *)malloc( size );
    //b = (int *)malloc( size );

    random_ints( a, N );

    printf("contents of Array: ");  
    for(int i =0; i<N; i++)
    {
        printf(" %d ", a[i]);
    }
    printf("\n");

    // copy inputs to device
    cudaMemcpy( dev_a, a, size, cudaMemcpyHostToDevice );
    cudaMemcpy( dev_b, b, size, cudaMemcpyHostToDevice );

    // launch dot() kernel with 1 block and N threads
    reduce<<< 1, N >>>( dev_a, dev_b);

    // copy device result back to host copy of c
    cudaMemcpy( b, dev_b, sizeof( int ) , cudaMemcpyDeviceToHost );



    printf("Reduced sum of Array elements = %d ", b[0]);


    //free( a );
    // free( b ); 


    cudaFree( dev_a );
    cudaFree( dev_b );

    return 0;
}


__global__ void reduce(int *g_idata, int *g_odata) {

    extern __shared__ int sdata[];

    // each thread loads one element from global to shared mem
    int i = blockIdx.x*blockDim.x + threadIdx.x;

    sdata[threadIdx.x] = g_idata[i];

    __syncthreads();
    // do reduction in shared mem
    for (int s=1; s < blockDim.x; s *=2) 
    {
        int index = 2 * s * threadIdx.x;;

        if (index < blockDim.x)
        {
            sdata[index] += sdata[index + s];
        }
        __syncthreads();
    }

    // write result for this block to global mem
    if (threadIdx.x == 0) g_odata[blockIdx.x] = sdata[0];
}

// CPU function to generate a vector of random integers
void random_ints (int *a, int n) {
    for (int i = 0; i < n; i++)
        a[i] = rand() % 50; // random number between 0 and 49
}

person Zubaid.m    schedule 08.11.2015    source источник
comment
Вам не хватает аргумента для запуска ядра, и в результате ядро ​​никогда не запускается, и вы просто распечатываете содержимое унифицированной памяти устройства. Если бы вы добавили элементарную проверку ошибок в свой код или использовали cuda-memcheck в своей программе, вы бы уже это знали.   -  person talonmies    schedule 08.11.2015
comment
Я попробовал ваше предложение, но уменьшенная сумма по-прежнему печатается одинаково. любые другие возможные проблемы с моим кодом?   -  person Zubaid.m    schedule 09.11.2015
comment
Попробуйте изменить это: if (index < blockDim.x) на это: if (index+s < blockDim.x)   -  person Robert Crovella    schedule 09.11.2015
comment
Я понял свою проблему. В качестве устройства я использовал GeForce GTX 280. Я подключаюсь по ssh к устройству GeForce GTX 480. Не уверен, в чем разница, но теперь мой код работает отлично. Спасибо за помощь!   -  person Zubaid.m    schedule 09.11.2015


Ответы (1)


Вам необходимо указать объем разделяемой памяти, если вы используете extern разделяемой памяти.
У вас есть два решения:

с

extern __shared__ int sdata[];

reduce<<< 1, N, N*sizeof(int) >>>( dev_a, dev_b); 

с этим параметром задайте размер разделяемой памяти для использования в этом ядре.

с

__shared__ int sdata[N];

с N постоянным числом элементов.

person Kalgat    schedule 08.11.2015