Вопрос CUDA в простой программе - PullRequest
1 голос
/ 01 мая 2011

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

Это мой код .cpp

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <windows.h>
#include <shrUtils.h>
#include <cutil_inline.h>
#include <cutil_gl_inline.h>
#include <cuda.h>


CUfunction reduce0;    //i've used many ways to declare my kernel function,but.....


int main( int argc , char *argv[] ){

    int i,N,sum;
    int *data;
    int *Md;
    srand ( time(NULL) );
    N=(int)pow((float)2,(float)atoi(argv[1]));
    data=(int *)malloc(N * sizeof(int));

    for (i=0;i<N;i++){
        data[i]=rand() % 10 + 1;    
    }
    cudaMalloc((void**) &Md, N );

    clock_t start = clock();

    dim3 dimBlock(512,0);
    dim3 dimGrid(1,1);

    reduce0<<< dimGrid,dimBlock >>>(Md,Md);    



    sum=0;
    for(i=0;i<N;i++){
        sum=sum+data[i];
    } 

    printf("Sum of the %d-array is %d \n", N , sum);  
    printf("Time elapsed: %f\n", ((double)clock() - start) / CLOCKS_PER_SEC);   

return 0;

}

, а вот мой код .cu

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

extern __shared__ int sdata[];

// each thread loadsone element from global to shared mem

unsigned int tid = threadIdx.x;
unsigned int i= blockIdx.x*blockDim.x+ threadIdx.x;
sdata[tid] = g_idata[i];

__syncthreads();

// do reduction in shared mem

for(unsigned int s=1; s < blockDim.x; s *= 2) {
if(tid % (2*s) == 0){
sdata[tid] += sdata[tid + s];
}

__syncthreads();
}

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

Поэтому я спрашиваю, чтоя должен сделать, чтобы вызвать ядро?При компиляции он не распознает этот символ «<<<», а насколько за редуктор (0) он распознает его, только если я объявлю в .cpp!Пожалуйста, кто-нибудь, помогите мне наконец начать с настоящих вещей! </p>

Ответы [ 5 ]

1 голос
/ 01 мая 2011

CUfunction - это абстракция API драйвера - не нужна, если вы собираетесь использовать функцию языковой интеграции, которая включает синтаксис <<< >>> вызова ядра.

Если вам не нужноиспользуйте API драйвера (а большинство людей этого не делают), просто переместите ваш код C ++ в файл .cu и вызовите ядро ​​так же, как вы делаете сейчас.

Вызов cudaMalloc() выделяет память устройства, которуюПроцессор не может читать или писать.Вы должны скопировать вход для сокращения в память вашего устройства, используя cudaMemcpy(...,cudaMemcpyHostToDevice);, затем, после того, как вы закончите обработку, скопируйте вывод в память хоста, используя cudaMemcpy(..., cudaMemcpyDeviceToHost);

ps. Это ядро ​​сокращения очень медленное.Я бы порекомендовал вам открыть редукционный SDK и использовать оттуда одно из ядер.

Либо используйте библиотеку Thrust, которая будет включена в CUDA 4.0.Thrust поддерживает очень быстрые и гибкие сокращения.

0 голосов
/ 13 мая 2011

Если вы работаете на компьютере с Windows, проверьте статью по настройке Visual Studio 2010 для CUDA 3.2: http://www.codeproject.com/Tips/186655/CUDA-3-2-on-VS2010-in-9-steps.aspx

0 голосов
/ 05 мая 2011

В дополнение к вышесказанному, я думаю, что обнаружил ошибку в вашем вызове cudaMalloc.Даже если это не настоящая ошибка, я думаю, что это лучшая практика программирования для переносимости.Вместо этого должно быть:

cudaMalloc((void**) &Md, sizeof(int)*N);
0 голосов
/ 04 мая 2011

Ваш код, вызывающий ядро, должен обрабатываться компилятором NVCC.(<<< не является допустимым C ++) Обычно это означает, что он помещается в файл .cu.Вы не хотите перемещать весь свой cpp-код в cu (как вы просили в комментарии), просто код, вызывающий ядро. </p>

0 голосов
/ 02 мая 2011

Ваш код, вызывающий ядро, должен обрабатываться компилятором NVCC. (<<< не является допустимым C ++) Обычно это означает, что он помещается в файл .cu. Вы не хотите перемещать весь свой cpp-код в cu (как вы просили в комментарии), просто код, вызывающий ядро. </p>

Изменение

CUfunction reduce0;

до

void reduce_kernel(int*g_idata, int*g_odata);

и замените эти строки:

dim3 dimBlock(512,0);
dim3 dimGrid(1,1);

reduce0<<< dimGrid,dimBlock >>>(Md,Md);  

с:

reduce_kernel(Md, Md);

и добавьте это в ваш .cu файл:

void reduce_kernel(int*g_idata, int*g_odata)
{
    dim3 dimBlock(512,0);
    dim3 dimGrid(1,1);

    reduce0<<< dimGrid,dimBlock >>>(g_idata, g_odata);  
}

Это на макушке моей головы, так что может быть немного не в порядке, но вы можете понять это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...