2010-09-04 3 views
3

Je viens de commencer à expérimenter avec le cuda Cude suivantErreur numérique dans un langage simple code CUDA

#include "macro.hpp" 
#include <algorithm> 
#include <iostream> 
#include <cstdlib> 

//#define double float 
//#define double int 

int RandomNumber(){return static_cast<double>(rand() % 1000);} 

__global__ void sum3(double const* a, 
      double const* b, 
      double const* c, 
      double * result, 
      unsigned const* n) 
{  
    unsigned i = blockIdx.x; 
    while(i < (*n)) 
{ 
    result[i] = (a[i] + b[i] + c[i]); 
} 
}; 


int main() 
{ 

    static unsigned size = 1e2; 
    srand(0); 
    double* a = new double[size]; 
    double* b = new double[size]; 
    double* c = new double[size]; 
    double* result = new double[size]; 

    std::generate(a, a+size, RandomNumber); 
    std::generate(b, b+size, RandomNumber); 
    std::generate(c, c+size, RandomNumber); 

    double* ad, *bd,* cd; 
    double* resultd; 

    unsigned * sized; 
    std::cout << cudaMalloc((void**) &ad, size*sizeof(double)) << std::endl; 
    std::cout << cudaMalloc((void**) &bd, size*sizeof(double)) << std::endl; 
    std::cout << cudaMalloc((void**) &cd, size*sizeof(double)) << std::endl; 
    std::cout << cudaMalloc((void**) &resultd, size*sizeof(double)) << std::endl; 
    std::cout << cudaMalloc((void**) &sized, sizeof(unsigned)) << std::endl; 

    cudaMemcpy((void**) &sized, &size, sizeof(unsigned), cudaMemcpyHostToDevice); 

    // print_array(a, size); 
    for(int i = 0; i < 1000; ++i) 
    { 
     cudaMemcpy(ad, a, size*sizeof(double), cudaMemcpyHostToDevice); 
     cudaMemcpy(bd, b, size*sizeof(double), cudaMemcpyHostToDevice); 
     cudaMemcpy(cd, c, size*sizeof(double), cudaMemcpyHostToDevice);  
     sum3<<<size, 1>>>(ad, bd, cd, resultd, sized); 
     cudaMemcpy(result, resultd, size*sizeof(double), cudaMemcpyDeviceToHost); 
    } 

#ifdef PRINT 
    for(int i = 0; i < size; ++i) 
    { 
     std::cout << a[i] << ", "<< b[i] <<"," << c[i] << "," << result[i]<< std::endl; 
    } 
#endif 

    cudaFree(ad); 
    cudaFree(bd); 
    cudaFree(cd); 
    cudaFree(resultd); 

    delete[] a; 
    delete[] b; 
    delete[] c; 
    delete[] result; 

    return 0; 
} 

compiler ce livre sur mac pro sans problème. Cependant, lorsque je tente d'exécuter ce que je reçois

930, 22,538,899 
691, 832,205,23 
415, 655,148,120 
872, 876,481,985 
761, 909,583,619 
841, 104,466,917 
610, 635,911,52 
//more useless numbers 

J'ai comparé mes échantillons avec celui Cuda par exemple et je ne vois aucune différence majeure, sauf le type. Tout pointeur sur ce problème est apprécié.

+0

Qu'attendez-vous de cette ligne? std :: generate (a, a + taille, RandomNumber); Il s'attendrait à ce qu'une taille + soit incorrecte, car l'ajout d'un pointeur de tableau à un nombre est généralement incorrect, car vous avez dépassé la fin du tableau. –

+0

doesnt * (a + size) donne l'espace d'adresse juste après l'élément a [taille-1]? – leon

+0

@James: Aller un passé le tableau est très bien et assez commun. @leon: L'arithmétique de votre pointeur est correcte. Bien que vous ayez vraiment besoin d'utiliser des concepts de gestion des ressources liés à Scope (également connus sous le nom de RAII). Utilisez 'std :: vector' pour les tableaux dynamiques, * toujours *. Et vous devriez probablement envelopper la mémoire CUDA dans un conteneur. Si vous êtes en mesure de libérer quelque chose, vous l'avez mal fait. Cela devrait arriver automatiquement. – GManNickG

Répondre

1
while(i < (*n)) 
{ 
    result[i] = (a[i] + b[i] + c[i]); 
} 

est faux (infini)

ce qui ne va pas

cudaMemcpy((void**) &sized, &size, sizeof(unsigned), cudaMemcpyHostToDevice); 

&sized est l'adresse de la variable de pointeur, pas de valeur pointeur

numéro unique peut être transmise au dispositif sur la pile donc utilisez

unsigned size 

vérifier l'état de retour de vos fonctions de cuda, http://www.drdobbs.com/high-performance-computing/207603131

+0

Pouvez-vous expliquer :)? – leon

+0

@leon. désolé, j'ai mal compris votre code avant, voir ma mise à jour – Anycorn

+0

Je viens de réaliser qu'il devrait un 'si' au lieu de' while' :) – leon

-1

vous avez écrit:

double* a = new double[size]; 

donc, "a" est un pointeur sur un tableau de double, vous dites

std::generate(a, a+size, RandomNumber); 
    std::generate(b, b+size, RandomNumber); 
    std::generate(c, c+size, RandomNumber); 

qui est faux, vous devriez dire

std::generate(*a, (*a)+size, RandomNumber); 
    std::generate(*b, (*b)+size, RandomNumber); 
    std::generate(*c, (*c)+size, RandomNumber); 

Serait plus facile t o vous aider si vous énoncez ce que vous voulez que votre programme fasse.

En outre, vous mettre

unsigned * sized; 
std::cout << cudaMalloc((void**) &ad, size*sizeof(double)) << std::endl; 

mais vous pouvez faire

unsigned * sized; 
std::cout << cudaMalloc((void*) ad, size*sizeof(double)) << std::endl; 

en fonction de ce que vous essayez de faire.

+0

En C/C++ le nom 'a' dans' a [] 'est le pointeur qui pointe au premier élément du tableau, et ne pointant pas sur un tableau de double. Ensuite, 'std :: generate' prend un pointeur (itérateur) qui pointe vers le début de la plage et l'adresse mémoire juste après le dernier élément de la plage. '(* a) + size' = a [0] + la taille n'a pas de sens pour l'argument generate. Enfin, 'cudaMalloc()' prend un pointeur de pointeur, donc je passe '& ad'. '(void **) & ad' n'est pas la même chose que' (void *) ad'. Ce qui est pareil est '* & ad' et' ad' mais ce n'est pas ce que je fais. – leon

+0

:(de ma faute, étais-je saoul? – user290149

Questions connexes