source: soft/giet_vm/transpose/main.c @ 313

Last change on this file since 313 was 307, checked in by alain, 11 years ago

Reducing the number of log messages to be compatible with 64 processors architectures.

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