IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les r�ponses en temps r�el, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

CUDA - Dev sur le GPU


Sujet :

C++

Vue hybride

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre confirm�
    Inscrit en
    Avril 2013
    Messages
    93
    D�tails du profil
    Informations forums :
    Inscription : Avril 2013
    Messages : 93
    Par d�faut CUDA - Dev sur le GPU
    Bonjour,

    Je cherche � utiliser la puissance des cartes graphiques pour faire du calcul parall�le.
    Je commence donc avec une petite appli pour comparer la multiplication entre 2 matrices (n*p) et (p*n) entre une impl�mentation s�quentielle sur le CPU et une parall�le sur le GPU.

    Pour des petits jeux de donn�es, �a marche bien mais d�s que je passe � des matrices de plus de 1000 par 1000, je me retrouve avec un �cran noir et je suis oblig� de rebooter ma machine..

    main.cpp
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
     
    #include "stdafx.h"
    #include "test.h"
     
    #include <iostream>
    #include <Windows.h>
     
    #include <ppl.h>
     
    using namespace std;
     
    void MultiplicationMatriceCPU(double *matrice1, double *matrice2,int n, int p, double *matriceR)
    {
    	double tempo = 0.0;
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = 0; j < n; j++)
    		{
    			tempo = 0.0;
    			for (int k = 0; k < p; k++)
    				tempo += matrice1[k * n + i] + matrice2[j * p + k];
    			matriceR[j * n + i] = tempo;
    		}
    	}
    }
     
    void MultiplicationMatriceCPUParallel(double *matrice1, double *matrice2,int n, int p, double *matriceR)
    {
    	Concurrency::parallel_for(0, n, 1, [&](int i)
    	{
    		double tempo = 0.0;
    		for (int j = 0; j < n; j++)
    		{
    			tempo = 0.0;
    			for (int k = 0; k < p; k++)
    				tempo += matrice1[k * n + i] + matrice2[j * p + k];
    			matriceR[j * n + i] = tempo;
    		}
    	});
    }
     
    void Afifchage(double *matrice, int n, int p, string prompt)
    {
    	cout<<prompt.c_str()<<endl;
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = 0; j < p; j++)
    		{
    			cout<<matrice[j * n + i]<<"  ";
    		}
    		cout<<endl;
    	}
    	cout<<endl;
    }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int n = 10;
    	int p = 10;
     
    	double *matrice1 = new double[n * p];
    	double *matrice2 = new double[n * p];
     
    	double *matriceR1 = new double[n * n];
    	double *matriceR2 = new double[n * n];
    	double *matriceR3 = new double[n * n];
     
    	for (int i = 0; i < n * p; ++i)
    	{
    		matrice1[i] = rand() % 4;
    		matrice2[i] = rand() % 4;
    	}
     
    	//multiplication sur le GPU
    	double t1 = GetTickCount();
    	MultiplicationMatriceGPU(matrice1, matrice2, matriceR1, n, p);
    	t1 = GetTickCount() - t1;
     
     
    	//multiplication sur le CPU
    	double t2 = GetTickCount();
    	MultiplicationMatriceCPU(matrice1, matrice2, n, p, matriceR2);
    	t2 = GetTickCount() - t2;
     
    	//multiplication sur le CPU parallélisé
    	double t3 = GetTickCount();
    	MultiplicationMatriceCPUParallel(matrice1, matrice2, n, p, matriceR3);
    	t3 = GetTickCount() - t3;		
     
    	//Affichage des résultats
    	int nbDiff = 0;
    	for (int i = 0; i < n * n; ++i)
    	{
    		if (matriceR2[i] != matriceR3[i] || matriceR2[i] != matriceR1[i])
    			++nbDiff;
    	}
     
    	cout<<"Resultats :"<<endl;
    	if (nbDiff > 0)
    	{
    		cout<<"  Le code n'est pas correct. ("<<nbDiff<<" differences)"<<endl;
     
    		if (n < 10)
    		{
    			Afifchage(matrice1, n, p, "matrice1:");
    			Afifchage(matrice2, p, n, "matrice2:");
    			Afifchage(matriceR1, n, n, "matriceR1 (GPU):");
    			Afifchage(matriceR3, n, n, "matriceR2 (CPU):");
    			Afifchage(matriceR3, n, n, "matriceR3 (CPU multicore):");
    		}
    	}
    	else
    	{
    		cout<<"  - Les résultats sont corrects."<<endl;
    		cout<<"  - Temps de traitement:"<<endl;
    		cout<<"    * GPU: "<<t1<<endl;
    		cout<<"    * CPU: "<<t2<<endl;
    		cout<<"    * CPU (multicore): "<<t3<<endl;
    	}
     
    	delete [] matrice1;
    	delete [] matrice2;
     
    	delete [] matriceR1;
    	delete [] matriceR2;
    	delete [] matriceR3;
     
    	return 1;
    }
    test.cu:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
     
    #include <cuda.h>
    #include <cuda_runtime.h>
    #include <curand_kernel.h>
     
    __global__ 
    	void MatrixMulKernel(double* matrice1, 
    	double* matrice2, 
    	double* matriceResult, 
    	int n,
    	int p)
    {
    	const int i = blockIdx.x * blockDim.x + threadIdx.x;
    	const int j = blockIdx.y * blockDim.y + threadIdx.y;
     
    	if (i > n || j > n) 
    		return;
     
    	double P_val = 0.0;
    	for (int k = 0; k < p; ++k)
    	{
    		P_val += matrice1[k * n + i] + matrice2[j * p + k];
    	}
     
    	matriceResult[j * n + i] = P_val;
    }
     
    void MultiplicationMatriceGPU(double *matrice1, double *matrice2, double *matriceResult, int n, int p)
    {
    	int BLOCK_SIZE = 16;
     
    	//préparation des matrices (allocation + initialisation)
     
    	//préparation du lien avec le GPU
     
    	//allocation mémoire dans le GPU
    	double *cuda_matrix1;
    	double *cuda_matrix2;
    	double *cuda_matrixResult;
     
    	cudaMalloc((void**)&cuda_matrix1, sizeof(double) * n * p);
    	cudaMalloc((void**)&cuda_matrix2, sizeof(double) * p * n);
    	cudaMalloc((void**)&cuda_matrixResult, sizeof(double) * n * n);
     
    	cudaMemcpy(cuda_matrix1, matrice1, sizeof(double) * n * p, cudaMemcpyHostToDevice);
    	cudaMemcpy(cuda_matrix2, matrice2, sizeof(double) * p * n, cudaMemcpyHostToDevice);
     
    	if (n / double(BLOCK_SIZE) > int(n / double(BLOCK_SIZE)))
    		BLOCK_SIZE = 1;
    	else if (p / double(BLOCK_SIZE) > int(p / double(BLOCK_SIZE)))
    		BLOCK_SIZE = 1;
     
    	dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
    	dim3 dimGrid((n + dimBlock.x - 1) / dimBlock.x, (n + dimBlock.y - 1) / dimBlock.y);
     
    	//<<<...,...>> kernel launch”
    	MatrixMulKernel<<<dimGrid, dimBlock>>>(cuda_matrix1, cuda_matrix2, cuda_matrixResult, n, p);
     
     
    	//copie du GPU vers la RAM
    	cudaMemcpy(matriceResult, cuda_matrixResult, sizeof(double) * n * n, cudaMemcpyDeviceToHost);
     
     
    	cudaFree(cuda_matrix1);
    	cudaFree(cuda_matrix2);
    	cudaFree(cuda_matrixResult);
     
    }
    test.h
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    void MultiplicationMatriceGPU(double *matrix1, double *matrix2, double *matrixResult, int N, int P);
    Voil� voil� tout mon code!

    D'un point de vue config, je dev sur visual 2010 sous windows 7 avec une GeForce GT 620 (1 Go de DRam et 48 coeurs).

    Mon probl�me d'�cran noir provient de quoi? Est-ce que c'est la m�moire du GPU qui explose, le nombre de threads, de blocks?

    Je d�bute tout juste, et je suis preneur de toute aide et conseil.

    Merci beaucoup!!

  2. #2
    Membre �prouv� Avatar de KsassPeuk
    Homme Profil pro
    Ing�nieur Chercheur
    Inscrit en
    Juillet 2013
    Messages
    138
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : Ing�nieur Chercheur
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Juillet 2013
    Messages : 138
    Par d�faut
    Lu'!

    Quand tu fais tes premiers tests, commence toujours par utiliser le type float plut�t que double. Tu as plus d'unit�s de calcul pour les float donc tu verras mieux ton acc�l�ration .
    Autre chose : pour les multiplications de matrices, arrange toi pour avoir des matrices carr�es en faisant du padding avec des z�ros, �a te co�tera pas excessivement cher mais �a te permettra d'avoir un kernel plus simple.

    Si tu utilise VisualStudio, tu utilises probablement NSight, tu peux l'utiliser pour faire du profiling et du debugging et donc voir ce qui foire.
    Apr�s dans les raisons qui peuvent faire que �a plante : si le temps pass� dans un kernel est trop long, ton OS peut consid�rer que le driver a craqu� son slip.

    Pour �viter �a, ce que tu peux faire c'est passer sur une autre mani�re (plus maligne, mais toujours suivant le m�me algo) de faire ta multiplication. Tu peux d�couper ta matrice en blocs et faire une multiplication suivant ce principe : http://fr.wikipedia.org/wiki/Produit...rices_par_bloc.
    L'id�e : tu fais des blocs de calculs et des blocs de multiproc selon une topologie 2D. Ensuite, c�t� kernel, tu vas faire des blocs* (cette fois ci dans la matrice) qui ont la m�me taille que le bloc de calcul** (ATTENTION : padding n�cessaire pour que la taille de la matrice soit multiple de �a).
    Apr�s c'est le m�me algo, mais la localit� des donn�es et le nombre de donn�es � traiter par bloc de multiproc �tant plus faible, va permettre de r�duire le temps pass� dans le kernel.

    * optimisation possible : charger le bloc en m�moire shared, il est possible de faire des acc�s avec tr�s peu de conflits de banques
    ** optimisation possible : charger les blocs 4 par 4 sur une des deux matrices, permet de mieux utiliser la bande passante.
    Autre opti : passage de la matrice en cache texture.

  3. #3
    Membre �prouv�
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par d�faut
    Cette m�thode est expliqu�e dans la doc du CUDA Toolkit, il me semble.

Discussions similaires

  1. [PDT] Dev. sur serveur distant ?
    Par snowguru dans le forum Eclipse PHP
    R�ponses: 1
    Dernier message: 26/03/2009, 17h14
  2. Quel langage pour un dev sur multi-plateforme ?
    Par KarelAppel dans le forum Windows
    R�ponses: 1
    Dernier message: 05/01/2007, 01h58
  3. R�ponses: 23
    Dernier message: 23/03/2006, 20h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo