| [708] | 1 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 2 | // File   : transpose.c    | 
|---|
 | 3 | // Date   : september 2015 | 
|---|
 | 4 | // author : Alain Greiner | 
|---|
 | 5 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 6 | // This multi-threaded aplication transposes a raw image (one pbyte per pixel). | 
|---|
 | 7 | // It can run on a multi-processors, multi-clusters architecture, with one thread | 
|---|
 | 8 | // per processor, and uses the POSIX threads API.  | 
|---|
 | 9 | // | 
|---|
 | 10 | // The main() function can be launched on any processor P[x,y,l]. | 
|---|
 | 11 | // It makes the initialisations, launch (N-1) threads to run the execute() function | 
|---|
 | 12 | // on the (N-1) other processors than P[x,y,l], call himself the execute() function,  | 
|---|
 | 13 | // and finally call the instrument() function to display instrumentation results  | 
|---|
 | 14 | // when the parallel execution is completed. | 
|---|
 | 15 | // | 
|---|
 | 16 | // The input and output buffers containing the image are distributed in clusters. | 
|---|
 | 17 | // | 
|---|
 | 18 | // The execute() function read a set of lines from an input file on disk, | 
|---|
 | 19 | // to the local buffer buf_in[x][y], transpose it, write the result to a remote buffer  | 
|---|
 | 20 | // buf_out[x'][y'], display the content of the local buffer buf_out[x][y] to the | 
|---|
 | 21 | // frame buffer, and store it on disk to another output file.  | 
|---|
 | 22 | // | 
|---|
 | 23 | // - The image size must fit the frame buffer size. | 
|---|
 | 24 | // - The block size in block device must be 512 bytes. | 
|---|
 | 25 | // - The number of clusters  must be a power of 2 no larger than 256. | 
|---|
 | 26 | // - The number of processors per cluster must be a power of 2 no larger than 4. | 
|---|
 | 27 | /////////////////////////////////////////////////////////////////////////////////////// | 
|---|
 | 28 |  | 
|---|
 | 29 | #include "stdio.h" | 
|---|
 | 30 | #include "user_barrier.h" | 
|---|
 | 31 | #include "malloc.h" | 
|---|
 | 32 |  | 
|---|
 | 33 | #define BLOCK_SIZE            512                         // block size on disk | 
|---|
 | 34 | #define X_MAX                 16                          // max number of clusters in row | 
|---|
 | 35 | #define Y_MAX                 16                          // max number of clusters in column | 
|---|
 | 36 | #define PROCS_MAX             4                           // max number of procs per cluster | 
|---|
 | 37 | #define CLUSTER_MAX           (X_MAX * Y_MAX)             // max number of clusters | 
|---|
 | 38 | #define IMAGE_SIZE            256                         // image size : nlines = npixels | 
|---|
 | 39 | #define INPUT_FILE_PATH       "/misc/lena_256.raw"        // pathname on virtual disk | 
|---|
 | 40 | #define OUTPUT_FILE_PATH      "/home/lena_transposed.raw" // pathname on virtual disk | 
|---|
 | 41 |  | 
|---|
 | 42 | // macro to use a shared TTY | 
|---|
 | 43 | #define printf(...);    { lock_acquire( &tty_lock ); \ | 
|---|
 | 44 |                           giet_tty_printf(__VA_ARGS__);  \ | 
|---|
 | 45 |                           lock_release( &tty_lock ); } | 
|---|
 | 46 |  | 
|---|
 | 47 | /////////////////////////////////////////////////////// | 
|---|
 | 48 | // global variables stored in seg_data in cluster(0,0) | 
|---|
 | 49 | /////////////////////////////////////////////////////// | 
|---|
 | 50 |  | 
|---|
 | 51 | // instrumentation counters for each processor in each cluster  | 
