-
Notifications
You must be signed in to change notification settings - Fork 1
/
TP1_Prise_en_main.cu
178 lines (122 loc) · 4.8 KB
/
TP1_Prise_en_main.cu
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>
// Fonction permettant la création d'une matrice M à n lignes et p colonnes //
/*
- Cette matrice sera remplie de float compris entre -1 et 1
- Cette matrice est créée sur le CPU
*/
void MatrixInit(float *M, int n, int p){
srand(time(NULL));
for (int i = 0; i <n*p; i++){
M[i] = (float)rand()/RAND_MAX*2-1;
};
}
// Fonction permettant d'afficher une matrice sur le CPU
/*
- prend en entrée l'adresse de la matrice (sous forme de colonne)
- prend en argument la taille de la matrice: n lignes p colonnes
*/
void MatrixPrint(float *M, int n, int p){
for (int i = 0; i <n*p; i++){
// on print ligne par ligne
if (i%p==0){
printf("\n");
}
printf(" %1.1f ", M[i]);
};
printf("\n \n");
}
// Fonction réalisant l'addition de deux matrices sur le GPU//
/*
- Prend en argument l'adresse des deux matrices à additioner ainsi que celle de la matrice de sortie.
- Prend en argument la taille de la matrice: n lignes p colonnes.
- Les deux matrices doivent bien entendu avoir les mêmes dimension
*/
void MatrixAdd(float *M1, float *M2, float *Mout, int n, int p){
for (int i = 0; i <n*p; i++){
Mout[i] = M1[i] + M2[i];
};
}
// Fonction permettant de faire une multiplication de matrice de taille nxn //
/*
- Prend en argument l'adresse des deux matrices à multiplier ainsi que celle de la matrice de sortie.
- Prend en argument la taille de la matrice: n lignes n colonnes.
- Les deux matrices doivent avoir les mêmes dimension (n x n)
*/
void MatrixMult(float *M1, float *M2, float *Mout, int n){
for (int lig = 0; lig < n; lig++){
for (int col = 0; col < n; col++){
float s = 0.0f;
for (int i = 0; i < n; i++) {
s += M1[lig * n + i] * M2[i * n + col];
}
Mout[lig * n + col] = s;
};
}
}
///// Fonctions équivalente écrite pour le GPU /////
__global__ void cudaMatrixAdd(float *M1, float *M2, float *Mout, int n, int p){
int tid = blockIdx.x * blockDim.x + threadIdx.x;
if (tid < n*p){
Mout[tid] = M1[tid] + M2[tid];
}
}
__global__ void cudaMatrixMult(float *M1, float *M2, float *Mout, int n){
int lig = blockIdx.x;
int col = threadIdx.x;
float s = 0.0f;
if(lig < n && col < n){
for (int i = 0; i < n; i++){
s += M1[lig * n + i] * M2[i * n + col];
}
}
Mout[lig * n + col] = s;
}
////////////////////////////////////////// Main ///////////////////////////////////////////////
int main(){
// Déclaration des pointeurs des matrices utilisés par le CPU et par le GPU
float *M1, *M2, *Mout;
float *d_M1, *d_M2, *d_Mout;
// On se propose de travailler avec des matrices 5x5
int n = 5,p=5;
//allocation de mémoire accessible par le CPU
M1 = (float*)malloc(sizeof(float) * n*p);
M2 = (float*)malloc(sizeof(float) * n*p);
Mout = (float*)malloc(sizeof(float) * n*p);
//allocation de mémoire accessible par le GPU
cudaMalloc((void**)&d_M1, sizeof(float)*n*p);
cudaMalloc((void**)&d_M2, sizeof(float)*n*p);
cudaMalloc((void**)&d_Mout, sizeof(float)*n*p);
// Ici on initialise les matrices M1 et M2 avant de lancer nos opérations
MatrixInit(M1,n,p);
MatrixInit(M2,n,p);
// On copie les matrices en mémoire du CPU vers le GPU
cudaMemcpy(d_M1, M1, sizeof(float) * n*p, cudaMemcpyHostToDevice);
cudaMemcpy(d_M2, M2, sizeof(float) * n*p, cudaMemcpyHostToDevice);
printf("Matrice M1 de taille (%d,%d) :\n",n,p);
MatrixPrint(M1,n,p);
printf("Matrice M2 de taille (%d,%d) :\n",n,p);
MatrixPrint(M2,n,p);
printf("///////// Comparaison des deux additions ////////// \n \n");
printf("Addition du CPU \n");
MatrixAdd(M1,M2,Mout,n,p);
MatrixPrint(Mout,n,p);
// on a un bloc par ligne et un thread par colonne
int block_size = n;
int grid_size = p;
cudaMatrixAdd<<<grid_size,block_size>>>(d_M1, d_M2, d_Mout, n,p);
// On copie ici la Matrice de sortie du GPU vers celle du CPU
cudaMemcpy(Mout, d_Mout, sizeof(float) * n*p, cudaMemcpyDeviceToHost);
printf("Addition de Matrices sur le GPU : \n");
MatrixPrint(Mout,n,p);
printf("///////// Comparaison des deux multiplications ////////// \n \n");
MatrixMult(M1,M2,Mout, n);
printf("Multiplication du CPU /n");
MatrixPrint(Mout,n,p);
//printf("Multiplication du GPU");
cudaMatrixMult<<<grid_size,block_size>>>(d_M1, d_M2, d_Mout, n);
cudaMemcpy(Mout, d_Mout, sizeof(float) * n*p, cudaMemcpyDeviceToHost);
printf("Multiplication de Matrices sur le GPU : \n");
MatrixPrint(Mout,n,p);
}