source: soft/giet_vm/applications/transpose/main.c @ 542

Last change on this file since 542 was 515, checked in by alain, 10 years ago

Cosmetic.

File size: 16.0 KB
RevLine 
[502]1///////////////////////////////////////////////////////////////////////////////////////
[295]2// File   : main.c   (for transpose application)
3// Date   : february 2014
4// author : Alain Greiner
[502]5///////////////////////////////////////////////////////////////////////////////////////
6// This multi-threaded application makes a transpose for a NN*NN pixels
7// sequence of images.
[444]8// It can run on a multi-processors, multi-clusters architecture, with one thread
[502]9// per processor.
10//
[295]11// The image sequence is read from a file (one byte per pixel).
12// The input and output buffers containing the image are distributed in all clusters.
13//
[502]14// - The image size NN must fit the frame buffer size: 128 bytes
15// - The block size in block device must be 512 bytes.
16// - The number of clusters  must be a power of 2 no larger than 32
17// - The number of processors per cluster must be a power of 2 no larger than 4
[295]18//
19// For each image the application makes a self test (checksum for each line).
[393]20// The actual display on the frame buffer depends on frame buffer availability.
[502]21///////////////////////////////////////////////////////////////////////////////////////
[295]22
23#include "stdio.h"
[502]24#include "user_barrier.h"
[383]25#include "malloc.h"
[295]26
[502]27#define BLOCK_SIZE          512                 // block size on disk
28#define CLUSTERS_MAX        32                  // max number of clusters
29#define PROCS_MAX           4                   // max number of processors per cluster
[295]30#define NN                  128                 // image size : nlines = npixels = 128
[444]31#define NB_IMAGES           5                   // number of images to be handled
[295]32#define FILE_PATHNAME       "misc/images.raw"   // file pathname on disk
[393]33#define INSTRUMENTATION_OK  0                   // display statistics on TTY when non zero
[295]34
35///////////////////////////////////////////////////////
36// global variables stored in seg_data in cluster(0,0)
37///////////////////////////////////////////////////////
38
[502]39// instrumentation counters for each processor in each cluster
40unsigned int LOAD_START[CLUSTERS_MAX][PROCS_MAX];
41unsigned int LOAD_END  [CLUSTERS_MAX][PROCS_MAX];
42unsigned int TRSP_START[CLUSTERS_MAX][PROCS_MAX];
43unsigned int TRSP_END  [CLUSTERS_MAX][PROCS_MAX];
44unsigned int DISP_START[CLUSTERS_MAX][PROCS_MAX];
45unsigned int DISP_END  [CLUSTERS_MAX][PROCS_MAX];
[295]46
47// arrays of pointers on distributed buffers
48// one input buffer & one output buffer per cluster
[502]49unsigned char*  buf_in [CLUSTERS_MAX];
50unsigned char*  buf_out[CLUSTERS_MAX];
[295]51
52// checksum variables
53unsigned check_line_before[NN];
54unsigned check_line_after[NN];
55
[383]56// global synchronisation barrier
[502]57giet_sqt_barrier_t barrier;
[295]58
[444]59volatile unsigned int init_ok = 0;
[295]60
61//////////////////////////////////////////
62__attribute__ ((constructor)) void main()
[383]63//////////////////////////////////////////
[295]64{
65
[502]66    unsigned int l;                  // line index for loops
67    unsigned int p;                  // pixel index for loops
68    unsigned int c;                  // cluster index for loops
[295]69
[502]70    // processor identifiers
71    unsigned int x;                  // x cluster coordinate
72    unsigned int y;                  // y cluster coordinate
73    unsigned int lpid;               // local processor index
74
75    // plat-form parameters
76    unsigned int x_size;             // number of clusters in a row
77    unsigned int y_size;             // number of clusters in a column
78    unsigned int nprocs;             // number of processors per cluster
79   
[432]80    giet_proc_xyp( &x, &y, &lpid);             
[295]81
[502]82    giet_procs_number( &x_size , &y_size , &nprocs );
[295]83
[502]84    unsigned int nclusters  = x_size * y_size;               // number of clusters
85    unsigned int ntasks     = x_size * y_size * nprocs;      // number of tasks
86    unsigned int npixels    = NN * NN;                       // pixels per image
87    unsigned int nblocks    = npixels / BLOCK_SIZE;          // blocks per image
88    unsigned int image      = 0;                             // image counter
89    int          file       = 0;                             // file descriptor
90    unsigned int cluster_id = (x * y_size) + y;              // "continuous" index   
91    unsigned int task_id    = (cluster_id * nprocs) + lpid;  // "continuous" task index
92
[398]93    // Processor [0,0,0] makes initialisation
[502]94    // It includes parameters checking, barrier initialization,
[393]95    // distributed buffers allocation, and file open
[432]96    if ( (x==0) && (y==0) && (lpid==0) )
[295]97    {
[502]98        if ((nprocs != 1) && (nprocs != 2) && (nprocs != 4))
[295]99        { 
[502]100            giet_exit("[TRANSPOSE ERROR] number of procs per cluster must be 1, 2 or 4");
[295]101        }
[502]102        if ((nclusters != 1) && (nclusters != 2) && (nclusters != 4) && 
103            (nclusters != 8) && (nclusters != 16) && (nclusters != 32) )
[295]104        {
[393]105            giet_exit("[TRANSPOSE ERROR] number of clusters must be 1,2,4,8,16,32");
[295]106        }
107        if ( ntasks > NN )
108        {
109            giet_exit("[TRANSPOSE ERROR] number of tasks larger than number of lines");
110        }
111
[393]112        // Barrier initialisation
[502]113        sqt_barrier_init( &barrier, x_size , y_size , nprocs );
[295]114
[393]115        giet_shr_printf("\n[TRANSPOSE] Proc [0,0,0] completes barrier init at cycle %d\n",
116                        giet_proctime() );
[336]117
[393]118        // Distributed buffers allocation
[502]119        // The buffers containing one image are distributed in the user
120        // heap (one buf_in and one buf_out per cluster).
121        // Each buffer contains (NN*NN / nclusters) bytes.
122        for ( c = 0 ; c < nclusters ; c++ )
[393]123        {
[502]124            unsigned int rx = c / y_size;
125            unsigned int ry = c % y_size;
[307]126
[502]127            buf_in[c]  = remote_malloc( npixels/nclusters, rx, ry );
128            buf_out[c] = remote_malloc( npixels/nclusters, rx, ry );
[295]129
[393]130            giet_shr_printf("\n[TRANSPOSE] Proc [0,0,0] completes buffer allocation"
131                            " for cluster[%d,%d] at cycle %d\n"
132                            " - buf_in  = %x\n"
133                            " - buf_out = %x\n",
134                            rx, ry, giet_proctime(), 
135                            (unsigned int)buf_in[c], 
136                            (unsigned int)buf_out[c] );
137        }
[295]138
139        // open file containing images
140        file = giet_fat_open( "misc/images.raw", 0);
141
[307]142        if (file < 0)
143        { 
[432]144            giet_shr_printf("\n[TRANSPOSE ERROR] Proc [%d,%d,%d]"
[307]145                            " cannot open file misc/images.raw",
146                            x, y, lpid );
147            giet_exit(" open() failure");
148        }
[317]149        else
150        {
[432]151            giet_shr_printf("\n[TRANSPOSE] Proc [0,0,0] open file misc/images.raw\n");
[317]152        }
[444]153        init_ok = 1;
[295]154    }
[393]155    else   // others processors wait initialisation completion
156    {
[444]157        while ( init_ok == 0 );
[393]158    }
159   
[383]160    /////////////////////////
[295]161    // Main loop (on images)
162    while (image < NB_IMAGES)
163    {
[502]164        // pseudo parallel load from disk to buf_in buffer : nblocks/nclusters blocks
[295]165        // only task running on processor with (lpid == 0) does it
166
167        LOAD_START[cluster_id][lpid] = giet_proctime();
168
169        if (lpid == 0)
170        {
171            giet_fat_read( file,
172                           buf_in[cluster_id],
[502]173                           (nblocks / nclusters),
174                           ((image*nblocks) + ((nblocks*cluster_id)/nclusters)) );
[295]175
[502]176            if ( (x==0) && (y==0) )
[432]177            giet_shr_printf("\n[TRANSPOSE] Proc [%d,%d,%d] completes load"
[317]178                            "  for image %d at cycle %d\n",
[432]179                            x, y, lpid, image, giet_proctime() );
[295]180        }
181
182        LOAD_END[cluster_id][lpid] = giet_proctime();
183
[502]184        /////////////////////////////
185        sqt_barrier_wait( &barrier );
[295]186
187        // parallel transpose from buf_in to buf_out
188        // each task makes the transposition for nlt lines (nlt = NN/ntasks)
189        // from line [task_id*nlt] to line [(task_id + 1)*nlt - 1]
190        // (p,l) are the absolute pixel coordinates in the source image
191
192
193        TRSP_START[cluster_id][lpid] = giet_proctime();
194
195        unsigned int nlt   = NN / ntasks;      // number of lines per task
[502]196        unsigned int nlc   = NN / nclusters;   // number of lines per cluster
[295]197
198        unsigned int src_cluster;
199        unsigned int src_index;
200        unsigned int dst_cluster;
201        unsigned int dst_index;
202
203        unsigned char byte;
204
205        unsigned int first = task_id * nlt;    // first line index for a given task
206        unsigned int last  = first + nlt;      // last line index for a given task
207
208        for ( l = first ; l < last ; l++ )
209        {
210            check_line_before[l] = 0;
211         
212            // in each iteration we transfer one byte
213            for ( p = 0 ; p < NN ; p++ )
214            {
215                // read one byte from local buf_in
216                src_cluster = l / nlc;
217                src_index   = (l % nlc)*NN + p;
218                byte        = buf_in[src_cluster][src_index];
219
220                // compute checksum
221                check_line_before[l] = check_line_before[l] + byte;
222
223                // write one byte to remote buf_out
224                dst_cluster = p / nlc; 
225                dst_index   = (p % nlc)*NN + l;
226                buf_out[dst_cluster][dst_index] = byte;
227            }
228        }
229
[307]230        if ( lpid == 0 )
231        {
[502]232            if ( (x==0) && (y==0) )
[317]233            giet_shr_printf("\n[TRANSPOSE] proc [%d,%d,0] completes transpose"
234                            " for image %d at cycle %d\n", 
235                            x, y, image, giet_proctime() );
[295]236
[307]237        }
[295]238        TRSP_END[cluster_id][lpid] = giet_proctime();
239
[502]240        /////////////////////////////
241        sqt_barrier_wait( &barrier );
[295]242
243
[307]244        if ( USE_FBF )  // external frame buffer available
[295]245        {
[515]246            // parallel display from local buf_out to frame buffer
247            // all processors contribute to display using memcpy...
248
[295]249            DISP_START[cluster_id][lpid] = giet_proctime();
250
251            unsigned int  npt   = npixels / ntasks;   // number of pixels per task
252
[444]253            giet_fbf_sync_write( npt * task_id, 
254                                 &buf_out[cluster_id][lpid*npt], 
255                                 npt );
[295]256
[502]257            if ( (x==0) && (y==0) && (lpid==0) )
258            giet_shr_printf("\n[TRANSPOSE] Proc [%d,%d,%d] completes display"
259                            " for image %d at cycle %d\n",
260                            x, y, lpid, image, giet_proctime() );
[295]261
262            DISP_END[cluster_id][lpid] = giet_proctime();
263
[502]264            /////////////////////////////
265            sqt_barrier_wait( &barrier );
[295]266        }
[515]267        else         // checksum by processor(x,y,0) in each cluster
[295]268        {
[515]269            if ( lpid == 0 )
[295]270            {
[515]271                unsigned int success = 1;
272                unsigned int start   = cluster_id * nlc;
273                unsigned int stop    = start + nlc;
[295]274
[515]275                for ( l = start ; l < stop ; l++ )
[295]276                {
[515]277                    check_line_after[l] = 0;
[295]278
[515]279                    for ( p = 0 ; p < NN ; p++ )
280                    {
281                        // read one byte in remote buffer
282                        src_cluster = p / nlc;
283                        src_index   = (p % nlc)*NN + l;
[295]284
[515]285                        unsigned char byte = buf_out[src_cluster][src_index];
286
287                        check_line_after[l] = check_line_after[l] + byte;
288                    }
289
290                    if ( check_line_before[l] != check_line_after[l] ) success = 0;
[295]291                }
292
[515]293                if ( success ) 
294                {
295                    giet_shr_printf("\n[TRANSPOSE] proc [%d,%d,0] checksum OK"
296                                    " for image %d at cycle %d\n",
297                                    x, y, image, giet_proctime() );
298                }
299                else
300                {
301                    giet_shr_printf("\n[TRANSPOSE] proc [%d,%d,0] checksum KO"
302                                    " for image %d at cycle %d\n",
303                                    x, y, image, giet_proctime() );
304                }
305            } 
[295]306        }
307
[502]308        /////////////////////////////
309        sqt_barrier_wait( &barrier );
[336]310
[432]311        // instrumentation done by processor [0,0,0]
312        if ( (x==0) && (y==0) && (lpid==0) && INSTRUMENTATION_OK )
[295]313        {
314            int cc, pp;
315            unsigned int min_load_start = 0xFFFFFFFF;
316            unsigned int max_load_start = 0;
317            unsigned int min_load_ended = 0xFFFFFFFF;
318            unsigned int max_load_ended = 0;
319            unsigned int min_trsp_start = 0xFFFFFFFF;
320            unsigned int max_trsp_start = 0;
321            unsigned int min_trsp_ended = 0xFFFFFFFF;
322            unsigned int max_trsp_ended = 0;
323            unsigned int min_disp_start = 0xFFFFFFFF;
324            unsigned int max_disp_start = 0;
325            unsigned int min_disp_ended = 0xFFFFFFFF;
326            unsigned int max_disp_ended = 0;
327
[502]328            for (cc = 0; cc < nclusters; cc++)
[295]329            {
330                for (pp = 0; pp < NB_PROCS_MAX; pp++)
331                {
332                    if (LOAD_START[cc][pp] < min_load_start)  min_load_start = LOAD_START[cc][pp];
333                    if (LOAD_START[cc][pp] > max_load_start)  max_load_start = LOAD_START[cc][pp];
334                    if (LOAD_END[cc][pp]   < min_load_ended)  min_load_ended = LOAD_END[cc][pp]; 
335                    if (LOAD_END[cc][pp]   > max_load_ended)  max_load_ended = LOAD_END[cc][pp];
336                    if (TRSP_START[cc][pp] < min_trsp_start)  min_trsp_start = TRSP_START[cc][pp];
337                    if (TRSP_START[cc][pp] > max_trsp_start)  max_trsp_start = TRSP_START[cc][pp];
338                    if (TRSP_END[cc][pp]   < min_trsp_ended)  min_trsp_ended = TRSP_END[cc][pp];
339                    if (TRSP_END[cc][pp]   > max_trsp_ended)  max_trsp_ended = TRSP_END[cc][pp];
340                    if (DISP_START[cc][pp] < min_disp_start)  min_disp_start = DISP_START[cc][pp];
341                    if (DISP_START[cc][pp] > max_disp_start)  max_disp_start = DISP_START[cc][pp];
342                    if (DISP_END[cc][pp]   < min_disp_ended)  min_disp_ended = DISP_END[cc][pp];
343                    if (DISP_END[cc][pp]   > max_disp_ended)  max_disp_ended = DISP_END[cc][pp];
344                }
345            }
346
347            giet_shr_printf(" - LOAD_START : min = %d / max = %d / med = %d / delta = %d\n",
348                            min_load_start, max_load_start, (min_load_start+max_load_start)/2, 
349                            max_load_start-min_load_start); 
350
351            giet_shr_printf(" - LOAD_END   : min = %d / max = %d / med = %d / delta = %d\n",
352                            min_load_ended, max_load_ended, (min_load_ended+max_load_ended)/2, 
353                            max_load_ended-min_load_ended); 
354
355            giet_shr_printf(" - TRSP_START : min = %d / max = %d / med = %d / delta = %d\n",
356                            min_trsp_start, max_trsp_start, (min_trsp_start+max_trsp_start)/2, 
357                            max_trsp_start-min_trsp_start); 
358
359            giet_shr_printf(" - TRSP_END   : min = %d / max = %d / med = %d / delta = %d\n",
360                            min_trsp_ended, max_trsp_ended, (min_trsp_ended+max_trsp_ended)/2, 
361                            max_trsp_ended-min_trsp_ended); 
362
363            giet_shr_printf(" - DISP_START : min = %d / max = %d / med = %d / delta = %d\n",
364                            min_disp_start, max_disp_start, (min_disp_start+max_disp_start)/2, 
365                            max_disp_start-min_disp_start); 
366
367            giet_shr_printf(" - DISP_END   : min = %d / max = %d / med = %d / delta = %d\n",
368                            min_disp_ended, max_disp_ended, (min_disp_ended+max_disp_ended)/2, 
369                            max_disp_ended-min_disp_ended); 
370        }
371
372        image++;
373
[502]374        /////////////////////////////
375        sqt_barrier_wait( &barrier );
[295]376
377    } // end while image     
378
[398]379    // Processor[0,0,0] releases the Distributed buffers
[432]380    if ( (x==0) && (y==0) && (lpid==0) )
[398]381    {
[502]382        for ( c = 0 ; c < nclusters ; c++ )
[398]383        {
384            free( buf_in[c] );
385            free( buf_in[c] );
386        }
387    }
388
[295]389    giet_exit("Completed");
390
391} // end main()
392
393// Local Variables:
394// tab-width: 3
395// c-basic-offset:
396// c-file-offsets:((innamespace . 0)(inline-open . 0))
397// indent-tabs-mode: nil
398// End:
399
400// vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3
401
402
403
Note: See TracBrowser for help on using the repository browser.