source: soft/giet_vm/applications/transpose/transpose.c @ 772

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