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

Last change on this file since 504 was 502, checked in by alain, 9 years ago

1) Introduce distributed barriers in the multi-threads applications
(classif) transpose, convol, sort, gameoflife)

2) Introducing support for architectures containing empty clusters
in the mapping of these multi-threaded applications.

3) Removing the "command line arguments" in the sort application
(replaced by the giet_procs_number() system call.

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