3 __global__ void genere_snake_rectangle_4nodes_gpu(snake_node_gpu * d_snake, int dist_bords, int i_dim, int j_dim){
7 d_snake[n].posi = dist_bords ;
8 d_snake[n].posj = dist_bords ;
11 d_snake[n].posi = i_dim - dist_bords ;
12 d_snake[n].posj = dist_bords ;
15 d_snake[n].posi = i_dim - dist_bords ;
16 d_snake[n].posj = j_dim - dist_bords ;
19 d_snake[n].posi = dist_bords ;
20 d_snake[n].posj = j_dim - dist_bords ;
22 for (int i=0; i<4; i++)
24 d_snake[i].freeman_in = 0;
25 d_snake[i].freeman_out = 0;
26 d_snake[i].centre_i = 0;
27 d_snake[i].centre_j = 0;
28 d_snake[i].last_move = 0;
29 d_snake[i].nb_pixels = 0;
30 d_snake[i].code_segment = 0;
36 __global__ void genere_snake_bande_gpu(snake_node_gpu * d_snake, int j1, int j2, int h){
37 if (threadIdx.x == 0){
41 d_snake[n].posj = j1 ;
44 d_snake[n].posi = h-1 ;
45 d_snake[n].posj = j1 ;
48 d_snake[n].posi = h-1 ;
49 d_snake[n].posj = j2 ;
53 d_snake[n].posj = j2 ;
55 for (int i=0; i<4; i++)
57 d_snake[i].freeman_in = 0;
58 d_snake[i].freeman_out = 0;
59 d_snake[i].centre_i = 0;
60 d_snake[i].centre_j = 0;
61 d_snake[i].last_move = 0;
62 d_snake[i].nb_pixels = 0;
63 d_snake[i].code_segment = 0;
70 __global__ void genere_snake_rectangle(snake_node_gpu * d_snake, int i1, int i2, int j1, int j2){
71 if (threadIdx.x == 0){
74 d_snake[n].posi = i1 ;
75 d_snake[n].posj = j1 ;
78 d_snake[n].posi = i2 ;
79 d_snake[n].posj = j1 ;
82 d_snake[n].posi = i2 ;
83 d_snake[n].posj = j2 ;
86 d_snake[n].posi = i1 ;
87 d_snake[n].posj = j2 ;
89 for (int i=0; i<4; i++)
91 d_snake[i].freeman_in = 0;
92 d_snake[i].freeman_out = 0;
93 d_snake[i].centre_i = 0;
94 d_snake[i].centre_j = 0;
95 d_snake[i].last_move = 0;
96 d_snake[i].nb_pixels = 0;
97 d_snake[i].code_segment = 0;
105 Evalue le critere dans l'hypothese gaussienne
107 __device__ double critere_gauss( int n, int ni, uint64 sxi, uint64 sxi2, uint64 sigX, uint64 sigX2){
109 uint64 sxe = sigX - sxi ;
110 uint64 sxe2= sigX2 - sxi2;
111 double sigi2, sige2, critere ;
113 /* variance des valeurs des niveaux de gris a l'interieur */
116 ((double)sxi/ni)*((double)sxi/ni) ;
118 /* variance des valeurs des niveaux de gris a l'exterieur */
121 ((double)sxe/ne)*((double)sxe/ne) ;
123 if ( (sigi2 > 0) && (sige2 > 0) )
124 critere = 0.5*((double)ni*log(sigi2) + (double)ne*log(sige2)) ;
125 else critere = DBL_MAX ;
130 __global__ void calcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
131 t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
132 int l, uint2 * liste_pix, t_sum_x2 * gsombloc, int * d_table_freeman)
134 // indices des elements
135 int blockSize = blockDim.x ;
136 int tib = threadIdx.x ;
137 int nblocs_seg = gridDim.x / nb_nodes ;
138 int idx = blockDim.x*blockIdx.x + threadIdx.x ;
139 int segment = blockIdx.x / nblocs_seg ;
140 int tis = idx - segment*nblocs_seg*blockDim.x ;
142 //tab pour coordonnées pixels & contribs pixels de taille = (blockDim.x+offset(dec,dec2) )*(sizeof(t_sum_1+t_sum_x+t_sum_x2))
143 extern __shared__ t_sum_1 scumuls_1[] ; // blockDim varie selon la longueur des segments => taille smem dynamique
144 t_sum_x* scumuls_x = (t_sum_x*) &scumuls_1[CFI(blockDim.x)] ;
145 t_sum_x2* scumuls_x2 = (t_sum_x2*) &scumuls_x[CFI(blockDim.x)] ;
148 uint x1, y1, x2, y2 ;
153 //gestion du bouclage du snake
154 if (n2 >= nb_nodes) n2 = 0 ;
156 //affectation des differentes positions aux différents segments 'blocs de threads'
157 x1 = d_snake[n1].posj ;
158 y1 = d_snake[n1].posi ;
159 x2 = d_snake[n2].posj ;
160 y2 = d_snake[n2].posi ;
162 //params des deplacements
165 uint abs_dx = ABS(dx);
166 uint abs_dy = ABS(dy);
167 uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1); // alternative -> lecture ds liste_points[]
172 //calcul liste des pixels du segment (x1,y1)-(x2,y2)
173 if (dy > 0) incy=1; else incy=-1 ;
174 if (dx > 0) incx=1; else incx=-1 ;
177 if (abs_dy > abs_dx){
179 double k = (double)dx/dy ;
180 p.x = y1 + incy*tis ;
181 p.y = x1 + floor((double)incy*k*tis+0.5) ;
182 //enreg. coords. pixels en global mem pour freemans
184 if ((tis < 2)||(tis > nb_pix - 3)||(tis == nb_pix/2))
186 liste_pix[idx].x = p.x ;
187 liste_pix[idx].y = p.y ;
191 //1 thread par colonne
192 double k=(double)dy/dx ;
193 p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
194 p.y = x1 + incx*tis ;
196 xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
197 xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
199 //enreg. coords. pixels en global mem pour freeman
201 //on peut calculer les freemans des segments
202 //sans stocker l'ensemble des valeurs des pixels
203 //juste avec les derivees aux extremites a calculer ici
205 if ((tis < 2)||(tis > nb_pix - 3)||(tis == nb_pix/2))
207 liste_pix[idx].x = p.x ;
208 liste_pix[idx].y = p.y ;
215 //calcul contribs individuelles des pixels
217 if ( (tis >0) && (tis < nb_pix-1)
218 && ( (abs_dy <= abs_dx)
219 && ( (xprec > p.x) || (xsuiv > p.x))
220 || (abs_dy > abs_dx) ) )
222 int pos = p.x * l + p.y ;
223 scumuls_1[ CFI(tib)] = 1+p.y;
224 scumuls_x[ CFI(tib)] = cumul_x[ pos ] ;
225 scumuls_x2[CFI(tib)] = cumul_x2[ pos ];
227 scumuls_1[ CFI(tib)] = 0;
228 scumuls_x[ CFI(tib)] = 0;
229 scumuls_x2[CFI(tib)] = 0;
233 //somme des contribs individuelles
234 // unroll des sommes partielles en smem
236 if (blockSize >= 512) {
238 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 256) ];
239 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 256) ];
240 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 256) ];
245 if (blockSize >= 256) {
247 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 128) ];
248 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 128) ];
249 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 128) ];
253 if (blockSize >= 128) {
255 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 64) ];
256 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 64) ];
257 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 64) ];
262 //32 threads <==> 1 warp
266 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 32) ];
267 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 32) ];
268 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 32) ];
271 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 16) ];
272 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 16) ];
273 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 16) ];
276 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 8) ];
277 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 8) ];
278 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 8) ];
280 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 4) ];
281 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 4) ];
282 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 4) ];
284 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 2) ];
285 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 2) ];
286 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 2) ];
288 scumuls_1[ CFI(tib)] += scumuls_1[ CFI(tib + 1) ];
289 scumuls_x[ CFI(tib)] += scumuls_x[ CFI(tib + 1) ];
290 scumuls_x2[CFI(tib)] += scumuls_x2[CFI(tib + 1) ];
293 // resultat sommes partielles en gmem
295 gsombloc[ blockIdx.x ] = (t_sum_x2) scumuls_1[0];
296 gsombloc[ blockIdx.x + gridDim.x ] = (t_sum_x2) scumuls_x[0];
297 gsombloc[ blockIdx.x + 2*gridDim.x ] = (t_sum_x2) scumuls_x2[0];
300 //calculs freemans, centre et code segment
301 //1 uint4 par segment
305 Di = 1 + liste_pix[idx+1].x - liste_pix[idx].x ;
306 Dj = 1 + liste_pix[idx+1].y - liste_pix[idx].y ;
307 d_snake[segment].freeman_out = d_table_freeman[3*Di + Dj] ;
309 if (dy > 0 ) d_snake[segment].code_segment = -1 ;
310 if (dy < 0 ) d_snake[segment].code_segment = 1 ;
311 if (dy == 0) d_snake[segment].code_segment = 0 ;
314 if (tis == nb_pix-1){
315 Di = 1 + liste_pix[idx].x - liste_pix[idx-1].x ;
316 Dj = 1 + liste_pix[idx].y - liste_pix[idx-1].y;
317 d_snake[segment].freeman_in = d_table_freeman[3*Di + Dj] ;
320 if (tis == (nb_pix/2)){
321 d_snake[segment].centre_i = liste_pix[idx].x ;
322 d_snake[segment].centre_j = liste_pix[idx].y ;
327 sommme des contribs par bloc -> contribs segment, pour le snake
329 execution sur : 1bloc / 1 thread par segment
332 __global__ void somsom_snake(t_sum_x2 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake){
335 unsigned int seg = blockIdx.x ;
337 //un thread par segment
344 for (int b=0; b < nb_bl_seg ; b++){
345 sdata[0] += somblocs[seg*nb_bl_seg + b];
346 sdata[1] += somblocs[(seg + nb_nodes)*nb_bl_seg + b];
347 sdata[2] += somblocs[(seg + 2*nb_nodes)*nb_bl_seg + b];
352 d_snake[seg].sum_1 = sdata[0];
353 d_snake[seg].sum_x = sdata[1];
354 d_snake[seg].sum_x2 = sdata[2];
358 __device__ double codage_gl_gauss(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
359 uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
360 uint64 stat_sum_xe ; /* somme des xn region exterieure */
361 uint32 ne ; /* nombre de pixel region exterieure */
362 double sigi2, sige2; /* variance region interieure et exterieure */
364 /* variance des valeurs des niveaux de gris a l'interieur du snake */
366 ((double)stat_sum_x2/(double)stat_sum_1) -
367 ((double)stat_sum_x/(uint64)stat_sum_1)*((double)stat_sum_x/(uint64)stat_sum_1) ;
369 /* variance des valeurs des niveaux de gris a l'exterieur du snake */
370 ne = n_dim-stat_sum_1 ;
371 stat_sum_xe = SUM_X - stat_sum_x ;
373 ((double)SUM_X2-stat_sum_x2)/(double)ne -
374 ((double)stat_sum_xe/(uint64)ne)*((double)stat_sum_xe/(uint64)ne) ;
376 if ((sigi2 > 0) && (sige2 > 0))
377 return 0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
382 __global__ void calcul_stats_snake(snake_node_gpu * d_snake, int nnodes, int64 * d_stats_snake, double * vrais_min,
383 t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * TABLE_CODAGE, uint32 l
387 int id_nx, id_nprec, id_nprecprec ;
388 int code_noeud, code_segment, pos ;
389 __shared__ int64 s_stats_snake[3] ;
391 //init stats en shared mem
392 s_stats_snake[0] = 0 ;
393 s_stats_snake[1] = 0 ;
394 s_stats_snake[2] = 0 ;
397 for (id_nx = 0; id_nx < nnodes; id_nx++)
399 if (id_nx == 0) id_nprec = nnodes - 1;
400 else id_nprec = id_nx - 1;
401 if (id_nprec == 0) id_nprecprec = nnodes -1 ;
402 else id_nprecprec = id_nprec - 1 ;
403 /* gestion des segments partant du noeud */
404 /* vers le noeud suivant dans l'ordre trigo */
405 code_segment = d_snake[id_nprec].code_segment ;
406 if (code_segment > 0)
408 /* on somme les contributions */
409 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
410 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
411 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
413 else if (code_segment < 0)
415 /* on soustrait les contributions */
416 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
417 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
418 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
420 // else (code_segment == 0), on ne fait rien
421 /* gestion des pixels connectant les segments */
422 /* pixel de depart du segment actuel np --> np->noeud_suiv */
423 /* freeman_out = np->freeman_out ; */
424 /* freeman_in = np->noeud_prec->freeman_in ; */
425 pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
426 code_noeud = TABLE_CODAGE[pos] ;
427 pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
431 /* on somme les contributions */
432 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
433 s_stats_snake[1] += cumul_x[pos] ;
434 s_stats_snake[2] += cumul_x2[pos] ;
436 else if (code_noeud < 0)
438 /* on soustrait les contributions */
439 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
440 s_stats_snake[1] -= cumul_x[pos] ;
441 s_stats_snake[2] -= cumul_x2[pos] ;
443 // else (code_pixel == 0), on ne fait rien
445 d_stats_snake[0] = s_stats_snake[0] ;
446 d_stats_snake[1] = s_stats_snake[1] ;
447 d_stats_snake[2] = s_stats_snake[2] ;
449 *vrais_min = codage_gl_gauss(s_stats_snake[0], s_stats_snake[1], s_stats_snake[2],
450 d_stats_snake[3], d_stats_snake[4], d_stats_snake[5]);
453 // kernel d'init rectangulaire au niveau snake
454 // un block par point de base et un point opposé par thread du bloc
456 __global__ void calcul_contribs_snake4(snake_node_gpu * snake, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int h, int l,
457 int64 * sums, t_rectangle_snake * critere)
459 // nb de diagonales testees par bloc (ie. par point de base NO)
460 int blockSize = blockDim.x ;
461 // indice du second point de chaque diagonale (=Opposite Point, = point SE)
462 int OPib = threadIdx.x ;
463 // coordonnees de chaque point de base (NO)
464 int BPi = blockIdx.x ;
465 int BPj = blockIdx.y ;
466 //coordonnees de chaque Opposite Point (SE)
467 double incThread = ((h-BPi)*(l-BPj) + blockSize -1)/(double)blockSize ;
468 int OPi = (double)(OPib*incThread)/(l - BPj) ;
469 int OPj = OPib*incThread - OPi*(l-BPj) ;
472 if (OPi >= h) OPi = h-1 ;
473 if (OPj >= l) OPj = l-1 ;
474 //indices des pixels dans les images cumulees
477 int C1 = (OPi - BPi)*(OPj - BPj) ;
479 //pour stocker contribs de chaque snake d'un block
480 //TODO on peut utiliser une structure restreinte (sans le c1)
481 extern __shared__ tcontribs scumuls[];
483 //calcul contribs du snake
484 scumuls[CFI(OPib)].cx = 0;
485 scumuls[CFI(OPib)].cx2 = 0;
486 for (int k=BPi ; k < OPi ; k++)
488 posG = (BPi+k)*l + BPj ;
489 posD = posG - BPj + OPj ;
490 scumuls[CFI(OPib)].cx += (cumul_x[ posD ] - cumul_x[ posG ]) ;
491 scumuls[CFI(OPib)].cx2 += (cumul_x2[ posD ] - cumul_x2[ posG ]);
494 //calcul de critère pour chaque snake
495 uint64 stat_sum_xe ; /* somme des xn region exterieure */
496 uint32 ne ; /* nombre de pixel region exterieure */
497 double sigi2, sige2; /* variance region interieure et exterieure */
500 /* variance des valeurs des niveaux de gris a l'interieur du snake */
502 ((double)scumuls[CFI(OPib)].cx2/(double)C1) -
503 ((double)scumuls[CFI(OPib)].cx/(uint64)C1)*((double)scumuls[CFI(OPib)].cx/(uint64)C1) ;
505 /* variance des valeurs des niveaux de gris a l'exterieur du snake */
508 stat_sum_xe = sums[4] - scumuls[CFI(OPib)].cx ;
510 ((double)sums[5]-scumuls[CFI(OPib)].cx2)/(double)ne -
511 ((double)stat_sum_xe/(uint64)ne)*((double)stat_sum_xe/(uint64)ne) ;
512 index_crit = blockSize*(BPi*gridDim.y + BPj) + OPib ;
514 critere[ index_crit ].bpi = BPi;
515 critere[ index_crit ].bpj = BPj;
516 critere[ index_crit ].opi = OPi;
517 critere[ index_crit ].opj = OPj;
519 if ((sigi2 > 0)|(sige2 > 0))
520 critere[ index_crit ].crit = 0.5*((double)C1*log(sigi2) + (double)ne*log(sige2)) ;
522 critere[ index_crit ].crit = -1 ;
524 // identification meilleur snake du bloc
525 // laissé au CPU pour test mais le principe de ce kernel n'est pas efficace.
528 __global__ void calcul_contribs_cols(t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int h, int l, tcontribs * sums )
531 int bs = blockDim.x ; // nb pixels par bloc
532 int nbC = gridDim.x ; // nb de colonnes traitees
533 int bpc = gridDim.y ; // nb de blocs par colonne
534 int idC = blockIdx.x ; // indice de la colonne ds la grille
535 int idB = blockIdx.y ; // indice du bloc de pixels ds la colonne
536 int tib = threadIdx.x ; // indice du thread ds le bloc courant
538 int i = idB*bs + tib ; // ligne du pixel
539 int j = idC * (l/nbC) ; // colonne du pixel
540 int pos = i*l + j ; // index absolu du pixel ds l'image
542 extern __shared__ tcontribs scontrib[]; // pour stocker les contribs partielles
546 scontrib[ CFI(tib) ].cx = cumul_x[ pos ] ;
547 scontrib[ CFI(tib) ].cx2= cumul_x2[pos ] ;
551 scontrib[ CFI(tib) ].cx = 0 ;
552 scontrib[ CFI(tib) ].cx2= 0 ;
556 // somme des contribs individuelles par bloc
557 // unroll des sommes partielles en smem
560 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 512) ].cx;
561 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 512) ].cx2;
568 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 256) ].cx;
569 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 256) ].cx2;
576 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 128) ].cx;
577 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 128) ].cx2;
583 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 64) ].cx;
584 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 64) ].cx2;
589 //32 threads <==> 1 warp
592 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 32) ].cx;
593 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 32) ].cx2;
597 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 16) ].cx;
598 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 16) ].cx2;
602 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 8) ].cx;
603 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 8) ].cx2;
607 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 4) ].cx;
608 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 4) ].cx2;
612 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 2) ].cx;
613 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 2) ].cx2;
617 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 1) ].cx;
618 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 1) ].cx2;
623 // resultat contribs partielles ( par bloc) en gmem
625 // c1 s'obtient directement car les sommes sont à j constant ( j=idC )
626 sums[ idC*bpc +idB ].cx = scontrib[0].cx ;
627 sums[ idC*bpc +idB ].cx2 = scontrib[0].cx2 ;
632 sommme des contribs par bloc -> contribs colonnes
633 execution sur : (1 bloc de 1 thread) par colonne
636 __global__ void somsom_contribs(tcontribs * somblocs, int bpc, tcontribs * somcols){
639 int col = blockIdx.x ;
642 //un thread par colonne
648 for (int b=0; b < bpc ; b++){
649 scontrib.cx += somblocs[ base +b ].cx ;
650 scontrib.cx2 += somblocs[ base +b ].cx2 ;
655 somcols[ col ].cx = scontrib.cx ;
656 somcols[ col ].cx2 = scontrib.cx2;
662 recherche des criteres minis dans les blocs
664 __device__ void mini_critere_bloc(double2 *critere, int bs){
666 int tib = threadIdx.x ;
668 critere[ CFI(tib) ].y = tib ; //initialisation des indices pour les minima
670 if ( (bs >= 1024) && (tib < 512) ) {
671 if ( critere[ CFI(tib + 512) ].x < critere[ CFI(tib) ].x ){
672 critere[ CFI(tib) ] = critere[ CFI(tib + 512) ] ;
677 if ( (bs >= 512) && (tib < 256) ) {
678 if ( critere[ CFI(tib + 256) ].x < critere[ CFI(tib) ].x ){
679 critere[ CFI(tib) ] = critere[ CFI(tib + 256) ] ;
684 if ( (bs >= 256) && (tib < 128) ) {
685 if ( critere[ CFI(tib + 128) ].x < critere[ CFI(tib) ].x ){
686 critere[ CFI(tib) ] = critere[ CFI(tib + 128) ] ;
691 if ( (bs >= 128) && (tib < 64) ) {
692 if ( critere[ CFI(tib + 64) ].x < critere[ CFI(tib) ].x ){
693 critere[ CFI(tib) ] = critere[ CFI(tib + 64) ] ;
698 //32 threads <==> 1 warp
700 if ( critere[ CFI(tib + 32) ].x < critere[ CFI(tib) ].x ){
701 critere[ CFI(tib) ] = critere[ CFI(tib + 32) ] ;
706 if ( critere[ CFI(tib + 16) ].x < critere[ CFI(tib) ].x ){
707 critere[ CFI(tib) ] = critere[ CFI(tib + 16) ] ;
712 if ( critere[ CFI(tib + 8) ].x < critere[ CFI(tib) ].x ){
713 critere[ CFI(tib) ] = critere[ CFI(tib + 8) ] ;
718 if ( critere[ CFI(tib + 4) ].x < critere[ CFI(tib) ].x ){
719 critere[ CFI(tib) ] = critere[ CFI(tib + 4) ] ;
724 if ( critere[ CFI(tib + 2) ].x < critere[ CFI(tib) ].x ){
725 critere[ CFI(tib) ] = critere[ CFI(tib + 2) ] ;
730 if ( critere[ CFI(tib + 1) ].x < critere[ CFI(tib) ].x ){
731 critere[ CFI(tib) ] = critere[ CFI(tib + 1) ] ;
739 calcule, pour l'ensemble des permutations possibles
740 des colonnes j1 et j2 (j1<J2) :
741 - le critère correspondant
743 __global__ void calcul_contribs_permutations(tcontribs * somcols, int bpc, int h, int l, uint64 * stats_img, double2 * miniblocs){
745 int bs = blockDim.x ;
746 int j1 = blockIdx.x ;
747 int j2 = threadIdx.x ;
749 //shared mem dynamique 'critere' et 'indice'
750 extern __shared__ double2 critere[] ;
752 critere[ CFI(j2) ].y = j2 ; //initialisation des indices pour les minima
759 int ni = h*(colj2 - colj1) ;
760 int ne = h*l - ni ; // h*l ou stats_img[3]
761 uint64 stat_sum_xi = somcols[j2].cx - somcols[j1].cx ;
762 uint64 stat_sum_xi2 = somcols[j2].cx2 - somcols[j1].cx2 ;
763 uint64 stat_sum_xe = stats_img[4] - stat_sum_xi ; /* somme des xn region exterieure */
764 uint64 stat_sum_xe2 = stats_img[5] - stat_sum_xi2 ;
765 double sigi2, sige2; /* variances regions interieure et exterieure */
767 /* variance des valeurs des niveaux de gris a l'interieur */
769 ((double)stat_sum_xi2/ni) -
770 ((double)stat_sum_xi/ni)*((double)stat_sum_xi/ni) ;
772 /* variance des valeurs des niveaux de gris a l'exterieur */
774 ((double)stat_sum_xe2)/ne -
775 ((double)stat_sum_xe/ne)*((double)stat_sum_xe/ne) ;
777 if ((sigi2 > 0)|(sige2 > 0))
778 critere[CFI(j2)].x = 0.5*((double)ni*log(sigi2) + (double)ne*log(sige2)) ;
779 else critere[CFI(j2)].x = DBL_MAX;
781 else critere[CFI(j2)].x = DBL_MAX ;
783 __syncthreads(); // on s'assure que toutes les valeurs des criteres sont calculees avant de chercher le mini
786 if ( (bs >= 1024) && (j2 < 512) ) {
787 if ( critere[ CFI(j2 + 512) ].x < critere[ CFI(j2) ].x ){
788 critere[ CFI(j2) ] = critere[ CFI(j2 + 512) ] ;
793 if ( (bs >= 512) && (j2 < 256) ) {
794 if ( critere[ CFI(j2 + 256) ].x < critere[ CFI(j2) ].x ){
795 critere[ CFI(j2) ] = critere[ CFI(j2 + 256) ] ;
800 if ( (bs >= 256) && (j2 < 128) ) {
801 if ( critere[ CFI(j2 + 128) ].x < critere[ CFI(j2) ].x ){
802 critere[ CFI(j2) ] = critere[ CFI(j2 + 128) ] ;
807 if ( (bs >= 128) && (j2 < 64) ) {
808 if ( critere[ CFI(j2 + 64) ].x < critere[ CFI(j2) ].x ){
809 critere[ CFI(j2) ] = critere[ CFI(j2 + 64) ] ;
814 //32 threads <==> 1 warp
816 if ( critere[ CFI(j2 + 32) ].x < critere[ CFI(j2) ].x ){
817 critere[ CFI(j2) ] = critere[ CFI(j2 + 32) ] ;
822 if ( critere[ CFI(j2 + 16) ].x < critere[ CFI(j2) ].x ){
823 critere[ CFI(j2) ] = critere[ CFI(j2 + 16) ] ;
828 if ( critere[ CFI(j2 + 8) ].x < critere[ CFI(j2) ].x ){
829 critere[ CFI(j2) ] = critere[ CFI(j2 + 8) ] ;
834 if ( critere[ CFI(j2 + 4) ].x < critere[ CFI(j2) ].x ){
835 critere[ CFI(j2) ] = critere[ CFI(j2 + 4) ] ;
840 if ( critere[ CFI(j2 + 2) ].x < critere[ CFI(j2) ].x ){
841 critere[ CFI(j2) ] = critere[ CFI(j2 + 2) ] ;
846 if ( critere[ CFI(j2 + 1) ].x < critere[ CFI(j2) ].x ){
847 critere[ CFI(j2) ] = critere[ CFI(j2 + 1) ] ;
849 //critere[0] contient maintenant les params du mini du bloc
850 miniblocs[ j1 ] = critere[0] ;
853 mini_critere_bloc(critere, bs) ;
854 if (j2 == 0) miniblocs[ j1 ] = critere[0] ;
858 __device__ void somme_contribs_blocs(tcontribs * scontrib, int bs){
859 int tib = threadIdx.x ;
860 // somme des contribs individuelles par bloc
861 // unroll des sommes partielles en smem
864 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 512) ].cx;
865 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 512) ].cx2;
872 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 256) ].cx;
873 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 256) ].cx2;
880 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 128) ].cx;
881 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 128) ].cx2;
887 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 64) ].cx;
888 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 64) ].cx2;
893 //32 threads <==> 1 warp
896 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 32) ].cx;
897 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 32) ].cx2;
901 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 16) ].cx;
902 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 16) ].cx2;
906 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 8) ].cx;
907 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 8) ].cx2;
911 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 4) ].cx;
912 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 4) ].cx2;
916 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 2) ].cx;
917 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 2) ].cx2;
921 scontrib[ CFI(tib) ].cx += scontrib[ CFI(tib + 1) ].cx;
922 scontrib[ CFI(tib) ].cx2 += scontrib[CFI(tib + 1) ].cx2;
929 effectue la somme (pix par pix) ds un bloc des contribs sur les colonnes j1 et j2 (j1 < j2)
930 Grille de calcul GPU :
931 -> threads = bs selon capacités/perfs
932 -> grid = div = (h+bs-1)/bs (h = nb lignes)
934 __global__ void calcul_contrib_conjuguee_colonnes(t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int h, int l, int j1, int j2, tcontribs * vect_contrib)
936 int bs = blockDim.x ;
937 int id_bloc = blockIdx.x ;
938 int tib = threadIdx.x ;
939 int idx = id_bloc * bs + tib ;
941 extern __shared__ tcontribs sh_contrib[] ;
944 sh_contrib[CFI(tib)].cx = cumul_x[ idx * l + j2 ] - cumul_x[ idx * l + j1 ] ;
945 sh_contrib[CFI(tib)].cx2= cumul_x2[ idx * l + j2 ] - cumul_x2[ idx * l + j1 ] ;
947 sh_contrib[CFI(tib)].cx = 0 ;
948 sh_contrib[CFI(tib)].cx2= 0 ;
950 __syncthreads(); // synchro avant de sommer
953 somme_contribs_blocs(sh_contrib, bs);
955 /*enregistrement somme des blocs*/
956 if (tib == 0) vect_contrib[ id_bloc ] = sh_contrib[0] ;
961 evalue les hauteurs les plus probables des horizontales
962 du rectangle 'englobant' (qui ne l'est pas nécessairement en fait)
963 Grille de calcul GPU :
964 -> threads = div = nb de blocs de lignes (Cf. calcul_contrib_conjuguee_colonnes() )
965 -> grid = div x div x 1
967 __global__ void calcul_contribs_snake_rectangle(tcontribs * vect_contribs, tcontribs * soms)
969 int bs = blockDim.x ;
970 int div = gridDim.x ;
971 int tib = threadIdx.x ;
972 int i1 = blockIdx.x ;
973 int i2 = blockIdx.y ;
975 extern __shared__ tcontribs scontribs[] ;
978 if ( (tib >= i1) && (tib <= i2) ) {
979 scontribs[CFI(tib)].cx = vect_contribs[tib].cx ;
980 scontribs[CFI(tib)].cx2= vect_contribs[tib].cx2;
982 scontribs[CFI(tib)].cx = 0;
983 scontribs[CFI(tib)].cx2 = 0;
987 somme_contribs_blocs(scontribs, bs);
989 /*ranger les sommes ds un vecteur en gmem*/
990 if (tib == 0) soms[ i1*div + i2 ] = scontribs[0] ;
993 soms[ i1*div + i2 ].cx = 0 ;
994 soms[ i1*div + i2 ].cx = 0 ;
1000 Evalue la valeur du critere pour chaque combinaison possible
1001 des blocs de lignes définis par calcul_contrib_conjuguee_colonnes()
1002 grille de calcul GPU :
1003 threads -> nextPow2 (div)
1006 TODO voir a inverser les indices i1/i2
1009 __global__ void calcul_critere_permutations_verticales(tcontribs *soms, int lpb, int j1, int j2, int h, int l, uint64 sigX, uint64 sigX2, double2 *miniblocs){
1012 int bs = blockDim.x ;
1013 int div = gridDim.x ;
1014 int i2 = threadIdx.x ;
1015 int i1 = blockIdx.x ;
1017 extern __shared__ double2 sh_mini[];
1019 if ( (i2 < div) && (i2 >= i1) )
1020 sh_mini[ CFI(i2) ].x = critere_gauss(n, (i2-i1+1)*lpb*(j2 - j1), soms[ i1*div +i2 ].cx, soms[ i1*div + i2 ].cx2, sigX, sigX2);
1021 else sh_mini[ CFI(i2) ].x = DBL_MAX ;
1024 mini_critere_bloc(sh_mini, bs) ;
1027 //miniblocs[i1] = sh_mini[0] ;
1028 miniblocs[i1].x = sh_mini[0].x ;
1029 miniblocs[i1].y = sh_mini[0].y ;