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

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

Introducing application "display"

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