2 texture<int, 2, cudaReadModeElementType> tex_img_in ;
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
18 extern __shared__ tcumuls sdata[];
19 //chargement en smem avec complement de 0
22 z = tex2D(tex_img_in, til, num_ligne) ;
32 //passe 1 : construction des sommes
34 for (int d = bs/2; d > 0; d >>= 1)
40 int i = __mul24(__mul24(2, stride), tib);
41 int ai = i + stride - 1;
42 int bi = CFI(ai + stride);
47 sdata[bi].x += sdata[ai].x;
48 sdata[bi].x2 += sdata[ai].x2;
54 //stockage somme du bloc en gmem
56 //mise a zero dernier element du bloc
61 t_cumul_x som_x = sdata[CFI(tib)].x;
62 t_cumul_x2 som_x2 = sdata[CFI(tib)].x2;
63 if (til < l){ //il ne faut pas ecrire de somme dans le dernier bloc, elle serait hors image
64 cumul_x[ pos_img ] = som_x;
65 cumul_x2[pos_img ] = som_x2;
67 gsomblocs[blockIdx.x] = som_x;
68 gsomblocs[blockIdx.x + offsetSom] = som_x2;
69 sdata[CFI(tib)].x = 0;
70 sdata[CFI(tib)].x2 = 0;
73 //Passe 2 : construction des scans
74 for (int d = 1; d <= (bs/2); d *= 2)
81 int i = __mul24(__mul24(2, stride), tib);
82 int ai = i + stride - 1;
83 int bi = CFI(ai + stride);
88 t_cumul_x tx = sdata[ai].x;
89 t_cumul_x2 tx2 = sdata[ai].x2;
91 sdata[ai].x = sdata[bi].x;
94 sdata[ai].x2 = sdata[bi].x2;
99 //transfert en gmem des scans
100 //il faut décaler à gauche de 1 element
102 if ( (til < l) && ( tib < (bs-1) ) ){
103 cumul_x[ pos_img ] = sdata[CFI(tib+1)].x;
104 cumul_x2[pos_img ] = sdata[CFI(tib+1)].x2;
112 kernel pour faire le prefixsum des sommes de blocs des lignes de l'image
113 les params d'executions kivonbien sont :
114 - threads : la moitié de la nextpow2 du nb de blocs par ligne
115 - grid : 2 x le nombre de blocs de sommes dans l'image , soit le nb_blocs_par_ligne x nb_lignes x 2
116 - shared mem : 2 x nextPow2(nb_blocs par ligne)
121 __global__ void scan_somblocs(uint64 * g_idata, int n_bl_l){
123 extern __shared__ uint64 temp[];
125 int tib = threadIdx.x;
126 int toff = blockIdx.x*n_bl_l; // offset des positions des sommes partielles dans le tableau g_idata
127 int nmax = blockDim.x*2; //nb max de sommes partielles par ligne
131 int bbi = tib + blockDim.x;
134 // chargement data en smem
135 temp[ CFI(aai) ] = (aai < n_bl_l)? g_idata[ toff + aai ] : 0;
136 temp[ CFI(bbi) ] = (bbi < n_bl_l)? g_idata[ toff + bbi ] : 0;
140 // passe 1 de bas en haut
141 for (int d = nmax/2; d > 0; d >>= 1)
147 int ai = CFI(offset*(2*tib+1)-1);
148 int bi = CFI(offset*(2*tib+2)-1);
150 temp[bi] += temp[ai];
156 // zero le dernier element
160 int index = CFI(nmax - 1);
161 g_idata[ toff + n_bl_l - 1 ] = temp[ index ]; //memorisation de la somme du bloc a sa place en gmem
165 // passe 2 de haut en bas
166 for (int d = 1; d < nmax; d *= 2)
174 int ai = CFI(offset*(2*tib+1)-1);
175 int bi = CFI(offset*(2*tib+2)-1);
179 temp[bi] += t; //tester atomicadd 64 bits
186 // transfert resultats en gmem decales d'un element vers la gauche
187 g_idata[ toff + aai ] = temp[ CFI(aai + 1) ]; //pour le demi tableau smem inferieur
188 if ( bbi < n_bl_l-1 ) g_idata[ toff + bbi ] = temp[CFI( bbi + 1) ]; //demi tableau smem sup. sauf dernier=somme.
193 __global__ void add_soms_to_cumuls(t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * gsomblocs,
194 unsigned int N_BLOCS_LIGNE, unsigned int baseline, unsigned int nb_lines){
196 int bs = blockDim.x ;
197 int offsetSom = N_BLOCS_LIGNE * nb_lines;
198 int tib = threadIdx.x ; //indice du thread dans le bloc
199 int idx = blockIdx.x*blockDim.x + tib ; //indice global du thread
200 int num_ligne = blockIdx.x / N_BLOCS_LIGNE ; //indice de la ligne du thread dans l'image partielle
201 int til = idx - num_ligne*bs*N_BLOCS_LIGNE ; //indice du thread ds la ligne
202 int pos = num_ligne*l + til;
203 int pos_img = pos + baseline*l ;
206 //chargement des valeurs a ajouter en smem 0<-->x et 1<-->x2
207 uint64 __shared__ ajout[2];
210 ajout[0] = gsomblocs[blockIdx.x -1 ];
211 ajout[1] = gsomblocs[blockIdx.x -1 + offsetSom];
212 __syncthreads(); //tester les nouveaux __sync__
216 cumul_x[pos_img] += ajout[0];
217 cumul_x2[pos_img]+= ajout[1];
222 //calcul des SUM_1, SUM_X et SUM_X2 de l'image
224 __global__ void calcul_stats_image( t_cumul_x * cumul_x, t_cumul_x2 * cumul_x2, uint32 h, uint32 l, uint64 * d_stats_snake){
225 uint64 sigX = 0, sigX2 = 0 ;
226 for (int i=l-1; i<h*l; i+=l)
231 d_stats_snake[3] = h*l ;
232 d_stats_snake[4] = sigX ;
233 d_stats_snake[5] = sigX2;