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
|
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
///Fonction qui fait la réduction
/** @param in : tableau à réduire, sa taille est égale au double du nombre de threads dans la grille
* @param sizeIn : taille du tableau in
* @param out : tableau de valeurs réduites, sa taille est égale au nombre de block
* @param sizeOut : taille du tableau out
*/
__global__ void kernelReduction(float *in, size_t sizeIn, float *out, size_t sizeOut){
int i = 2*(blockIdx.x*blockDim.x + threadIdx.x);
int indexCalcul = 1;
while(indexCalcul < 2*blockDim.x){
if(i + indexCalcul < sizeIn){ in[i] += in[i + indexCalcul];
}
indexCalcul *= 2;
__syncthreads(); }
if(threadIdx.x == 0) out[blockIdx.x] = in[i];
}
///fonction qui permet d'initialiser les tableaux de valeurs sur l'hote
/** @param h_in : tableaux dont on veut initialiser les valeurs
* @param ntot : nombre d'éléments du tableau
*/
__host__ void init_vec(float *h_in, int ntot){
for(int i = 0 ; i < ntot ; i++){
h_in[i] = sinf(float(i));
}
}
///fonction qui permet d'initialiser les tableaux de valeurs sur l'hote
/** @param h_in : tableaux dont l'on veut afficher les valeurs
* @param ntot : nombre d'éléments du tableau
*/
__host__ void printf_vec(float *h_in, int ntot){
for(int i = 0 ; i < ntot ; i++){
printf("%f,\t", h_in[i]);
if(i%8 == 0 && i != 0) printf("\n"); }
printf("\n");
}
///fonction qui permet de vérifier les résultats contenus dans les tableaux de valeurs
/** @param sun : somme que l'on a trouvé avec le GPU
* @param h_in : tableaux de valeurs
* @param ntot : nombre d'éléments du tableau
*/
__host__ void verifCalcul(float sumGPU, float sumCPU){
float err = fabsf((sumGPU - sumCPU)/sumGPU);
printf("GPU sum : %.4e\n", sumGPU);
printf("CPU sum : %.4e\n", sumCPU);
if(err < 1.e-4){
printf("TEST PASSED (err %.4e < 1.e-4).\n", err);
}else{
printf("TEST FAILED (err %.4e > 1.e-4).\n", err);
}
}
float reductionCPU(float *h_in, int ntot){
float sum = 0.0;
for(int i = 0 ; i < ntot ; ++i){
sum += h_in[i];
}
return sum;
}
void checkNoErr(int linenr, float * d_sum, float * d_bl, float * d_in, float * h_in){
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) {
printf("Erreur ligne %d : %s \n", linenr, cudaGetErrorString(err));
cudaFree(d_sum);
cudaFree(d_bl);
cudaFree(d_in);
cudaFree(h_in);
abort();
}
}
int main(int argc, char **argv){
float sum;
size_t nthreads, nblocks = 16, ntot = 1024;
nthreads = ntot/(2*nblocks);
printf("Ntot : %lu\n", ntot);
printf("nthreads : %lu\n", nthreads);
printf("nblocks : %lu\n", nblocks);
float *d_sum, *d_bl, *h_bl, *d_in, *h_in;
cudaMallocHost((void**)&h_in, ntot*sizeof(float));
cudaMallocHost((void**)&h_bl, nblocks*sizeof(float));
if(h_in == NULL){printf("Impossible d'allouer h_in == NULL\n");return 1;}
cudaMalloc((void**)&d_sum, sizeof(float));
cudaMalloc((void**)&d_bl, nblocks*sizeof(float));
cudaMalloc((void**)&d_in, ntot*sizeof(float));
checkNoErr(__LINE__, d_sum, d_bl, d_in, h_in);
init_vec(h_in, ntot);
float sommeCPU = reductionCPU(h_in, ntot);
cudaMemcpy(d_in, h_in, ntot*sizeof(float), cudaMemcpyHostToDevice);
checkNoErr(__LINE__, d_sum, d_bl, d_in, h_in);
dim3 dimGrid(nblocks, 1, 1);
dim3 dimBlock(nthreads, 1, 1);
dim3 dimGridHalf(nblocks/2, 1, 1);
dim3 unique(1,1,1);
kernelReduction<<<dimGrid, dimBlock>>>(d_in, ntot, d_bl, nblocks); kernelReduction<<<unique, dimGridHalf>>>(d_bl, nblocks, d_sum, 1); checkNoErr(__LINE__, d_sum, d_bl, d_in, h_in);
cudaThreadSynchronize();
checkNoErr(__LINE__, d_sum, d_bl, d_in, h_in);
cudaMemcpy(h_in, d_in, ntot*sizeof(float), cudaMemcpyDeviceToHost);
cudaMemcpy(h_bl, d_bl, nblocks*sizeof(float), cudaMemcpyDeviceToHost);
checkNoErr(__LINE__, d_sum, d_bl, d_in, h_in);
cudaMemcpy(&sum, d_sum, sizeof(float), cudaMemcpyDeviceToHost);
checkNoErr(__LINE__, d_sum, d_bl, d_in, h_in);
verifCalcul(sum, sommeCPU);
cudaFree(d_sum);
cudaFree(d_bl);
cudaFreeHost(h_bl);
cudaFree(d_in);
cudaFreeHost(h_in);
return 0;
}
|