|---|
 | 52 | unsigned int LOAD_START[X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 53 | unsigned int LOAD_END  [X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 54 | unsigned int TRSP_START[X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 55 | unsigned int TRSP_END  [X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 56 | unsigned int DISP_START[X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 57 | unsigned int DISP_END  [X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 58 | unsigned int STOR_START[X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 59 | unsigned int STOR_END  [X_MAX][Y_MAX][PROCS_MAX] = {{{ 0 }}}; | 
|---|
 | 60 |  | 
|---|
 | 61 | // arrays of pointers on distributed buffers | 
|---|
 | 62 | // one input buffer & one output buffer per cluster | 
|---|
 | 63 | unsigned char*  buf_in [CLUSTER_MAX]; | 
|---|
 | 64 | unsigned char*  buf_out[CLUSTER_MAX]; | 
|---|
 | 65 |  | 
|---|
 | 66 | // checksum variables  | 
|---|
 | 67 | unsigned check_line_before[IMAGE_SIZE]; | 
|---|
 | 68 | unsigned check_line_after[IMAGE_SIZE]; | 
|---|
 | 69 |  | 
|---|
 | 70 | // lock protecting shared TTY | 
|---|
 | 71 | user_lock_t  tty_lock; | 
|---|
 | 72 |  | 
|---|
 | 73 | // synchronisation barrier (all threads) | 
|---|
 | 74 | giet_sqt_barrier_t barrier; | 
|---|
 | 75 |  | 
|---|
 | 76 | //////////////////////////////////////////// | 
|---|
 | 77 | __attribute__ ((constructor)) void execute() | 
|---|
 | 78 | //////////////////////////////////////////// | 
|---|
 | 79 | { | 
|---|
 | 80 |     unsigned int l;                            // line index for loops | 
|---|
 | 81 |     unsigned int p;                            // pixel index for loops | 
|---|
 | 82 |  | 
|---|
 | 83 |     // get processor identifiers  | 
|---|
 | 84 |     unsigned int x_id;                         // x cluster coordinate | 
|---|
 | 85 |     unsigned int y_id;                         // y cluster coordinate | 
|---|
 | 86 |     unsigned int p_id;                         // local processor index | 
|---|
 | 87 |  | 
|---|
 | 88 |     giet_proc_xyp( &x_id, &y_id, &p_id);              | 
|---|
 | 89 |  | 
|---|
 | 90 |     // get & check plat-form parameters | 
|---|
 | 91 |     unsigned int x_size;                       // number of clusters in a row | 
|---|
 | 92 |     unsigned int y_size;                       // number of clusters in a column | 
|---|
 | 93 |     unsigned int nprocs;                       // number of processors per cluster | 
|---|
 | 94 |      | 
|---|
 | 95 |     giet_procs_number( &x_size , &y_size , &nprocs ); | 
|---|
 | 96 |  | 
|---|
 | 97 |     unsigned int nclusters     = x_size * y_size;               // number of clusters | 
|---|
 | 98 |     unsigned int nthreads      = x_size * y_size * nprocs;      // number of threads | 
|---|
 | 99 |     unsigned int npixels       = IMAGE_SIZE * IMAGE_SIZE;       // pixels per image | 
|---|
 | 100 |     int          fd_in         = 0;                             // initial file descriptor | 
|---|
 | 101 |     int          fd_out        = 0;                             // output file descriptor | 
|---|
 | 102 |     unsigned int cluster_id    = (x_id * y_size) + y_id;        // "continuous" index    | 
|---|
 | 103 |     unsigned int thread_id     = (cluster_id * nprocs) + p_id;  // "continuous" thread index | 
|---|
 | 104 |  | 
|---|
 | 105 |     // parallel load of image: | 
|---|
 | 106 |     // allocate buf_in and buf_out distributed buffers (one buf_in & one buf_out per cluster).  | 
|---|
 | 107 |     // open input and output files, and load the relevant lines in local buf_in. | 
|---|
 | 108 |     // only thread running on processor[x,y,0] does it. | 
|---|
 | 109 |  | 
|---|
 | 110 |     LOAD_START[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 111 |  | 
|---|
 | 112 |     if ( p_id == 0 )  | 
|---|
 | 113 |     { | 
|---|
 | 114 |         buf_in[cluster_id]  = remote_malloc( npixels/nclusters, x_id, y_id ); | 
|---|
 | 115 |         buf_out[cluster_id] = remote_malloc( npixels/nclusters, x_id, y_id ); | 
|---|
 | 116 |  | 
|---|
 | 117 |         if ( (x_id==0) && (y_id==0) ) | 
|---|
 | 118 |         { | 
|---|
 | 119 |             printf("\n[TRANSPOSE] Proc [%d,%d,%d] completes buffer allocation at cycle %d\n", | 
|---|
 | 120 |                    x_id, y_id, p_id, giet_proctime() ); | 
|---|
 | 121 |         } | 
|---|
 | 122 |  | 
|---|
 | 123 |         // open input file | 
|---|
 | 124 |         fd_in = giet_fat_open( INPUT_FILE_PATH , O_RDONLY );  // read_only | 
|---|
 | 125 |         if ( fd_in < 0 )  | 
|---|
 | 126 |         {  | 
|---|
 | 127 |             printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d] cannot open file %s\n", | 
|---|
 | 128 |                    x_id , y_id , p_id , INPUT_FILE_PATH ); | 
|---|
 | 129 |             giet_pthread_exit(" open() failure"); | 
|---|
 | 130 |         } | 
|---|
 | 131 |         else if ( (x_id==0) && (y_id==0) ) | 
|---|
 | 132 |         { | 
|---|
 | 133 |             printf("\n[TRANSPOSE] Proc [0,0,0] open file %s / fd = %d\n", | 
|---|
 | 134 |                    INPUT_FILE_PATH , fd_in ); | 
|---|
 | 135 |         } | 
|---|
 | 136 |  | 
|---|
 | 137 |         // open output file | 
|---|
 | 138 |         fd_out = giet_fat_open( OUTPUT_FILE_PATH , O_CREATE );   // create if required | 
|---|
 | 139 |         if ( fd_out < 0 )  | 
|---|
 | 140 |         {  | 
|---|
 | 141 |             printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d] cannot open file %s\n", | 
|---|
 | 142 |                             x_id , y_id , p_id , OUTPUT_FILE_PATH ); | 
|---|
 | 143 |             giet_pthread_exit(" open() failure"); | 
|---|
 | 144 |         } | 
|---|
 | 145 |         else if ( (x_id==0) && (y_id==0) ) | 
|---|
 | 146 |         { | 
|---|
 | 147 |             printf("\n[TRANSPOSE] Proc [0,0,0] open file %s / fd = %d\n", | 
|---|
 | 148 |                    OUTPUT_FILE_PATH , fd_out ); | 
|---|
 | 149 |         } | 
|---|
 | 150 |  | 
|---|
 | 151 |  | 
|---|
 | 152 |         unsigned int offset = ((npixels*cluster_id)/nclusters); | 
|---|
 | 153 |         if ( giet_fat_lseek( fd_in, | 
|---|
 | 154 |                              offset, | 
|---|
 | 155 |                              SEEK_SET ) != offset ) | 
|---|
 | 156 |         { | 
|---|
 | 157 |             printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d] cannot seek fd = %d\n", | 
|---|
 | 158 |                    x_id , y_id , p_id , fd_in ); | 
|---|
 | 159 |             giet_pthread_exit(" seek() failure"); | 
|---|
 | 160 |         } | 
|---|
 | 161 |  | 
|---|
 | 162 |         unsigned int pixels = npixels / nclusters; | 
|---|
 | 163 |         if ( giet_fat_read( fd_in, | 
|---|
 | 164 |                             buf_in[cluster_id], | 
|---|
 | 165 |                             pixels ) != pixels ) | 
|---|
 | 166 |         { | 
|---|
 | 167 |             printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d] cannot read fd = %d\n", | 
|---|
 | 168 |                    x_id , y_id , p_id , fd_in ); | 
|---|
 | 169 |             giet_pthread_exit(" read() failure"); | 
|---|
 | 170 |         } | 
|---|
 | 171 |  | 
|---|
 | 172 |         if ( (x_id==0) && (y_id==0) ) | 
|---|
 | 173 |         { | 
|---|
 | 174 |             printf("\n[TRANSPOSE] Proc [%d,%d,%d] completes load at cycle %d\n", | 
|---|
 | 175 |                    x_id, y_id, p_id, giet_proctime() ); | 
|---|
 | 176 |         } | 
|---|
 | 177 |     } | 
|---|
 | 178 |  | 
|---|
 | 179 |     LOAD_END[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 180 |  | 
|---|
 | 181 |     ///////////////////////////// | 
|---|
 | 182 |     sqt_barrier_wait( &barrier ); | 
|---|
 | 183 |     ///////////////////////////// | 
|---|
 | 184 |  | 
|---|
 | 185 |     // parallel transpose from buf_in to buf_out | 
|---|
 | 186 |     // each thread makes the transposition for nlt lines (nlt = IMAGE_SIZE/nthreads) | 
|---|
 | 187 |     // from line [thread_id*nlt] to line [(thread_id + 1)*nlt - 1] | 
|---|
 | 188 |     // (p,l) are the absolute pixel coordinates in the source image | 
|---|
 | 189 |  | 
|---|
 | 190 |     TRSP_START[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 191 |  | 
|---|
 | 192 |     unsigned int nlt   = IMAGE_SIZE / nthreads;    // number of lines per thread | 
|---|
 | 193 |     unsigned int nlc   = IMAGE_SIZE / nclusters;   // number of lines per cluster | 
|---|
 | 194 |  | 
|---|
 | 195 |     unsigned int src_cluster; | 
|---|
 | 196 |     unsigned int src_index; | 
|---|
 | 197 |     unsigned int dst_cluster; | 
|---|
 | 198 |     unsigned int dst_index; | 
|---|
 | 199 |  | 
|---|
 | 200 |     unsigned char byte; | 
|---|
 | 201 |  | 
|---|
 | 202 |     unsigned int first = thread_id * nlt;  // first line index for a given thread | 
|---|
 | 203 |     unsigned int last  = first + nlt;      // last line index for a given thread | 
|---|
 | 204 |  | 
|---|
 | 205 |     for ( l = first ; l < last ; l++ ) | 
|---|
 | 206 |     { | 
|---|
 | 207 |         check_line_before[l] = 0; | 
|---|
 | 208 |       | 
|---|
 | 209 |         // in each iteration we transfer one byte | 
|---|
 | 210 |         for ( p = 0 ; p < IMAGE_SIZE ; p++ ) | 
|---|
 | 211 |         { | 
|---|
 | 212 |             // read one byte from local buf_in | 
|---|
 | 213 |             src_cluster = l / nlc; | 
|---|
 | 214 |             src_index   = (l % nlc)*IMAGE_SIZE + p; | 
|---|
 | 215 |             byte        = buf_in[src_cluster][src_index]; | 
|---|
 | 216 |  | 
|---|
 | 217 |             // compute checksum | 
|---|
 | 218 |             check_line_before[l] = check_line_before[l] + byte; | 
|---|
 | 219 |  | 
|---|
 | 220 |             // write one byte to remote buf_out | 
|---|
 | 221 |             dst_cluster = p / nlc;  | 
|---|
 | 222 |             dst_index   = (p % nlc)*IMAGE_SIZE + l; | 
|---|
 | 223 |             buf_out[dst_cluster][dst_index] = byte; | 
|---|
 | 224 |         } | 
|---|
 | 225 |     } | 
|---|
 | 226 |  | 
|---|
 | 227 |     if ( (p_id == 0) && (x_id==0) && (y_id==0) ) | 
|---|
 | 228 |     { | 
|---|
 | 229 |         printf("\n[TRANSPOSE] proc [%d,%d,%d] completes transpose at cycle %d\n",  | 
|---|
 | 230 |         x_id, y_id, p_id, giet_proctime() ); | 
|---|
 | 231 |     } | 
|---|
 | 232 |  | 
|---|
 | 233 |     TRSP_END[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 234 |  | 
|---|
 | 235 |     ///////////////////////////// | 
|---|
 | 236 |     sqt_barrier_wait( &barrier ); | 
|---|
 | 237 |     ///////////////////////////// | 
|---|
 | 238 |  | 
|---|
 | 239 |     // parallel display from local buf_out to frame buffer | 
|---|
 | 240 |     // all threads contribute to display using memcpy... | 
|---|
 | 241 |  | 
|---|
 | 242 |     DISP_START[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 243 |  | 
|---|
 | 244 |     unsigned int  npt   = npixels / nthreads;   // number of pixels per thread | 
|---|
 | 245 |  | 
|---|
 | 246 |     giet_fbf_sync_write( npt * thread_id,  | 
|---|
 | 247 |                          &buf_out[cluster_id][p_id*npt],  | 
|---|
 | 248 |                          npt ); | 
|---|
 | 249 |  | 
|---|
 | 250 |     if ( (x_id==0) && (y_id==0) && (p_id==0) ) | 
|---|
 | 251 |     { | 
|---|
 | 252 |         printf("\n[TRANSPOSE] Proc [%d,%d,%d] completes display at cycle %d\n", | 
|---|
 | 253 |                x_id, y_id, p_id, giet_proctime() ); | 
|---|
 | 254 |     } | 
|---|
 | 255 |  | 
|---|
 | 256 |     DISP_END[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 257 |  | 
|---|
 | 258 |     ///////////////////////////// | 
|---|
 | 259 |     sqt_barrier_wait( &barrier ); | 
|---|
 | 260 |     ///////////////////////////// | 
|---|
 | 261 |  | 
|---|
 | 262 |     // parallel store : buf_out buffers to disk | 
|---|
 | 263 |     // only thread running on processor(x,y,0) does it | 
|---|
 | 264 |  | 
|---|
 | 265 |     STOR_START[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 266 |  | 
|---|
 | 267 |     if ( p_id == 0 ) | 
|---|
 | 268 |     { | 
|---|
 | 269 |         unsigned int offset = ((npixels*cluster_id)/nclusters); | 
|---|
 | 270 |         if ( giet_fat_lseek( fd_out, | 
|---|
 | 271 |                              offset, | 
|---|
 | 272 |                              SEEK_SET ) != offset ) | 
|---|
 | 273 |         { | 
|---|
 | 274 |             printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d] cannot seek fr = %d\n", | 
|---|
 | 275 |                    x_id , y_id , p_id , fd_out ); | 
|---|
 | 276 |             giet_pthread_exit(" seek() failure"); | 
|---|
 | 277 |         } | 
|---|
 | 278 |  | 
|---|
 | 279 |         unsigned int pixels = npixels / nclusters; | 
|---|
 | 280 |         if ( giet_fat_write( fd_out, | 
|---|
 | 281 |                              buf_out[cluster_id], | 
|---|
 | 282 |                              pixels ) != pixels ) | 
|---|
 | 283 |         { | 
|---|
 | 284 |             printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d] cannot write fd = %d\n", | 
|---|
 | 285 |                    x_id , y_id , p_id , fd_out ); | 
|---|
 | 286 |             giet_pthread_exit(" write() failure"); | 
|---|
 | 287 |         } | 
|---|
 | 288 |  | 
|---|
 | 289 |         if ( (x_id==0) && (y_id==0) ) | 
|---|
 | 290 |         { | 
|---|
 | 291 |             printf("\n[TRANSPOSE] Proc [%d,%d,%d] completes store at cycle %d\n", | 
|---|
 | 292 |                    x_id, y_id, p_id, giet_proctime() ); | 
|---|
 | 293 |         } | 
|---|
 | 294 |     } | 
|---|
 | 295 |  | 
|---|
 | 296 |     STOR_END[x_id][y_id][p_id] = giet_proctime(); | 
|---|
 | 297 |  | 
|---|
 | 298 |     // In each cluster, only thread running on Processor[x,y,0] releases | 
|---|
 | 299 |     // the distributed buffers and close the file descriptors. | 
|---|
 | 300 |  | 
|---|
 | 301 |     if ( p_id==0 ) | 
|---|
 | 302 |     { | 
|---|
 | 303 |         free( buf_in[cluster_id] ); | 
|---|
 | 304 |         free( buf_out[cluster_id] ); | 
|---|
 | 305 |  | 
|---|
 | 306 |         giet_fat_close( fd_in ); | 
|---|
 | 307 |         giet_fat_close( fd_out ); | 
|---|
 | 308 |     } | 
|---|
 | 309 |  | 
|---|
 | 310 |     if ( (x_id != 0) || (y_id != 0) || (p_id != 0) )  | 
|---|
 | 311 |     giet_pthread_exit( "completed" ); | 
|---|
 | 312 |  | 
|---|
 | 313 | } // end execute() | 
|---|
 | 314 |  | 
|---|
 | 315 |  | 
|---|
 | 316 |  | 
|---|
 | 317 | ////////////////////////////////////// | 
|---|
 | 318 | void instrument( unsigned int x_size, | 
|---|
 | 319 |                  unsigned int y_size, | 
|---|
 | 320 |                  unsigned int nprocs ) | 
|---|
 | 321 | ////////////////////////////////////// | 
|---|
 | 322 | { | 
|---|
 | 323 |     unsigned int x, y, l; | 
|---|
 | 324 |  | 
|---|
 | 325 |     unsigned int min_load_start = 0xFFFFFFFF; | 
|---|
 | 326 |     unsigned int max_load_start = 0; | 
|---|
 | 327 |     unsigned int min_load_ended = 0xFFFFFFFF; | 
|---|
 | 328 |     unsigned int max_load_ended = 0; | 
|---|
 | 329 |     unsigned int min_trsp_start = 0xFFFFFFFF; | 
|---|
 | 330 |     unsigned int max_trsp_start = 0; | 
|---|
 | 331 |     unsigned int min_trsp_ended = 0xFFFFFFFF; | 
|---|
 | 332 |     unsigned int max_trsp_ended = 0; | 
|---|
 | 333 |     unsigned int min_disp_start = 0xFFFFFFFF; | 
|---|
 | 334 |     unsigned int max_disp_start = 0; | 
|---|
 | 335 |     unsigned int min_disp_ended = 0xFFFFFFFF; | 
|---|
 | 336 |     unsigned int max_disp_ended = 0; | 
|---|
 | 337 |     unsigned int min_stor_start = 0xFFFFFFFF; | 
|---|
 | 338 |     unsigned int max_stor_start = 0; | 
|---|
 | 339 |     unsigned int min_stor_ended = 0xFFFFFFFF; | 
|---|
 | 340 |     unsigned int max_stor_ended = 0; | 
|---|
 | 341 |  | 
|---|
 | 342 |     for (x = 0; x < x_size; x++) | 
|---|
 | 343 |     { | 
|---|
 | 344 |         for (y = 0; y < y_size; y++) | 
|---|
 | 345 |         { | 
|---|
 | 346 |             for ( l = 0 ; l < nprocs ; l++ ) | 
|---|
 | 347 |             { | 
|---|
 | 348 |                 if (LOAD_START[x][y][l] < min_load_start)  min_load_start = LOAD_START[x][y][l]; | 
|---|
 | 349 |                 if (LOAD_START[x][y][l] > max_load_start)  max_load_start = LOAD_START[x][y][l]; | 
|---|
 | 350 |                 if (LOAD_END[x][y][l]   < min_load_ended)  min_load_ended = LOAD_END[x][y][l];  | 
|---|
 | 351 |                 if (LOAD_END[x][y][l]   > max_load_ended)  max_load_ended = LOAD_END[x][y][l]; | 
|---|
 | 352 |                 if (TRSP_START[x][y][l] < min_trsp_start)  min_trsp_start = TRSP_START[x][y][l]; | 
|---|
 | 353 |                 if (TRSP_START[x][y][l] > max_trsp_start)  max_trsp_start = TRSP_START[x][y][l]; | 
|---|
 | 354 |                 if (TRSP_END[x][y][l]   < min_trsp_ended)  min_trsp_ended = TRSP_END[x][y][l]; | 
|---|
 | 355 |                 if (TRSP_END[x][y][l]   > max_trsp_ended)  max_trsp_ended = TRSP_END[x][y][l]; | 
|---|
 | 356 |                 if (DISP_START[x][y][l] < min_disp_start)  min_disp_start = DISP_START[x][y][l]; | 
|---|
 | 357 |                 if (DISP_START[x][y][l] > max_disp_start)  max_disp_start = DISP_START[x][y][l]; | 
|---|
 | 358 |                 if (DISP_END[x][y][l]   < min_disp_ended)  min_disp_ended = DISP_END[x][y][l]; | 
|---|
 | 359 |                 if (DISP_END[x][y][l]   > max_disp_ended)  max_disp_ended = DISP_END[x][y][l]; | 
|---|
 | 360 |                 if (STOR_START[x][y][l] < min_stor_start)  min_stor_start = STOR_START[x][y][l]; | 
|---|
 | 361 |                 if (STOR_START[x][y][l] > max_stor_start)  max_stor_start = STOR_START[x][y][l]; | 
|---|
 | 362 |                 if (STOR_END[x][y][l]   < min_stor_ended)  min_stor_ended = STOR_END[x][y][l]; | 
|---|
 | 363 |                 if (STOR_END[x][y][l]   > max_stor_ended)  max_stor_ended = STOR_END[x][y][l]; | 
|---|
 | 364 |             } | 
|---|
 | 365 |         } | 
|---|
 | 366 |     } | 
|---|
 | 367 |  | 
|---|
 | 368 |     printf("\n   ---------------- Instrumentation Results ---------------------\n"); | 
|---|
 | 369 |  | 
|---|
 | 370 |     printf(" - LOAD_START : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 371 |            min_load_start, max_load_start, (min_load_start+max_load_start)/2,  | 
|---|
 | 372 |            max_load_start-min_load_start);  | 
|---|
 | 373 |  | 
|---|
 | 374 |     printf(" - LOAD_END   : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 375 |            min_load_ended, max_load_ended, (min_load_ended+max_load_ended)/2,  | 
|---|
 | 376 |            max_load_ended-min_load_ended);  | 
|---|
 | 377 |  | 
|---|
 | 378 |     printf(" - TRSP_START : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 379 |            min_trsp_start, max_trsp_start, (min_trsp_start+max_trsp_start)/2,  | 
|---|
 | 380 |            max_trsp_start-min_trsp_start);  | 
|---|
 | 381 |  | 
|---|
 | 382 |     printf(" - TRSP_END   : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 383 |            min_trsp_ended, max_trsp_ended, (min_trsp_ended+max_trsp_ended)/2,  | 
|---|
 | 384 |            max_trsp_ended-min_trsp_ended);  | 
|---|
 | 385 |  | 
|---|
 | 386 |     printf(" - DISP_START : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 387 |            min_disp_start, max_disp_start, (min_disp_start+max_disp_start)/2,  | 
|---|
 | 388 |            max_disp_start-min_disp_start);  | 
|---|
 | 389 |  | 
|---|
 | 390 |     printf(" - DISP_END   : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 391 |            min_disp_ended, max_disp_ended, (min_disp_ended+max_disp_ended)/2,  | 
|---|
 | 392 |            max_disp_ended-min_disp_ended);  | 
|---|
 | 393 |  | 
|---|
 | 394 |     printf(" - STOR_START : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 395 |            min_stor_start, max_stor_start, (min_stor_start+max_stor_start)/2,  | 
|---|
 | 396 |            max_stor_start-min_stor_start);  | 
|---|
 | 397 |  | 
|---|
 | 398 |     printf(" - STOR_END   : min = %d / max = %d / med = %d / delta = %d\n", | 
|---|
 | 399 |            min_stor_ended, max_stor_ended, (min_stor_ended+max_stor_ended)/2,  | 
|---|
 | 400 |            max_stor_ended-min_stor_ended);  | 
|---|
 | 401 |  | 
|---|
 | 402 | }  // end instrument() | 
|---|
 | 403 |  | 
|---|
 | 404 |  | 
|---|
 | 405 |  | 
|---|
 | 406 | ////////////////////////////////////////// | 
|---|
 | 407 | __attribute__ ((constructor)) void main() | 
|---|
 | 408 | ////////////////////////////////////////// | 
|---|
 | 409 | { | 
|---|
 | 410 |     // indexes for loops | 
|---|
 | 411 |     unsigned int x , y , n; | 
|---|
 | 412 |  | 
|---|
 | 413 |     // get identifiers for proc executing main | 
|---|
 | 414 |     unsigned int x_id;                          // x cluster coordinate | 
|---|
 | 415 |     unsigned int y_id;                          // y cluster coordinate | 
|---|
 | 416 |     unsigned int p_id;                          // local processor index | 
|---|
 | 417 |  | 
|---|
 | 418 |     giet_proc_xyp( &x_id , &y_id , &p_id ); | 
|---|
 | 419 |  | 
|---|
 | 420 |     // get & check plat-form parameters | 
|---|
 | 421 |     unsigned int x_size;                       // number of clusters in a row | 
|---|
 | 422 |     unsigned int y_size;                       // number of clusters in a column | 
|---|
 | 423 |     unsigned int nprocs;                       // number of processors per cluster | 
|---|
 | 424 |  | 
|---|
 | 425 |     giet_procs_number( &x_size , &y_size , &nprocs ); | 
|---|
 | 426 |  | 
|---|
 | 427 |     giet_pthread_assert( ((nprocs == 1) || (nprocs == 2) || (nprocs == 4)), | 
|---|
 | 428 |                          "[TRANSPOSE ERROR] number of procs per cluster must be 1, 2 or 4"); | 
|---|
 | 429 |  | 
|---|
 | 430 |     giet_pthread_assert( ((x_size == 1) || (x_size == 2) || (x_size == 4) ||  | 
|---|
 | 431 |                   (x_size == 8) || (x_size == 16)), | 
|---|
 | 432 |                          "[TRANSPOSE ERROR] x_size must be 1,2,4,8,16"); | 
|---|
 | 433 |  | 
|---|
 | 434 |     giet_pthread_assert( ((y_size == 1) || (y_size == 2) || (y_size == 4) ||  | 
|---|
 | 435 |                   (y_size == 8) || (y_size == 16)), | 
|---|
 | 436 |                          "[TRANSPOSE ERROR] y_size must be 1,2,4,8,16"); | 
|---|
 | 437 |  | 
|---|
 | 438 |     giet_pthread_assert( (nprocs * x_size * y_size <= IMAGE_SIZE ), | 
|---|
 | 439 |                          "[TRANSPOSE ERROR] number of threads larger than number of lines"); | 
|---|
 | 440 |  | 
|---|
 | 441 |     unsigned int nthreads = x_size * y_size * nprocs; | 
|---|
 | 442 |  | 
|---|
 | 443 |     // shared TTY allocation | 
|---|
 | 444 |     giet_tty_alloc( 1 );      | 
|---|
 | 445 |     lock_init( &tty_lock); | 
|---|
 | 446 |  | 
|---|
 | 447 |     printf("\n[TRANSPOSE] start at cycle %d on %d cores\n", giet_proctime(), nthreads ); | 
|---|
 | 448 |  | 
|---|
 | 449 |     // distributed heap initialisation | 
|---|
 | 450 |     for ( x = 0 ; x < x_size ; x++ )  | 
|---|
 | 451 |     { | 
|---|
 | 452 |         for ( y = 0 ; y < y_size ; y++ )  | 
|---|
 | 453 |         { | 
|---|
 | 454 |             heap_init( x , y ); | 
|---|
 | 455 |         } | 
|---|
 | 456 |     } | 
|---|
 | 457 |  | 
|---|
 | 458 |     // allocate thread[] array | 
|---|
 | 459 |     pthread_t* thread = malloc( nthreads * sizeof(pthread_t) ); | 
|---|
 | 460 |  | 
|---|
 | 461 |     // barrier initialisation | 
|---|
 | 462 |     sqt_barrier_init( &barrier, x_size , y_size , nprocs ); | 
|---|
 | 463 |  | 
|---|
 | 464 |     // Initialisation completed | 
|---|
 | 465 |     printf("\n[TRANSPOSE] initialisation completed at cycle %d\n", giet_proctime() ); | 
|---|
 | 466 |      | 
|---|
 | 467 |     // launch other threads to run execute() function | 
|---|
 | 468 |     for ( n = 1 ; n < nthreads ; n++ ) | 
|---|
 | 469 |     { | 
|---|
 | 470 |         if ( giet_pthread_create( &thread[n], | 
|---|
 | 471 |                                   NULL,                  // no attribute | 
|---|
 | 472 |                                   &execute, | 
|---|
 | 473 |                                   NULL ) )               // no argument | 
|---|
 | 474 |         { | 
|---|
 | 475 |             printf("\n[TRANSPOSE ERROR] creating thread %x\n", thread[n] ); | 
|---|
 | 476 |             giet_pthread_exit( NULL ); | 
|---|
 | 477 |         } | 
|---|
 | 478 |     } | 
|---|
 | 479 |  | 
|---|
 | 480 |     // run the execute() function | 
|---|
 | 481 |     execute(); | 
|---|
 | 482 |  | 
|---|
 | 483 |     // wait other threads completion | 
|---|
 | 484 |     for ( n = 1 ; n < nthreads ; n++ ) | 
|---|
 | 485 |     { | 
|---|
 | 486 |         if ( giet_pthread_join( thread[n], NULL ) ) | 
|---|
 | 487 |         { | 
|---|
 | 488 |             printf("\n[TRANSPOSE ERROR] joining thread %x\n", thread[n] ); | 
|---|
 | 489 |             giet_pthread_exit( NULL ); | 
|---|
 | 490 |         } | 
|---|
 | 491 |         else | 
|---|
 | 492 |         { | 
|---|
 | 493 |             printf("\n[TRANSPOSE] thread %x joined at cycle %d\n", | 
|---|
 | 494 |                    thread[n] , giet_proctime() ); | 
|---|
 | 495 |         } | 
|---|
 | 496 |     } | 
|---|
 | 497 |  | 
|---|
 | 498 |     // call the instrument() function | 
|---|
 | 499 |     instrument( x_size , y_size , nprocs ); | 
|---|
 | 500 |  | 
|---|
 | 501 |     giet_pthread_exit( "completed" ); | 
|---|
 | 502 |      | 
|---|
 | 503 | } // end main() | 
|---|
 | 504 |  | 
|---|