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
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
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.h
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); }
Voilà voilà tout mon code!
Code : Sélectionner tout - Visualiser dans une fenêtre à part void MultiplicationMatriceGPU(double *matrix1, double *matrix2, double *matrixResult, int N, int P);
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!!






Répondre avec citation




Partager