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

Last change on this file since 408 was 398, checked in by alain, 10 years ago

Releases dynamically allocated buffers at the end of the transpose application.

File size: 15.8 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).
[393]16// The actual display on the frame buffer depends on frame buffer availability.
[295]17///////////////////////////////////////////////////////////////////////////////////////////////
18
19#include "hard_config.h"
20#include "stdio.h"
21#include "barrier.h"
[383]22#include "malloc.h"
[295]23
24#define NN                  128                 // image size : nlines = npixels = 128
[398]25#define NB_IMAGES           2                   // number of images to be handled
[295]26#define FILE_PATHNAME       "misc/images.raw"   // file pathname on disk
[383]27#define NB_CLUSTERS         (X_SIZE * Y_SIZE)   // number of clusters
[393]28#define INSTRUMENTATION_OK  0                   // display statistics on TTY when non zero
[295]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)
[383]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];
[295]43
44// arrays of pointers on distributed buffers
45// one input buffer & one output buffer per cluster
[383]46unsigned char*  buf_in [NB_CLUSTERS];
47unsigned char*  buf_out[NB_CLUSTERS];
[295]48
49// checksum variables
50unsigned check_line_before[NN];
51unsigned check_line_after[NN];
52
[383]53// global synchronisation barrier
54giet_barrier_t barrier;
[295]55
56volatile unsigned int init_ok = 1;
57
58//////////////////////////////////////////
59__attribute__ ((constructor)) void main()
[383]60//////////////////////////////////////////
[295]61{
62
[355]63    int          file = 0;                                         // file descriptor
[307]64    unsigned int l;                                                // line index for loops
65    unsigned int p;                                                // pixel index for loops
[393]66    unsigned int c;                                                // cluster index for loops
[295]67
[336]68    unsigned int proc_id    = giet_procid();                       // global processor id
69    unsigned int lpid       = proc_id % NB_PROCS_MAX;              // local processor id
[393]70    unsigned int cluster_xy = proc_id / NB_PROCS_MAX;              // 8 bits format
[336]71    unsigned int x          = cluster_xy >> Y_WIDTH;               // x coordinate
72    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);       // y coordinate
[295]73
[336]74    unsigned int npixels    = NN * NN;                             // pixels per image
75    unsigned int nblocks    = npixels / 512;                       // blocks per image
76    unsigned int image      = 0;                                   // image counter
[295]77
[393]78    unsigned int cluster_id = (x * Y_SIZE) + y;                    // "continuous" index   
79    unsigned int ntasks     = NB_CLUSTERS * NB_PROCS_MAX;          // number of tasks
[336]80    unsigned int task_id    = (cluster_id * NB_PROCS_MAX) + lpid;  // "continuous" task index
[307]81
[398]82    // Processor [0,0,0] makes initialisation
[393]83    // It includes parameters checking, barriers initialization,
84    // distributed buffers allocation, and file open
[295]85    if ( proc_id == 0 )
86    {
[393]87        // Parameters checking
[295]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        }
[393]92        if ((NB_CLUSTERS != 1) && (NB_CLUSTERS != 2) && (NB_CLUSTERS != 4) && 
93            (NB_CLUSTERS != 8) && (NB_CLUSTERS != 16) && (NB_CLUSTERS != 32) )
[295]94        {
[393]95            giet_exit("[TRANSPOSE ERROR] number of clusters must be 1,2,4,8,16,32");
[295]96        }
97        if ( ntasks > NN )
98        {
99            giet_exit("[TRANSPOSE ERROR] number of tasks larger than number of lines");
100        }
101
[393]102        giet_shr_printf("\n[TRANSPOSE] Processor[0,0,0] starts at cycle %d\n"
103                        " - x_size    = %d\n"
104                        " - y_size    = %d\n"
105                        " - nprocs    = %d\n"
106                        " - nclusters = %d\n"
107                        " - ntasks    = %d\n",
108                        giet_proctime(), X_SIZE, Y_SIZE, NB_PROCS_MAX, NB_CLUSTERS, ntasks );
109
110        // Barrier initialisation
[383]111        barrier_init( &barrier, ntasks );
[295]112
[393]113        giet_shr_printf("\n[TRANSPOSE] Proc [0,0,0] completes barrier init at cycle %d\n",
114                        giet_proctime() );
[336]115
[393]116        // Distributed buffers allocation
117        // The buffers containing one image are distributed in clusters
118        // (one buf_in and one buf_out per cluster).
119        // Each buffer contains (NN*NN / NB_CLUSTERS) bytes.
120        for ( c = 0 ; c < NB_CLUSTERS ; c++ )
121        {
122            unsigned int rx = c / Y_SIZE;
123            unsigned int ry = c % Y_SIZE;
[307]124
[393]125            buf_in[c]  = remote_malloc( npixels/NB_CLUSTERS, rx, ry );
126            buf_out[c] = remote_malloc( npixels/NB_CLUSTERS, rx, ry );
[295]127
[393]128            giet_shr_printf("\n[TRANSPOSE] Proc [0,0,0] completes buffer allocation"
129                            " for cluster[%d,%d] at cycle %d\n"
130                            " - buf_in  = %x\n"
131                            " - buf_out = %x\n",
132                            rx, ry, giet_proctime(), 
133                            (unsigned int)buf_in[c], 
134                            (unsigned int)buf_out[c] );
135        }
[295]136
137        // open file containing images
138        file = giet_fat_open( "misc/images.raw", 0);
139
[307]140        if (file < 0)
141        { 
[393]142            giet_shr_printf("\n[TRANSPOSE ERROR] Processor[%d,%d,%d]"
[307]143                            " cannot open file misc/images.raw",
144                            x, y, lpid );
145            giet_exit(" open() failure");
146        }
[317]147        else
148        {
[393]149            giet_shr_printf("\n[TRANSPOSE] Processor[0,0,0] open file misc/images.raw\n");
[317]150        }
[393]151        init_ok = 0;
[295]152    }
[393]153    else   // others processors wait initialisation completion
154    {
155        while ( init_ok == 1 );
156    }
157   
[295]158
[383]159    /////////////////////////
[295]160    // Main loop (on images)
161    while (image < NB_IMAGES)
162    {
[393]163        // pseudo parallel load from disk to buf_in buffer : nblocks/NB_CLUSTERS blocks
[295]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],
[393]172                           (nblocks / NB_CLUSTERS),
173                           ((image*nblocks) + ((nblocks*cluster_id)/NB_CLUSTERS)) );
[295]174
[317]175            giet_shr_printf("\n[TRANSPOSE] Proc [%d,%d,0] completes load"
176                            "  for image %d at cycle %d\n",
[295]177                            x, y, image, giet_proctime() );
178        }
179
180        LOAD_END[cluster_id][lpid] = giet_proctime();
181
[383]182        /////////////////////////
183        barrier_wait( &barrier );
[295]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
[393]194        unsigned int nlc   = NN / NB_CLUSTERS;   // number of lines per cluster
[295]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
[307]228        if ( lpid == 0 )
229        {
[317]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() );
[295]233
[307]234        }
[295]235        TRSP_END[cluster_id][lpid] = giet_proctime();
236
[383]237        /////////////////////////
238        barrier_wait( &barrier );
[295]239
240        // optional parallel display from local buf_out to frame buffer
241        // all processors contribute to display using memcpy...
242
[307]243        if ( USE_FBF )  // external frame buffer available
[295]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
[307]253            if ( lpid == 0 )
254            {
[317]255                giet_shr_printf("\n[TRANSPOSE] Proc [%d,%d,0] completes display"
256                                " for image %d at cycle %d\n",
[307]257                                x, y, image, giet_proctime() );
258            }
[295]259
260            DISP_END[cluster_id][lpid] = giet_proctime();
261
[383]262            /////////////////////////
263            barrier_wait( &barrier );
[295]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            {
[317]294                giet_shr_printf("\n[TRANSPOSE] proc [%d,%d,0] checksum OK"
[336]295                                " for image %d at cycle %d\n",
296                                x, y, image, giet_proctime() );
[295]297            }
298            else
299            {
[317]300                giet_shr_printf("\n[TRANSPOSE] proc [%d,%d,0] checksum KO"
[336]301                                " for image %d at cycle %d\n",
302                                x, y, image, giet_proctime() );
[295]303            }
304        }
305
[383]306        /////////////////////////
307        barrier_wait( &barrier );
[336]308
[295]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
[393]327            for (cc = 0; cc < NB_CLUSTERS; cc++)
[295]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
[393]373        /////////////////////////
[383]374        barrier_wait( &barrier );
[295]375
376    } // end while image     
377
[398]378    // Processor[0,0,0] releases the Distributed buffers
379    if ( proc_id == 0 )
380    {
381        for ( c = 0 ; c < NB_CLUSTERS ; c++ )
382        {
383            free( buf_in[c] );
384            free( buf_in[c] );
385        }
386    }
387
[295]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.