4 __global__ void calcul_cumuls_gpu(unsigned short * img, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs, unsigned int N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines )
7 int offsetSom = N_BLOCS_LIGNE * nb_lines; //indice du premier element de cumul_x2 dans le tableau
9 int tib = threadIdx.x ; //indice du thread dans le bloc
10 int idx = blockIdx.x*bs + tib ; //indice global du thread dans la portion d'image
11 int num_ligne = blockIdx.x / N_BLOCS_LIGNE ; //indice de la ligne du thread dans la portion d'image
12 int til = idx - num_ligne*bs*N_BLOCS_LIGNE ; //indice du thread ds la ligne
13 int pos = num_ligne*l + til ; //indice du pixel dans la 'tranche' courante
14 int pos_img = pos + baseline*l ; //indice correspondant dans l'image originale
17 extern __shared__ tcumuls sdata[];
18 //chargement en smem avec complement de 0
21 sdata[id].x = img[ pos_img ] ;
22 sdata[id].x2 = img[ pos_img ]*img[ pos_img ] ;
30 //passe 1 : construction des sommes
32 for (int d = bs/2; d > 0; d >>= 1)
38 int i = __mul24(__mul24(2, stride), tib);
39 int ai = i + stride - 1;
40 int bi = CFI(ai + stride);
45 sdata[bi].x += sdata[ai].x;
46 sdata[bi].x2 += sdata[ai].x2;
52 //stockage somme du bloc en gmem
54 //mise a zero dernier element du bloc
59 t_cumul_x som_x = sdata[CFI(tib)].x;
60 t_cumul_x2 som_x2 = sdata[CFI(tib)].x2;
61 if (til < l){ //il ne faut pas ecrire de somme dans le dernier bloc, elle serait hors image
62 cumul_x[ pos_img ] = som_x;
63 cumul_x2[pos_img ] = som_x2;
65 gsomblocs[blockIdx.x] = som_x;
66 gsomblocs[blockIdx.x + offsetSom] = som_x2;
67 sdata[CFI(tib)].x = 0;
68 sdata[CFI(tib)].x2 = 0;
71 //Passe 2 : construction des scans
72 for (int d = 1; d <= (bs/2); d *= 2)
79 int i = __mul24(__mul24(2, stride), tib);
80 int ai = i + stride - 1;
81 int bi = CFI(ai + stride);
86 t_cumul_x tx = sdata[ai].x;
87 t_cumul_x2 tx2 = sdata[ai].x2;
89 sdata[ai].x = sdata[bi].x;
92 sdata[ai].x2 = sdata[bi].x2;
97 //transfert en gmem des scans
98 //il faut décaler à gauche de 1 element
100 if ( (til < l) && ( tib < (bs-1) ) ){
101 cumul_x[ pos_img ] = sdata[CFI(tib+1)].x;
102 cumul_x2[pos_img ] = sdata[CFI(tib+1)].x2;
110 kernel pour faire le prefixsum des sommes de blocs des lignes de l'image
111 les params d'executions kivonbien sont :
112 - threads : la moitié de la nextpow2 du nb de blocs par ligne
113 - grid : 2 x le nombre de blocs de sommes dans l'image , soit le nb_blocs_par_ligne x nb_lignes x 2
114 - shared mem : 2 x nextPow2(nb_blocs par ligne)
119 __global__ void scan_somblocs(uint64 * g_idata, int n_bl_l){
121 extern __shared__ uint64 temp[];
123 int tib = threadIdx.x;
124 int toff = blockIdx.x*n_bl_l; // offset des positions des sommes partielles dans le tableau g_idata
125 int nmax = blockDim.x*2; //nb max de sommes partielles par ligne
129 int bbi = tib + blockDim.x;
132 // chargement data en smem
133 temp[ CFI(aai) ] = (aai < n_bl_l)? g_idata[ toff + aai ] : 0;
134 temp[ CFI(bbi) ] = (bbi < n_bl_l)? g_idata[ toff + bbi ] : 0;
138 // passe 1 de bas en haut
139 for (int d = nmax/2; d > 0; d >>= 1)
145 int ai = CFI(offset*(2*tib+1)-1);
146 int bi = CFI(offset*(2*tib+2)-1);
148 temp[bi] += temp[ai];
154 // zero le dernier element
158 int index = CFI(nmax - 1);
159 g_idata[ toff + n_bl_l - 1 ] = temp[ index ]; //memorisation de la somme du bloc a sa place en gmem
163 // passe 2 de haut en bas
164 for (int d = 1; d < nmax; d *= 2)
172 int ai = CFI(offset*(2*tib+1)-1);
173 int bi = CFI(offset*(2*tib+2)-1);
177 temp[bi] += t; //tester atomicadd 64 bits
184 // transfert resultats en gmem decales d'un element vers la gauche
185 g_idata[ toff + aai ] = temp[ CFI(aai + 1) ]; //pour le demi tableau smem inferieur
186 if ( bbi < n_bl_l-1 ) g_idata[ toff + bbi ] = temp[CFI( bbi + 1) ]; //demi tableau smem sup. sauf dernier=somme.
191 __global__ void add_soms_to_cumuls(t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs,
192 unsigned int N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines){
194 int bs = blockDim.x ;
195 int offsetSom = N_BLOCS_LIGNE * nb_lines;
196 int tib = threadIdx.x ; //indice du thread dans le bloc
197 int idx = blockIdx.x*blockDim.x + tib ; //indice global du thread
198 int num_ligne = blockIdx.x / N_BLOCS_LIGNE ; //indice de la ligne du thread dans l'image partielle
199 int til = idx - num_ligne*bs*N_BLOCS_LIGNE ; //indice du thread ds la ligne
200 int pos = num_ligne*l + til;
201 int pos_img = pos + baseline*l ;
204 //chargement des valeurs a ajouter en smem 0<-->x et 1<-->x2
205 uint64 __shared__ ajout[2];
208 ajout[0] = gsomblocs[blockIdx.x -1 ];
209 ajout[1] = gsomblocs[blockIdx.x -1 + offsetSom];
210 __syncthreads(); //tester les nouveaux __sync__
214 cumul_x[pos_img] += ajout[0];
215 cumul_x2[pos_img]+= ajout[1];
220 //calcul des SUM_1, SUM_X et SUM_X2 de l'image
222 __global__ void calcul_stats_image( t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * d_stats_snake){
223 uint64 sigX = 0, sigX2 = 0 ;
224 for (int i=l-1; i<h*l; i+=l)
229 d_stats_snake[3] = h*l ;
230 d_stats_snake[4] = sigX ;
231 d_stats_snake[5] = sigX2;