1 #include "constantes.h"
4 * determine et retourne le nb de pixels composant le segment (i,j)-(i1,j1)
7 __device__ int calcul_nb_pixels(int i, int j, int i1, int j1){
8 int absi, absj,nbpix =0;
9 //MAX( ABS(i1-i) , ABS(j1-j)) + 1
10 if (i1 > i) absi = i1 - i ; else absi = i - i1 ;
11 if (j1 > j) absj = j1 - j ; else absj = j - j1 ;
12 if (absi > absj ) nbpix = absi+1 ; else nbpix = absj+1 ;
17 construit la liste des coordonnées des 8 positions a tester pour l'ensemble des N noeuds du snake
18 ainsi que le liste des nombres de pixels correspondant (en z, seg avant, en w seg apres)
19 a executer avec N blocs de 8 threads
21 __global__ void liste_positions_a_tester(snake_node_gpu * d_snake, uint4 * liste_positions, uint32 * nb_pix_max, int pas, int nb_nodes, int h, int l){
22 int tib = threadIdx.x; // une position par thread
23 int node = blockIdx.x; // 1 noeud par bloc de threads
24 int node_prec, node_suiv ; // indices des nodes
25 int i, j, i1, j1, i2, j2, i3, j3, npix_prec, npix_suiv ; // coordonnees des noeuds , nb de pixels
27 //lecture des coordonnees
28 node_prec = (node == 0)? (nb_nodes-1) : (node - 1) ;
29 node_suiv = (node == nb_nodes-1)? (0) : (node + 1) ;
30 i1 = d_snake[node_prec].posi ;
31 j1 = d_snake[node_prec].posj ;
32 i2 = d_snake[node].posi ;
33 j2 = d_snake[node].posj ;
34 i3 = d_snake[node_suiv].posi ;
35 j3 = d_snake[node_suiv].posj ;
37 switch(tib){ // on considere un voisinage a 8 points
40 if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
43 if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
44 if (i2 > pas ) i = i2 - pas ; else i = 1 ;
47 if (i2 > pas ) i = i2 - pas ; else i = 1 ;
51 if (i2 > pas) i = i2 - pas ; else i = 1 ;
52 if (j2 > pas) j = j2 - pas ; else j = 1 ;
56 if (j2 > pas) j = j2 - pas ; else j = 1 ;
59 if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
60 if (j2 > pas) j = j2 - pas ; else j = 1 ;
63 if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
67 if ((i2 + pas) < h) i = i2 + pas ; else i = h-2 ;
68 if ((j2 + pas) < l) j = j2 + pas ; else j = l-2 ;
72 //calcul des nombres de pixels dans chaque cas
73 npix_prec = calcul_nb_pixels(i,j,i1,j1) ;
74 npix_suiv = calcul_nb_pixels(i,j,i3,j3) ;
76 liste_positions[8*node + tib] = make_uint4(i,j, (uint)npix_prec, (uint)npix_suiv );
78 // calcule du maximum global du nb de pixels
79 if ((node == 0) && (tib == 0))
82 for (int n=0; n<nb_nodes; n++)
84 if (liste_positions[n].z > *nb_pix_max) *nb_pix_max = liste_positions[n].z ;
85 if (liste_positions[n].w > *nb_pix_max) *nb_pix_max = liste_positions[n].w ;
92 * - les coordonnees de chaque pixel de chaque segment a evaluer pour les 8 voisins de chaque noeud (pair ou impair)
93 * cela represente 16 segments par noeud pair/impair
94 * - les contributions de chacun de ces pixels
95 * - les sommes, par blocs, des contributions des pixels (les sommes totales sont faites par le kernel somsom)
96 * - le code de chaque segment envisage
99 __global__ void calcul_contribs_segments_blocs_full(snake_node_gpu * d_snake, int nb_nodes, uint4 * liste_points, uint32 npix_max,
100 t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * d_codes_x16,
101 int l, uint2 * liste_pix, uint64 * gsombloc, bool pairs)
103 // indices des elements
104 int blockSize = blockDim.x ; // nb threads par bloc
105 int tib = threadIdx.x ; // position du thread dans le bloc
106 int nblocs_noeud = gridDim.x / nb_nodes ; // nb de blocs dédié à chaque noeud
107 int nblocs_seg = nblocs_noeud / 16 ; // nb de blocs dédiés à un segment de test
108 int idx = blockDim.x*blockIdx.x + threadIdx.x ; // position absolue du thread ds la grille
109 int id_interval = blockIdx.x / nblocs_noeud ; // indice de l'intervalle du noeud dans la grille
110 int segment = ( blockIdx.x - id_interval*nblocs_noeud )/nblocs_seg ; // indice du segment de 0 à 15
111 int tis = idx - ( id_interval*nblocs_noeud + segment*nblocs_seg )*blockDim.x ; // position du thread ds le segment
112 int id_base_seg = 16*id_interval + segment ; // indice du segment courant
113 int id_base_pix = 5*id_base_seg ; // indice du pixel 0/5 du segment courant dans la liste_pix pour le calcul des freemans
115 //tab pour contribs pixels
116 extern __shared__ tcontribs scumuls[];
118 //coordonnees des extremites de segment
119 uint x1, y1, x2, y2 ;
120 //indices des noeuds precedent(n1), courant(n2), suivant(n3)
124 // nb de pixels du segment precedent, suivant
127 // determine les indices des noeuds prec, courant, suiv
128 n1 = id_interval -1 ;
130 n3 = id_interval +1 ;
132 //gestion du bouclage du snake
133 if (n1 < 0) n1 = nb_nodes-1 ;
134 if (n3 >= nb_nodes) n3 = 0 ;
137 //affectation des differentes positions aux différents segments 'blocs de threads'
139 x1 = d_snake[n1].posj ;
140 y1 = d_snake[n1].posi ;
141 x2 = liste_points[8*n2 + segment].y ;
142 y2 = liste_points[8*n2 + segment].x ;
144 x1 = liste_points[8*n2 + segment-8].y ;
145 y1 = liste_points[8*n2 + segment-8].x ;
146 x2 = d_snake[n3].posj ;
147 y2 = d_snake[n3].posi ;
150 //params des deplacements
153 uint abs_dx = ABS(dx);
154 uint abs_dy = ABS(dy);
155 uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1);
159 //calcul liste des pixels du segment (x1,y1)-(x2,y2)
160 if (dy > 0) incy=1; else incy=-1 ;
161 if (dx > 0) incx=1; else incx=-1 ;
164 if (abs_dy > abs_dx){
165 //1 thread par ligne pente 1/k
166 double k = (double)dx/dy ;
168 p.x = y1 + incy*tis ;
169 p.y = x1 + floor((double)incy*k*tis+0.5) ;
171 //1 thread par colonne pente k
172 double k=(double)dy/dx ;
174 p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
175 p.y = x1 + incx*tis ;
176 // ordonnees des pixels suivant & precedent
178 xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
179 xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
182 // memorisation des valeurs necessaires au calcul des freemans et des centres
183 if (tis == 0) liste_pix[id_base_pix] = make_uint2(p.x, p.y) ;
184 if (tis == 1) liste_pix[id_base_pix +1] = make_uint2(p.x,p.y) ;
185 if (tis == nb_pix/2) liste_pix[id_base_pix +2] = make_uint2(p.x,p.y) ;
186 if (tis == nb_pix-2) liste_pix[id_base_pix +3] = make_uint2(p.x,p.y) ;
187 if (tis == nb_pix-1) liste_pix[id_base_pix +4] = make_uint2(p.x,p.y) ;
191 // calcul contribs individuelles des pixels
192 // dans le cas des segments 'plutot horizontaux', on ne garde qu'une contrib par ligne ; celle du pixel le plus a l'interieur du snake
193 if ( (tis >0) && (tis < nb_pix-1)
194 && ( ((abs_dy <= abs_dx) && ( ( xprec > p.x) || ( xsuiv > p.x)))
195 || (abs_dy > abs_dx) ) )
197 int pos = p.x * l + p.y ;
198 scumuls[ CFI(tib)].c1 = 1 + p.y ;
199 scumuls[ CFI(tib)].cx = cumul_x[ pos ] ;
200 scumuls[CFI(tib)].cx2 = cumul_x2[ pos ];
202 scumuls[ CFI(tib)].c1 = 0;
203 scumuls[ CFI(tib)].cx = 0;
204 scumuls[ CFI(tib)].cx2 = 0;
208 // somme des contribs individuelles
209 // unroll des sommes partielles en shared memory
210 if (blockSize >= 512) {
212 scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 256) ].c1;
213 scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 256) ].cx;
214 scumuls[ CFI(tib)].cx2 += scumuls[CFI(tib + 256) ].cx2;
219 if (blockSize >= 256) {
221 scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 128) ].c1;
222 scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 128) ].cx;
223 scumuls[ CFI(tib)].cx2 += scumuls[CFI(tib + 128) ].cx2;
227 if (blockSize >= 128) {
229 scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 64) ].c1;
230 scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 64) ].cx;
231 scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 64) ].cx2;
236 //32 threads <==> 1 warp
237 volatile tcontribs * scontribs = scumuls ;
240 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 32) ].c1;
241 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 32) ].cx;
242 scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 32) ].cx2;
246 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 16) ].c1;
247 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 16) ].cx;
248 scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 16) ].cx2;
252 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 8) ].c1;
253 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 8) ].cx;
254 scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 8) ].cx2;
258 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 4) ].c1;
259 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 4) ].cx;
260 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 4) ].cx2;
264 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 2) ].c1;
265 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 2) ].cx;
266 scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 2) ].cx2;
270 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 1) ].c1;
271 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 1) ].cx;
272 scontribs[CFI(tib)].cx2 += scontribs[CFI(tib + 1) ].cx2;
274 // resultat sommes partielles en gmem
276 gsombloc[ blockIdx.x ] = scontribs[0].c1 ;
277 gsombloc[ blockIdx.x + gridDim.x ] = scontribs[0].cx ;
278 gsombloc[ blockIdx.x + 2*gridDim.x ] = scontribs[0].cx2 ;
281 if (dy > 0 ) d_codes_x16[id_base_seg] = -1 ;
282 if (dy < 0 ) d_codes_x16[id_base_seg] = 1 ;
283 if (dy == 0) d_codes_x16[id_base_seg]= 0 ;
291 calcul des freeman et du centre de chaque segment de test
292 a executer sur 'n_interval' blocs de 16 threads
293 soit un thread par segment
295 __global__ void calcul_freemans_centre(uint2 * liste_pix, int * d_table_freeman, uint4 * d_freemans_x16){
297 int id_segment = threadIdx.x ;
298 int id_freeman = ( blockDim.x*blockIdx.x + id_segment ) ;
299 int id_base_pix = 5*id_freeman ;
301 //calculs freemans, centre et code segment
302 //1 uint4 par segment
303 int Dio, Djo, Dii, Dji;
306 Dio = 1 + liste_pix[id_base_pix +1].x - liste_pix[id_base_pix].x ;
307 Djo = 1 + liste_pix[id_base_pix +1].y - liste_pix[id_base_pix].y ;
308 d_freemans_x16[id_freeman].z = d_table_freeman[3*Dio + Djo] ;
312 Dii = 1 + liste_pix[id_base_pix +4].x - liste_pix[id_base_pix +3].x ;
313 Dji = 1 + liste_pix[id_base_pix +4].y - liste_pix[id_base_pix +3].y ;
314 d_freemans_x16[id_freeman].w = d_table_freeman[3*Dii + Dji] ;
317 d_freemans_x16[id_freeman].x = liste_pix[id_base_pix +2].x ;
318 d_freemans_x16[id_freeman].y = liste_pix[id_base_pix +2].y ;
324 calcul des contribs 1, x et x2 des 16 segments
326 a partir des sommes partielles des blocs
327 1 bloc / 1 thread par segment
330 __global__ void somsom_full(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, uint64 * somsom){
333 unsigned int seg = blockIdx.x ;
334 unsigned int nb_seg = gridDim.x ;
336 //un thread par segment
343 for (int b=0; b < nb_bl_seg ; b++){ //voir atomicadd 64bits
344 sdata[0] += somblocs[seg*nb_bl_seg + b];
345 sdata[1] += somblocs[(seg + nb_seg)*nb_bl_seg + b];
346 sdata[2] += somblocs[(seg + 2*nb_seg)*nb_bl_seg + b];
351 somsom[3*seg] = sdata[0];
352 somsom[3*seg + 1] = sdata[1];
353 somsom[3*seg + 2] = sdata[2];
358 version GPU de la fonction definie ds src/lib_math.c
360 __device__ bool test_inf_gpu(double arg1, double arg2){
362 return (arg1 < (arg2*COEF_DECROI)) ;
364 return (arg1 < (arg2*INV_COEF_DECROI)) ;
368 version GPU de la fonction codage_niveau_gris_hyp_gaussienne
370 __device__ double codage_gl_hyp_gauss(uint64 stat_sum_1, uint64 stat_sum_x, uint64 stat_sum_x2,
371 uint64 n_dim, uint64 SUM_X, uint64 SUM_X2){
372 uint64 stat_sum_xe ; /* somme des xn region exterieure */
373 uint32 ne ; /* nombre de pixel region exterieure */
374 double sigi2, sige2; /* variance region interieure et exterieure */
376 /* variance des valeurs des niveaux de gris a l'interieur du snake */
378 (double)stat_sum_x2/(double)stat_sum_1 -
379 ((double)stat_sum_x/stat_sum_1)*((double)stat_sum_x/stat_sum_1) ;
381 /* variance des valeurs des niveaux de gris a l'exterieur du snake */
382 ne = n_dim-stat_sum_1 ;
383 stat_sum_xe = SUM_X - stat_sum_x ;
385 ((double)SUM_X2-stat_sum_x2)/ne -
386 ((double)stat_sum_xe/ne)*((double)stat_sum_xe/ne) ;
388 if ((sigi2 > 0)&&(sige2 > 0))
389 return 0.5*((double)stat_sum_1*log(sigi2) + (double)ne*log(sige2)) ;
394 soustrait, pour chaque intervalle [N1--Nx--N2]
395 les contributions des segments N1--Nx et Nx--N2
397 A executer par nnodes blocs de 1 thread par intervalle
400 __global__ void soustrait_aux_stats_2N_segments_noeud(snake_node_gpu * d_snake, int64 * d_stats_snake, int64 * d_stats_ref,
401 t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
402 int * TABLE_CODAGE, uint32 l
405 int nnodes = gridDim.x ;
406 int id_nx, id_nprec, id_nprecprec, id_nsuiv ;
408 __shared__ int64 s_stats_snake[3] ;
411 if (id_nx == 0) id_nprec = nnodes - 1;
412 else id_nprec = id_nx - 1;
413 if (id_nprec == 0) id_nprecprec = nnodes -1 ;
414 else id_nprecprec = id_nprec - 1 ;
415 if (id_nx == nnodes-1) id_nsuiv = 0;
416 else id_nsuiv = id_nx + 1 ;
418 //init avec les valeurs du contour actuel
419 s_stats_snake[0] = d_stats_snake[0] ;
420 s_stats_snake[1] = d_stats_snake[1] ;
421 s_stats_snake[2] = d_stats_snake[2] ;
423 /* segment Na -- Nx */
424 if (d_snake[id_nprec].code_segment > 0)
426 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
427 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
428 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
430 else if (d_snake[id_nprec].code_segment < 0)
432 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
433 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
434 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
436 // else (code_segment_NaNx == 0), on ne fait rien
438 /* gestion des pixels connectant les segments */
439 /* pixel de depart du segment Na --> Nx */
440 pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
441 code_noeud = TABLE_CODAGE[pos] ;
442 pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
445 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
446 s_stats_snake[1] -= cumul_x[pos] ;
447 s_stats_snake[2] -= cumul_x2[pos];
449 else if (code_noeud < 0)
451 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
452 s_stats_snake[1] += cumul_x[pos] ;
453 s_stats_snake[2] += cumul_x2[pos];
455 // else (code_noeud == 0), on ne fait rien
457 /* -------------------------- */
458 /* -------------------------- */
459 /* segment Nx -- Nb */
460 if ( d_snake[id_nx].code_segment > 0 )
462 // on soustrait la contribution
463 s_stats_snake[0] -= d_snake[id_nx].sum_1 ;
464 s_stats_snake[1] -= d_snake[id_nx].sum_x ;
465 s_stats_snake[2] -= d_snake[id_nx].sum_x2 ;
467 else if ( d_snake[id_nx].code_segment < 0)
469 s_stats_snake[0] += d_snake[id_nx].sum_1 ;
470 s_stats_snake[1] += d_snake[id_nx].sum_x ;
471 s_stats_snake[2] += d_snake[id_nx].sum_x2 ;
473 // else (code_segment_NxNb == 0), on ne fait rien
475 /* gestion des pixels connectant les segments */
476 /* pixel de depart du segment Nx --> Nb */
477 pos = d_snake[id_nprec].freeman_in*8 + d_snake[id_nx].freeman_out ;
478 code_noeud = TABLE_CODAGE[pos] ;
479 pos = d_snake[id_nx].posi*l + d_snake[id_nx].posj ;
482 s_stats_snake[0] -= 1 + d_snake[id_nx].posj ;
483 s_stats_snake[1] -= cumul_x[pos] ;
484 s_stats_snake[2] -= cumul_x2[pos];
486 else if (code_noeud < 0)
488 s_stats_snake[0] += 1 + d_snake[id_nx].posj ;
489 s_stats_snake[1] += cumul_x[pos] ;
490 s_stats_snake[2] += cumul_x2[pos];
492 // else (code_noeud == 0), on ne fait rien
494 /* pixel d'arrivee du segment Nx --> Nb */
495 pos = d_snake[id_nx].freeman_in*8 + d_snake[id_nsuiv].freeman_out ;
496 code_noeud = TABLE_CODAGE[pos] ;
497 pos = d_snake[id_nsuiv].posi*l + d_snake[id_nsuiv].posj ;
500 s_stats_snake[0] -= 1 + d_snake[id_nsuiv].posj ;
501 s_stats_snake[1] -= cumul_x[pos] ;
502 s_stats_snake[2] -= cumul_x2[pos];
504 else if (code_noeud < 0)
506 s_stats_snake[0] += 1 + d_snake[id_nsuiv].posj ;
507 s_stats_snake[1] += cumul_x[pos] ;
508 s_stats_snake[2] += cumul_x2[pos];
510 // else (code_noeud == 0), on ne fait rien
513 d_stats_ref[3*id_nx] = s_stats_snake[0] ;
514 d_stats_ref[3*id_nx + 1] = s_stats_snake[1] ;
515 d_stats_ref[3*id_nx + 2] = s_stats_snake[2] ;
521 calcul des stats associees a chaque position de test
523 EXEC : sur n_interval blocs de 8 threads
525 __global__ void calcul_stats_full(snake_node_gpu * d_snake, snake_node_gpu * d_snake_tmp, int nnodes, bool pairs, int64 * d_stats_snake,
526 int64 * d_stats_ref, int64 * d_stats, uint64 * d_contribs,
527 uint4 * d_liste_points, int * code_segment, uint4 * d_freemans,
528 int * d_table_codes, t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
529 uint32 h, uint32 l, double * vrais, double * vrais_min, bool * move){
531 int interval = blockIdx.x ;
532 int seg = threadIdx.x ;
534 int id_nx, id_nprec, id_nprecprec, id_nsuiv, id_seg ;
536 __shared__ int64 s_stats_snake[3*8] ;
539 if (id_nx == 0) id_nprec = nnodes - 1 ;
540 else id_nprec = id_nx - 1 ;
541 if (id_nprec == 0) id_nprecprec = nnodes -1 ;
542 else id_nprecprec = id_nprec - 1 ;
543 if (id_nx == nnodes-1) id_nsuiv = 0 ;
544 else id_nsuiv = id_nx + 1 ;
546 //chargement en smem , prevoir CFI car on a 24x64bits par blocs => conflits
547 s_stats_snake[3*thread + 0] = d_stats_ref[3*id_nx] ;
548 s_stats_snake[3*thread + 1] = d_stats_ref[3*id_nx + 1] ;
549 s_stats_snake[3*thread + 2] = d_stats_ref[3*id_nx + 2] ;
552 //stats segments N1-Nx
553 id_seg = 16*interval + seg ;
554 if ( code_segment[id_seg] > 0 ){
555 s_stats_snake[3*thread +0] += d_contribs[3*id_seg] ;
556 s_stats_snake[3*thread +1] += d_contribs[3*id_seg + 1 ] ;
557 s_stats_snake[3*thread +2] += d_contribs[3*id_seg + 2 ] ;
558 } else if ( code_segment[16*interval + seg] < 0 ) {
559 s_stats_snake[3*thread +0] -= d_contribs[3*id_seg] ;
560 s_stats_snake[3*thread +1] -= d_contribs[3*id_seg + 1] ;
561 s_stats_snake[3*thread +2] -= d_contribs[3*id_seg + 2] ;
564 //stats noeud N1(i1,j1)
565 int fo_N1 = d_freemans[id_seg].z ;
566 int fi_Nprecprec = d_snake[id_nprecprec].freeman_in ;
567 int pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
569 code_noeud = d_table_codes[fi_Nprecprec*8 + fo_N1];
571 s_stats_snake[3*thread +0] += 1 + d_snake[id_nprec].posj ;
572 s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
573 s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
574 } else if (code_noeud < 0){
575 s_stats_snake[3*thread +0] -= 1 + d_snake[id_nprec].posj ;
576 s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
577 s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
581 int fo_Nx = d_freemans[id_seg + 8].z ;
582 int fi_Nx = d_freemans[id_seg].w ;
583 int Nxi = d_liste_points[8*id_nx + seg].x ;
584 int Nxj = d_liste_points[8*id_nx + seg].y ;
587 code_noeud = d_table_codes[fi_Nx*8 + fo_Nx];
589 s_stats_snake[3*thread +0] += 1 + Nxj ;
590 s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
591 s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
594 s_stats_snake[3*thread +0] -= 1 + Nxj ;
595 s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
596 s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
599 //stats segments Nx-N2
601 id_seg = 16*interval + seg ;
602 if ( code_segment[id_seg] > 0 ){
603 s_stats_snake[3*thread +0] += d_contribs[3*id_seg] ;
604 s_stats_snake[3*thread +1] += d_contribs[3*id_seg + 1] ;
605 s_stats_snake[3*thread +2] += d_contribs[3*id_seg + 2] ;
607 if ( code_segment[id_seg] < 0 ) {
608 s_stats_snake[3*thread +0] -= d_contribs[3*id_seg] ;
609 s_stats_snake[3*thread +1] -= d_contribs[3*id_seg + 1] ;
610 s_stats_snake[3*thread +2] -= d_contribs[3*id_seg + 2] ;
613 //stats noeud N2(i2,j2)
614 int fi_N2 = d_freemans[id_seg].w ;
615 int fo_N2 = d_snake[id_nsuiv].freeman_out ;
616 pos = d_snake[id_nsuiv].posi*l + d_snake[id_nsuiv].posj ;
618 code_noeud = d_table_codes[fi_N2*8 + fo_N2];
620 s_stats_snake[3*thread +0] += 1 + d_snake[id_nsuiv].posj ;
621 s_stats_snake[3*thread +1] += cumul_x[ pos ] ;
622 s_stats_snake[3*thread +2] += cumul_x2[pos ] ;
625 s_stats_snake[3*thread +0] -= 1 + d_snake[id_nsuiv].posj ;
626 s_stats_snake[3*thread +1] -= cumul_x[ pos ] ;
627 s_stats_snake[3*thread +2] -= cumul_x2[pos ] ;
631 //voir si on peut s'en passer
632 d_stats[3*(8*interval + thread)] = s_stats_snake[3*thread +0];
633 d_stats[3*(8*interval + thread) + 1] = s_stats_snake[3*thread +1];
634 d_stats[3*(8*interval + thread) + 2] = s_stats_snake[3*thread +2];
636 //codage hyp gaussienne
637 uint64 stat_sum_xe[8] ; //somme des xn region exterieure
638 uint32 ne[8] ; // nombre de pixels region exterieure
639 double sigi2[8], sige2[8]; // carres des variances, regions interieure et exterieure
641 /* variance des valeurs des niveaux de gris a l'interieur du snake */
643 ((double)s_stats_snake[3*thread +2]/(double)s_stats_snake[3*thread +0]) -
644 ((double)s_stats_snake[3*thread +1]/s_stats_snake[3*thread +0])*((double)s_stats_snake[3*thread +1]/s_stats_snake[3*thread +0]) ;
646 /* variance des valeurs des niveaux de gris a l'exterieur du snake */
647 ne[thread] = h*l-s_stats_snake[3*thread +0] ;
648 stat_sum_xe[thread] = d_stats_snake[4] - s_stats_snake[3*thread +1] ;
650 (double)(d_stats_snake[5]-s_stats_snake[3*thread +2])/(double)ne[thread] -
651 ((double)stat_sum_xe[thread]/ne[thread])*((double)stat_sum_xe[thread]/ne[thread]) ;
653 if (sige2[thread]>0 && sigi2[thread]>0)
654 vrais[8*interval + thread] = 0.5*((double)s_stats_snake[3*thread]*log(sigi2[thread]) + (double)ne[thread]*log(sige2[thread])) ;
656 vrais[8*interval + thread] = -1.0;
660 move[id_nx] = false ;
662 double vrais_tmp = *vrais_min;
663 for (int v=0; v < 8; v++){
664 if ( (vrais[8*interval + v] > 0) && (vrais[8*interval + v] < vrais_tmp*COEF_DECROI) ) {
665 vrais_tmp = vrais[8*interval + v];
669 if ( (pos_optim >-1) && !croisement(d_snake, id_nx, d_liste_points[8*id_nx + pos_optim].x, d_liste_points[8*id_nx + pos_optim].y, nnodes) )
674 d_snake_tmp[id_nx].posi = d_liste_points[8*id_nx + pos_optim].x ;
675 d_snake_tmp[id_nx].posj = d_liste_points[8*id_nx + pos_optim].y ;
679 d_snake_tmp[id_nx].posi = d_snake[id_nx].posi ;
680 d_snake_tmp[id_nx].posj = d_snake[id_nx].posj ;
688 __global__ void recalcul_stats_snake(snake_node_gpu * d_snake, int nnodes, int64 * d_stats_snake, double * vrais_min,
689 t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, int * TABLE_CODAGE, uint32 l
693 int id_nx, id_nprec, id_nprecprec ;
694 int code_noeud, code_segment, pos;
695 int64 s_stats_snake[3] ;
697 //init stats en shared mem
698 s_stats_snake[0] = 0 ;
699 s_stats_snake[1] = 0 ;
700 s_stats_snake[2] = 0 ;
703 for (id_nx = 0; id_nx < nnodes; id_nx++)
705 if (id_nx == 0) id_nprec = nnodes - 1;
706 else id_nprec = id_nx - 1;
707 if (id_nprec == 0) id_nprecprec = nnodes -1 ;
708 else id_nprecprec = id_nprec - 1 ;
709 /* gestion des segments partant du noeud */
710 /* vers le noeud suivant dans l'ordre trigo */
711 code_segment = d_snake[id_nprec].code_segment ;
712 if (code_segment > 0)
714 /* on somme les contributions */
715 s_stats_snake[0] += d_snake[id_nprec].sum_1 ;
716 s_stats_snake[1] += d_snake[id_nprec].sum_x ;
717 s_stats_snake[2] += d_snake[id_nprec].sum_x2 ;
719 else if (code_segment < 0)
721 /* on soustrait les contributions */
722 s_stats_snake[0] -= d_snake[id_nprec].sum_1 ;
723 s_stats_snake[1] -= d_snake[id_nprec].sum_x ;
724 s_stats_snake[2] -= d_snake[id_nprec].sum_x2 ;
726 // else (code_segment == 0), on ne fait rien
727 /* gestion des pixels connectant les segments */
728 pos = d_snake[id_nprecprec].freeman_in*8 + d_snake[id_nprec].freeman_out ;
729 code_noeud = TABLE_CODAGE[pos] ;
730 pos = d_snake[id_nprec].posi*l + d_snake[id_nprec].posj ;
734 /* on somme les contributions */
735 s_stats_snake[0] += 1 + d_snake[id_nprec].posj ;
736 s_stats_snake[1] += cumul_x[pos] ;
737 s_stats_snake[2] += cumul_x2[pos] ;
739 else if (code_noeud < 0)
741 /* on soustrait les contributions */
742 s_stats_snake[0] -= 1 + d_snake[id_nprec].posj ;
743 s_stats_snake[1] -= cumul_x[pos] ;
744 s_stats_snake[2] -= cumul_x2[pos] ;
746 // else (code_pixel == 0), on ne fait rien
748 d_stats_snake[0] = s_stats_snake[0] ;
749 d_stats_snake[1] = s_stats_snake[1] ;
750 d_stats_snake[2] = s_stats_snake[2] ;
752 *vrais_min = codage_gl_hyp_gauss(s_stats_snake[0], s_stats_snake[1], s_stats_snake[2],
753 d_stats_snake[3], d_stats_snake[4], d_stats_snake[5]);
757 __global__ void ajoute_noeuds(snake_node_gpu * snake, snake_node_gpu * snake_tmp, int nnodes, int seuil, int * new_nb_nodes){
761 for (int id_nx=0; id_nx < nnodes; id_nx++){
762 //position du noeud existant
763 snake_tmp[id_cpy].posi = snake[id_nx].posi ;
764 snake_tmp[id_cpy].posj = snake[id_nx].posj ;
768 if ( snake_tmp[id_nx].nb_pixels > seuil)
770 //position du nouveau noeud
771 snake_tmp[id_cpy].posi = snake[id_nx].centre_i ;
772 snake_tmp[id_cpy].posj = snake[id_nx].centre_j ;
777 for (int id_nx=0; id_nx < id_cpy; id_nx++){
778 snake[id_cpy].posi = snake_tmp[id_nx].posi ;
779 snake[id_cpy].posj = snake_tmp[id_nx].posj ;
782 *new_nb_nodes = id_cpy-nnodes ;
785 // pour copier le contenu d'un snake dans un autre
786 // execution sur nnodes blocs de 1 threads
787 __global__ void copie_snake(snake_node_gpu * d_source, snake_node_gpu * d_dest){
788 int id = blockIdx.x ;
789 d_dest[id].posi = d_source[id].posi ;
790 d_dest[id].posj = d_source[id].posj ;
795 __global__ void recalcul_contribs_segments_snake(snake_node_gpu * d_snake, int nb_nodes,
796 t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2,
797 int l, uint2 * liste_pix, uint64 * gsombloc )
799 // indices des elements
800 int blockSize = blockDim.x ;
801 int tib = threadIdx.x ;
802 int nblocs_seg = gridDim.x / nb_nodes ;
803 int idx = blockDim.x*blockIdx.x + threadIdx.x ;
804 int segment = blockIdx.x / nblocs_seg ;
805 int tis = idx - segment*nblocs_seg*blockDim.x ;
807 //tab pour contribs pixels
808 extern __shared__ tcontribs scumuls[];
811 uint x1, y1, x2, y2 ;
818 //gestion du bouclage du snake
819 if (n2 >= nb_nodes) n2 = 0 ;
821 //affectation des differentes positions aux différents segments 'blocs de threads'
822 x1 = d_snake[n1].posj ;
823 y1 = d_snake[n1].posi ;
824 x2 = d_snake[n2].posj ;
825 y2 = d_snake[n2].posi ;
827 //params des deplacements
830 uint abs_dx = ABS(dx);
831 uint abs_dy = ABS(dy);
832 uint nb_pix = abs_dy>abs_dx?(abs_dy+1):(abs_dx+1); // alternative -> lecture ds liste_points[]
836 //calcul liste des pixels du segment (x1,y1)-(x2,y2)
837 if (dy > 0) incy=1; else incy=-1 ;
838 if (dx > 0) incx=1; else incx=-1 ;
841 if (abs_dy > abs_dx){
843 double k = (double)dx/dy ;
844 p.x = y1 + incy*tis ;
845 p.y = x1 + floor((double)incy*k*tis+0.5) ;
848 //1 thread par colonne
849 double k=(double)dy/dx ;
850 p.x = y1 + floor((double)(incx*k*tis)+0.5) ;
851 p.y = x1 + incx*tis ;
853 xsuiv = y1 + floor((double)(incx*k*(tis+1))+0.5) ;
854 xprec = y1 + floor((double)(incx*k*(tis-1))+0.5) ;
858 if (tis == 0) liste_pix[5*segment] = make_uint2(p.x, p.y) ;
859 if (tis == 1) liste_pix[5*segment +1] = make_uint2(p.x,p.y) ;
860 if (tis == nb_pix/2) liste_pix[5*segment +2] = make_uint2(p.x,p.y) ;
861 if (tis == nb_pix-2) liste_pix[5*segment +3] = make_uint2(p.x,p.y) ;
862 if (tis == nb_pix-1) liste_pix[5*segment +4] = make_uint2(p.x,p.y) ;
867 //calcul contribs individuelles des pixels
869 if ( (tis >0) && (tis < nb_pix-1)
870 && ( ( (abs_dy <= abs_dx) && ( ( xprec > p.x) || ( xsuiv > p.x)) )
871 || (abs_dy > abs_dx) ) )
873 int pos = p.x * l + p.y ;
874 scumuls[ CFI(tib)].c1 = 1+p.y;
875 scumuls[ CFI(tib)].cx = cumul_x[ pos ] ;
876 scumuls[CFI(tib)].cx2 = cumul_x2[ pos ];
878 scumuls[ CFI(tib)].c1 = 0;
879 scumuls[ CFI(tib)].cx = 0;
880 scumuls[CFI(tib)].cx2 = 0;
884 //somme des contribs individuelles
885 // unroll des sommes partielles en smem
887 if (blockSize >= 512) {
889 scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 256) ].c1;
890 scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 256) ].cx;
891 scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 256) ].cx2;
896 if (blockSize >= 256) {
898 scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 128) ].c1;
899 scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 128) ].cx;
900 scumuls[CFI(tib)].cx2 += scumuls[CFI(tib + 128) ].cx2;
904 if (blockSize >= 128) {
906 scumuls[ CFI(tib)].c1 += scumuls[ CFI(tib + 64) ].c1;
907 scumuls[ CFI(tib)].cx += scumuls[ CFI(tib + 64) ].cx;
908 scumuls[CFI(tib)].cx2 += scumuls[ CFI(tib + 64) ].cx2;
913 //32 threads <==> 1 warp
914 volatile tcontribs * scontribs = scumuls ;
918 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 32) ].c1;
919 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 32) ].cx;
920 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 32) ].cx2;
924 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 16) ].c1;
925 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 16) ].cx;
926 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 16) ].cx2;
930 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 8) ].c1;
931 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 8) ].cx;
932 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 8) ].cx2;}
934 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 4) ].c1;
935 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 4) ].cx;
936 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 4) ].cx2;
939 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 2) ].c1;
940 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 2) ].cx;
941 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 2) ].cx2;
944 scontribs[ CFI(tib)].c1 += scontribs[ CFI(tib + 1) ].c1;
945 scontribs[ CFI(tib)].cx += scontribs[ CFI(tib + 1) ].cx;
946 scontribs[ CFI(tib)].cx2 +=scontribs[ CFI(tib + 1) ].cx2;
947 // resultat sommes partielles en gmem
949 gsombloc[ blockIdx.x ] = scontribs[0].c1;
950 gsombloc[ blockIdx.x + gridDim.x ] = scontribs[0].cx;
951 gsombloc[ blockIdx.x + 2*gridDim.x ] = scontribs[0].cx2;
953 //calculs code segment
955 if (dy > 0 ) d_snake[segment].code_segment = -1 ;
956 if (dy < 0 ) d_snake[segment].code_segment = 1 ;
957 if (dy == 0) d_snake[segment].code_segment = 0 ;
962 __global__ void recalcul_freemans_centre(snake_node_gpu * snake, uint2 * liste_pix, int * d_table_freeman){
964 int id_segment = blockIdx.x ;
965 int nb_segments = gridDim.x ;
966 int id_base_pix = 5*id_segment ;
968 //calculs freemans, centre et code segment
969 //1 uint4 par segment
970 int Dio, Djo, Dii, Dji;
973 Dio = 1 + liste_pix[id_base_pix +1].x - liste_pix[id_base_pix].x ;
974 Djo = 1 + liste_pix[id_base_pix +1].y - liste_pix[id_base_pix].y ;
975 snake[id_segment].freeman_out = d_table_freeman[3*Dio + Djo] ;
978 Dii = 1 + liste_pix[id_base_pix +4].x - liste_pix[id_base_pix +3].x ;
979 Dji = 1 + liste_pix[id_base_pix +4].y - liste_pix[id_base_pix +3].y ;
980 snake[id_segment].freeman_in = d_table_freeman[3*Dii + Dji] ;
983 snake[id_segment].centre_i = liste_pix[id_base_pix +2].x ;
984 snake[id_segment].centre_j = liste_pix[id_base_pix +2].y ;
987 int nd = id_segment ;
988 int nd_suiv = nd + 1 ;
989 if (nd_suiv >= nb_segments ) nd_suiv = 0 ;
990 snake[id_segment].nb_pixels = calcul_nb_pixels(snake[nd].posi, snake[nd].posj, snake[nd_suiv].posi, snake[nd_suiv].posj) ;
994 sommme des contribs par bloc -> contribs segment, pour le snake
996 execution sur : 1bloc / 1 thread par segment
999 __global__ void resomsom_snake(uint64 * somblocs, int nb_nodes, unsigned int nb_bl_seg, snake_node_gpu * d_snake){
1002 unsigned int seg = blockIdx.x ;
1004 //un thread par segment
1011 for (int b=0; b < nb_bl_seg ; b++){
1012 sdata[0] += somblocs[seg*nb_bl_seg + b];
1013 sdata[1] += somblocs[(seg + nb_nodes)*nb_bl_seg + b];
1014 sdata[2] += somblocs[(seg + 2*nb_nodes)*nb_bl_seg + b];
1019 d_snake[seg].sum_1 = sdata[0];
1020 d_snake[seg].sum_x = sdata[1];
1021 d_snake[seg].sum_x2 = sdata[2];