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

Last change on this file since 391 was 383, checked in by alain, 10 years ago

Update the transpose application to use the new malloc.h and barrier.h libraries.

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