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

Last change on this file since 373 was 355, checked in by alain, 10 years ago

Cosmetic: remove GCC warnings.

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