source: soft/giet_vm/applications/convol/convol.c @ 712

Last change on this file since 712 was 708, checked in by alain, 9 years ago

Adapt the following application to the POSIX threads API

  • convol
  • classif
  • raycast
  • coproc
  • display
  • gameoflife
  • transpose
  • shell
File size: 27.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2// File   : convol.c 
3// Date   : june 2014
4// author : Alain Greiner
5///////////////////////////////////////////////////////////////////////////////////////
6// This multi-threaded application implements a 2D convolution product. 
7// It can run on a multi-processors, multi-clusters architecture, with one thread
8// per processor, and uses the POSIX threads API.
9//
10// The main() function can be launched on any processor P[x,y,l].
11// It makes the initialisations, launch (N-1) threads to run the execute() function
12// on the (N-1) other processors than P[x,y,l], call himself the execute() function,
13// and finally call the instrument() function to display instrumentation results
14// when the parallel execution is completed.
15//
16// The convolution kernel is [201]*[35] pixels, but it can be factored in two
17// independant line and column convolution products.
18// The five buffers containing the image are distributed in clusters.
19//
20// The (1024 * 1024) pixels image is read from a file (2 bytes per pixel).
21//
22// - number of clusters containing processors must be power of 2 no larger than 256.
23// - number of processors per cluster must be power of 2 no larger than 8.
24///////////////////////////////////////////////////////////////////////////////////////
25
26#include "stdio.h"
27#include "stdlib.h"
28#include "user_barrier.h"
29#include "malloc.h"
30
31#define USE_SQT_BARRIER            1
32#define VERBOSE                    1
33#define SUPER_VERBOSE              0
34
35#define X_SIZE_MAX                 16
36#define Y_SIZE_MAX                 16
37#define PROCS_MAX                  8
38#define CLUSTERS_MAX               (X_SIZE_MAX * Y_SIZE_MAX)
39
40#define INITIAL_DISPLAY_ENABLE     0
41#define FINAL_DISPLAY_ENABLE       1
42
43#define PIXEL_SIZE                 2
44#define NL                         1024
45#define NP                         1024
46#define NB_PIXELS                  (NP * NL)
47#define FRAME_SIZE                 (NB_PIXELS * PIXEL_SIZE)
48
49#define SEEK_SET                   0
50
51#define TA(c,l,p)  (A[c][((NP) * (l)) + (p)])
52#define TB(c,p,l)  (B[c][((NL) * (p)) + (l)])
53#define TC(c,l,p)  (C[c][((NP) * (l)) + (p)])
54#define TD(c,l,p)  (D[c][((NP) * (l)) + (p)])
55#define TZ(c,l,p)  (Z[c][((NP) * (l)) + (p)])
56
57#define max(x,y) ((x) > (y) ? (x) : (y))
58#define min(x,y) ((x) < (y) ? (x) : (y))
59
60// macro to use a shared TTY
61#define printf(...);  { lock_acquire( &tty_lock ); \
62                        giet_tty_printf(__VA_ARGS__);  \
63                        lock_release( &tty_lock ); }
64
65//////////////////////////////////////////////////////////
66//   global variables stored in seg_data in cluster[0,0]
67//////////////////////////////////////////////////////////
68
69// Instrumentation counters (cluster_id, lpid]
70
71unsigned int START[CLUSTERS_MAX][PROCS_MAX];
72unsigned int H_BEG[CLUSTERS_MAX][PROCS_MAX];
73unsigned int H_END[CLUSTERS_MAX][PROCS_MAX];
74unsigned int V_BEG[CLUSTERS_MAX][PROCS_MAX];
75unsigned int V_END[CLUSTERS_MAX][PROCS_MAX];
76unsigned int D_BEG[CLUSTERS_MAX][PROCS_MAX];
77unsigned int D_END[CLUSTERS_MAX][PROCS_MAX];
78
79// global synchronization barrier
80
81#if USE_SQT_BARRIER
82giet_sqt_barrier_t  barrier;
83#else
84giet_barrier_t      barrier;
85#endif
86
87volatile unsigned int barrier_init_ok    = 0;
88volatile unsigned int load_image_ok      = 0;
89volatile unsigned int instrumentation_ok = 0;
90
91// lock protecting access to shared TTY
92user_lock_t         tty_lock;
93
94// global pointers on distributed buffers in all clusters
95unsigned short * GA[CLUSTERS_MAX];
96int *            GB[CLUSTERS_MAX];
97int *            GC[CLUSTERS_MAX];
98int *            GD[CLUSTERS_MAX];
99unsigned char *  GZ[CLUSTERS_MAX];
100
101
102
103////////////////////////////////////////////
104__attribute__ ((constructor)) void execute()
105////////////////////////////////////////////
106{
107    /////////////////////////////////////////////////////////////////////////////////////
108    // Each thread[x,y,p] initialises the convolution kernel parameters in local stack.
109    // The values defined in the next 12 lines are Philips proprietary information.
110    /////////////////////////////////////////////////////////////////////////////////////
111
112    int   vnorm  = 115;
113    int   vf[35] = { 1, 1, 2, 2, 2,
114                     2, 3, 3, 3, 4,
115                     4, 4, 4, 5, 5,
116                     5, 5, 5, 5, 5,
117                     5, 5, 4, 4, 4,
118                     4, 3, 3, 3, 2,
119                     2, 2, 2, 1, 1 };
120
121    int hrange = 100;
122    int hnorm  = 201;
123
124    // get plat-form parameters
125    unsigned int x_size;             // number of clusters in a row
126    unsigned int y_size;             // number of clusters in a column
127    unsigned int nprocs;             // number of processors per cluster
128    giet_procs_number( &x_size , &y_size , &nprocs );
129
130    // get processor identifiers
131    unsigned int x;                  // x coordinate
132    unsigned int y;                  // y coordinate
133    unsigned int lpid;               // local proc index
134    giet_proc_xyp( &x, &y, &lpid );
135
136    // indexes for loops
137    int c; // cluster index
138    int l; // line index
139    int p; // pixel index
140    int z; // vertical filter index
141
142    int          file       = 0;                            // file descriptor
143    unsigned int nclusters  = x_size * y_size;              // number of clusters
144    unsigned int cluster_id = (x * y_size) + y;             // continuous cluster index
145    unsigned int thread_id  = (cluster_id * nprocs) + lpid; // continuous thread index
146    unsigned int nthreads   = nclusters * nprocs;           // number of threads
147    unsigned int frame_size = FRAME_SIZE;                   // total size (bytes)
148    unsigned int lines_per_thread   = NL / nthreads;        // lines per thread
149    unsigned int lines_per_cluster  = NL / nclusters;       // lines per cluster
150    unsigned int pixels_per_thread  = NP / nthreads;        // columns per thread
151    unsigned int pixels_per_cluster = NP / nclusters;       // columns per cluster
152
153    int first, last;
154
155    unsigned int date = giet_proctime();
156    START[cluster_id][lpid] = date;
157
158    /////////////////////////////////////////////////////////////////////
159    // Each thread[x][y][0] allocate the global buffers in cluster(x,y)
160    /////////////////////////////////////////////////////////////////////
161    if ( lpid == 0 )
162    {
163
164#if VERBOSE
165printf( "\n[CONVOL] thread[%d,%d,%d] enters malloc at cycle %d\n", 
166                 x,y,lpid, date );
167#endif
168
169        GA[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)   , x , y );
170        GB[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)*2 , x , y );
171        GC[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)*2 , x , y );
172        GD[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)*2 , x , y );
173        GZ[cluster_id] = remote_malloc( (FRAME_SIZE/nclusters)/2 , x , y );
174       
175#if VERBOSE
176printf( "\n[CONVOL]  Shared Buffer Virtual Addresses in cluster(%d,%d)\n"
177        "### GA = %x\n"
178        "### GB = %x\n"               
179        "### GC = %x\n"               
180        "### GD = %x\n"               
181        "### GZ = %x\n",
182        x, y,
183        GA[cluster_id],
184        GB[cluster_id],
185        GC[cluster_id],
186        GD[cluster_id],
187        GZ[cluster_id] );
188#endif
189    }
190
191    ///////////////////////////////
192    #if USE_SQT_BARRIER
193    sqt_barrier_wait( &barrier );
194    #else
195    barrier_wait( &barrier );
196    #endif
197
198    //////////////////////////////////////////////////////////////////////
199    // Each thread[x,y,p] initialise in its private stack a copy of the
200    // arrays of pointers on the shared, distributed buffers.
201    //////////////////////////////////////////////////////////////////////
202
203    unsigned short * A[CLUSTERS_MAX];
204    int            * B[CLUSTERS_MAX];
205    int            * C[CLUSTERS_MAX];
206    int            * D[CLUSTERS_MAX];
207    unsigned char  * Z[CLUSTERS_MAX];
208
209    for (c = 0; c < nclusters; c++)
210    {
211        A[c] = GA[c];
212        B[c] = GB[c];
213        C[c] = GC[c];
214        D[c] = GD[c];
215        Z[c] = GZ[c];
216    }
217
218    /////////////////////////////////////////////////////////////////////////////
219    // Ech thread[x,y,0] open the file containing image, and load it from disk
220    // to the local A[c] buffer (frame_size / nclusters loaded in each cluster).
221    // Other threads are waiting on the init_ok condition.
222    ////////////////////////////////////////////////////////////////////////////
223    if ( lpid==0 )
224    {
225        // open file
226        file = giet_fat_open( "/misc/philips_1024.raw" , 0 );
227        if (file < 0 )
228        {
229            printf("\n[CONVOL ERROR] thread[%d,%d,%d] "
230                   "cannot open file /misc/philips_1024.raw",
231                   x, y, lpid );
232            giet_pthread_exit( NULL );
233        } 
234 
235#if VERBOSE
236printf( "\n[CONVOL] thread[%d,%d,%d] open file /misc/philips_1024.raw at cycle %d\n", 
237        x, y, lpid, giet_proctime() );
238#endif
239
240        unsigned int offset = (frame_size/nclusters)*cluster_id;
241        unsigned int size   = frame_size/nclusters;
242
243        if ( giet_fat_lseek( file,
244                             offset,
245                             SEEK_SET ) )
246        {
247            printf("\n[CONVOL ERROR] thread[%d,%d,%d] "
248                   "cannot seek file /misc/philips_1024.raw",
249                   x, y, lpid );
250            giet_pthread_exit( NULL );
251        } 
252
253        if ( giet_fat_read( file,
254                            A[cluster_id],
255                            size ) != size )
256        {
257            printf("\n[CONVOL ERROR] thread[%d,%d,%d] "
258                   "cannot read file /misc/philips_1024.raw",
259                   x, y, lpid );
260            giet_pthread_exit( NULL );
261        }
262 
263#if VERBOSE
264printf( "\n[CONVOL] thread[%d,%d,%d] load file /misc/philips_1024.raw at cycle %d\n", 
265        x, y, lpid, giet_proctime() );
266#endif
267
268    }
269
270    ///////////////////////////////
271    #if USE_SQT_BARRIER
272    sqt_barrier_wait( &barrier );
273    #else
274    barrier_wait( &barrier );
275    #endif
276
277    /////////////////////////////////////////////////////////////////////////////
278    // Optionnal parallel display of the initial image stored in A[c] buffers.
279    // Eah thread[x,y,p] displays (NL/nthreads) lines. (one byte per pixel).
280    /////////////////////////////////////////////////////////////////////////////
281
282    if ( INITIAL_DISPLAY_ENABLE )
283    {
284
285#if VERBOSE
286printf( "\n[CONVOL] thread[%d,%d,%d] starts initial display at cycle %d\n",
287        x, y, lpid, giet_proctime() );
288#endif
289
290        unsigned int line;
291        unsigned int offset = lines_per_thread * lpid;
292
293        for ( l = 0 ; l < lines_per_thread ; l++ )
294        {
295            line = offset + l;
296
297            for ( p = 0 ; p < NP ; p++ )
298            {
299                TZ(cluster_id, line, p) = (unsigned char)(TA(cluster_id, line, p) >> 8);
300            }
301
302            giet_fbf_sync_write( NP*(l + (thread_id * lines_per_thread) ), 
303                                 &TZ(cluster_id, line, 0), 
304                                 NP);
305        }
306
307#if VERBOSE
308printf( "\n[CONVOL] thread[%d,%d,%d] completes initial display at cycle %d\n",
309        x, y, lpid, giet_proctime() );
310#endif
311
312        ////////////////////////////
313        #if USE_SQT_BARRIER
314        sqt_barrier_wait( &barrier );
315        #else
316        barrier_wait( &barrier );
317        #endif
318
319    }
320
321    ////////////////////////////////////////////////////////
322    // parallel horizontal filter :
323    // B <= transpose(FH(A))
324    // D <= A - FH(A)
325    // Each thread computes (NL/nthreads) lines
326    // The image must be extended :
327    // if (z<0)    TA(cluster_id,l,z) == TA(cluster_id,l,0)
328    // if (z>NP-1) TA(cluster_id,l,z) == TA(cluster_id,l,NP-1)
329    ////////////////////////////////////////////////////////
330
331    date  = giet_proctime();
332    H_BEG[cluster_id][lpid] = date;
333
334#if VERBOSE
335printf( "\n[CONVOL] thread[%d,%d,%d] starts horizontal filter"
336        " at cycle %d\n",
337        x, y, lpid, date );
338#else
339if ( (x==0) && (y==0) && (lpid==0) ) 
340printf( "\n[CONVOL] thread[0,0,0] starts horizontal filter"
341        " at cycle %d\n", date );
342#endif
343
344    // l = absolute line index / p = absolute pixel index 
345    // first & last define which lines are handled by a given thread
346
347    first = thread_id * lines_per_thread;
348    last  = first + lines_per_thread;
349
350    for (l = first; l < last; l++)
351    {
352        // src_c and src_l are the cluster index and the line index for A & D
353        int src_c = l / lines_per_cluster;
354        int src_l = l % lines_per_cluster;
355
356        // We use the specific values of the horizontal ep-filter for optimisation:
357        // sum(p) = sum(p-1) + TA[p+hrange] - TA[p-hrange-1]
358        // To minimize the number of tests, the loop on pixels is split in three domains
359
360        int sum_p = (hrange + 2) * TA(src_c, src_l, 0);
361        for (z = 1; z < hrange; z++)
362        {
363            sum_p = sum_p + TA(src_c, src_l, z);
364        }
365
366        // first domain : from 0 to hrange
367        for (p = 0; p < hrange + 1; p++)
368        {
369            // dst_c and dst_p are the cluster index and the pixel index for B
370            int dst_c = p / pixels_per_cluster;
371            int dst_p = p % pixels_per_cluster;
372            sum_p = sum_p + (int) TA(src_c, src_l, p + hrange) - (int) TA(src_c, src_l, 0);
373            TB(dst_c, dst_p, l) = sum_p / hnorm;
374            TD(src_c, src_l, p) = (int) TA(src_c, src_l, p) - sum_p / hnorm;
375        }
376        // second domain : from (hrange+1) to (NP-hrange-1)
377        for (p = hrange + 1; p < NP - hrange; p++)
378        {
379            // dst_c and dst_p are the cluster index and the pixel index for B
380            int dst_c = p / pixels_per_cluster;
381            int dst_p = p % pixels_per_cluster;
382            sum_p = sum_p + (int) TA(src_c, src_l, p + hrange) 
383                          - (int) TA(src_c, src_l, p - hrange - 1);
384            TB(dst_c, dst_p, l) = sum_p / hnorm;
385            TD(src_c, src_l, p) = (int) TA(src_c, src_l, p) - sum_p / hnorm;
386        }
387        // third domain : from (NP-hrange) to (NP-1)
388        for (p = NP - hrange; p < NP; p++)
389        {
390            // dst_c and dst_p are the cluster index and the pixel index for B
391            int dst_c = p / pixels_per_cluster;
392            int dst_p = p % pixels_per_cluster;
393            sum_p = sum_p + (int) TA(src_c, src_l, NP - 1) 
394                          - (int) TA(src_c, src_l, p - hrange - 1);
395            TB(dst_c, dst_p, l) = sum_p / hnorm;
396            TD(src_c, src_l, p) = (int) TA(src_c, src_l, p) - sum_p / hnorm;
397        }
398
399#if SUPER_VERBOSE
400printf(" - line %d computed at cycle %d\n", l, giet_proctime() );
401#endif   
402
403    }
404
405    date  = giet_proctime();
406    H_END[cluster_id][lpid] = date;
407
408#if VERBOSE
409printf( "\n[CONVOL] thread[%d,%d,%d] completes horizontal filter"
410        " at cycle %d\n",
411        x, y, lpid, date );
412#else
413if ( (x==0) && (y==0) && (lpid==0) ) 
414printf( "\n[CONVOL] thread[0,0,0] completes horizontal filter"
415        " at cycle %d\n", date );
416#endif
417
418    /////////////////////////////
419    #if USE_SQT_BARRIER
420    sqt_barrier_wait( &barrier );
421    #else
422    barrier_wait( &barrier );
423    #endif
424
425
426    ///////////////////////////////////////////////////////////////
427    // parallel vertical filter :
428    // C <= transpose(FV(B))
429    // Each thread computes (NP/nthreads) columns
430    // The image must be extended :
431    // if (l<0)    TB(cluster_id,p,l) == TB(cluster_id,p,0)
432    // if (l>NL-1)   TB(cluster_id,p,l) == TB(cluster_id,p,NL-1)
433    ///////////////////////////////////////////////////////////////
434
435    date  = giet_proctime();
436    V_BEG[cluster_id][lpid] = date;
437
438#if VERBOSE
439printf( "\n[CONVOL] thread[%d,%d,%d] starts vertical filter"
440        " at cycle %d\n",
441        x, y, lpid, date );
442#else
443if ( (x==0) && (y==0) && (lpid==0) ) 
444printf( "\n[CONVOL] thread[0,0,0] starts vertical filter"
445        " at cycle %d\n", date );
446#endif
447
448    // l = absolute line index / p = absolute pixel index
449    // first & last define which pixels are handled by a given thread
450
451    first = thread_id * pixels_per_thread;
452    last  = first + pixels_per_thread;
453
454    for (p = first; p < last; p++)
455    {
456        // src_c and src_p are the cluster index and the pixel index for B
457        int src_c = p / pixels_per_cluster;
458        int src_p = p % pixels_per_cluster;
459
460        int sum_l;
461
462        // We use the specific values of the vertical ep-filter
463        // To minimize the number of tests, the NL lines are split in three domains
464
465        // first domain : explicit computation for the first 18 values
466        for (l = 0; l < 18; l++)
467        {
468            // dst_c and dst_l are the cluster index and the line index for C
469            int dst_c = l / lines_per_cluster;
470            int dst_l = l % lines_per_cluster;
471
472            for (z = 0, sum_l = 0; z < 35; z++)
473            {
474                sum_l = sum_l + vf[z] * TB(src_c, src_p, max(l - 17 + z,0) );
475            }
476            TC(dst_c, dst_l, p) = sum_l / vnorm;
477        }
478        // second domain
479        for (l = 18; l < NL - 17; l++)
480        {
481            // dst_c and dst_l are the cluster index and the line index for C
482            int dst_c = l / lines_per_cluster;
483            int dst_l = l % lines_per_cluster;
484
485            sum_l = sum_l + TB(src_c, src_p, l + 4)
486                  + TB(src_c, src_p, l + 8)
487                  + TB(src_c, src_p, l + 11)
488                  + TB(src_c, src_p, l + 15)
489                  + TB(src_c, src_p, l + 17)
490                  - TB(src_c, src_p, l - 5)
491                  - TB(src_c, src_p, l - 9)
492                  - TB(src_c, src_p, l - 12)
493                  - TB(src_c, src_p, l - 16)
494                  - TB(src_c, src_p, l - 18);
495
496            TC(dst_c, dst_l, p) = sum_l / vnorm;
497        }
498        // third domain
499        for (l = NL - 17; l < NL; l++)
500        {
501            // dst_c and dst_l are the cluster index and the line index for C
502            int dst_c = l / lines_per_cluster;
503            int dst_l = l % lines_per_cluster;
504
505            sum_l = sum_l + TB(src_c, src_p, min(l + 4, NL - 1))
506                  + TB(src_c, src_p, min(l + 8, NL - 1))
507                  + TB(src_c, src_p, min(l + 11, NL - 1))
508                  + TB(src_c, src_p, min(l + 15, NL - 1))
509                  + TB(src_c, src_p, min(l + 17, NL - 1))
510                  - TB(src_c, src_p, l - 5)
511                  - TB(src_c, src_p, l - 9)
512                  - TB(src_c, src_p, l - 12)
513                  - TB(src_c, src_p, l - 16)
514                  - TB(src_c, src_p, l - 18);
515
516            TC(dst_c, dst_l, p) = sum_l / vnorm;
517        }
518
519#if SUPER_VERBOSE
520printf(" - column %d computed at cycle %d\n", p, giet_proctime());
521#endif
522
523    }
524
525    date  = giet_proctime();
526    V_END[cluster_id][lpid] = date;
527
528#if VERBOSE
529printf( "\n[CONVOL] thread[%d,%d,%d] completes vertical filter"
530        " at cycle %d\n",
531        x, y, lpid, date );
532#else
533if ( (x==0) && (y==0) && (lpid==0) ) 
534printf( "\n[CONVOL] thread[0,0,0] completes vertical filter"
535        " at cycle %d\n", date );
536#endif
537
538    ////////////////////////////
539    #if USE_SQT_BARRIER
540    sqt_barrier_wait( &barrier );
541    #else
542    barrier_wait( &barrier );
543    #endif
544
545    ////////////////////////////////////////////////////////////////////////
546    // Optional parallel display of the final image Z <= D + C
547    // Eah thread[x,y,p] displays (NL/nthreads) lines. (one byte per pixel).
548    ////////////////////////////////////////////////////////////////////////
549
550    if ( FINAL_DISPLAY_ENABLE )
551    {
552        date  = giet_proctime();
553        D_BEG[cluster_id][lpid] = date;
554
555#if VERBOSE
556printf( "\n[CONVOL] thread[%d,%d,%d] starts final display"
557        " at cycle %d\n",
558        x, y, lpid, date);
559#else
560if ( (x==0) && (y==0) && (lpid==0) ) 
561printf( "\n[CONVOL] thread[0,0,0] starts final display"
562        " at cycle %d\n", date );
563#endif
564
565        unsigned int line;
566        unsigned int offset = lines_per_thread * lpid;
567
568        for ( l = 0 ; l < lines_per_thread ; l++ )
569        {
570            line = offset + l;
571
572            for ( p = 0 ; p < NP ; p++ )
573            {
574                TZ(cluster_id, line, p) = 
575                   (unsigned char)( (TD(cluster_id, line, p) + 
576                                     TC(cluster_id, line, p) ) >> 8 );
577            }
578
579            giet_fbf_sync_write( NP*(l + (thread_id * lines_per_thread) ), 
580                                 &TZ(cluster_id, line, 0), 
581                                 NP);
582        }
583
584        date  = giet_proctime();
585        D_END[cluster_id][lpid] = date;
586
587#if VERBOSE
588printf( "\n[CONVOL] thread[%d,%d,%d] completes final display"
589        " at cycle %d\n",
590        x, y, lpid, date);
591#else
592if ( (x==0) && (y==0) && (lpid==0) ) 
593printf( "\n[CONVOL] thread[0,0,0] completes final display"
594        " at cycle %d\n", date );
595#endif
596     
597    //////////////////////////////
598    #if USE_SQT_BARRIER
599    sqt_barrier_wait( &barrier );
600    #else
601    barrier_wait( &barrier );
602    #endif
603
604    }
605
606    // all threads (but the one executing main) exit
607    if ( (x!=0) || (y!=0) || (lpid!=0) )
608    {
609        giet_pthread_exit( "completed");
610    }
611
612} // end execute()
613
614
615
616/////////////////////////////////////////
617void instrument( unsigned int nclusters,
618                 unsigned int nprocs )
619/////////////////////////////////////////
620{
621        int cc, pp;
622
623        unsigned int min_start = 0xFFFFFFFF;
624        unsigned int max_start = 0;
625
626        unsigned int min_h_beg = 0xFFFFFFFF;
627        unsigned int max_h_beg = 0;
628
629        unsigned int min_h_end = 0xFFFFFFFF;
630        unsigned int max_h_end = 0;
631
632        unsigned int min_v_beg = 0xFFFFFFFF;
633        unsigned int max_v_beg = 0;
634
635        unsigned int min_v_end = 0xFFFFFFFF;
636        unsigned int max_v_end = 0;
637
638        unsigned int min_d_beg = 0xFFFFFFFF;
639        unsigned int max_d_beg = 0;
640
641        unsigned int min_d_end = 0xFFFFFFFF;
642        unsigned int max_d_end = 0;
643
644        for (cc = 0; cc < nclusters; cc++)
645        {
646            for (pp = 0; pp < nprocs; pp++ )
647            {
648                if (START[cc][pp] < min_start) min_start = START[cc][pp];
649                if (START[cc][pp] > max_start) max_start = START[cc][pp];
650
651                if (H_BEG[cc][pp] < min_h_beg) min_h_beg = H_BEG[cc][pp];
652                if (H_BEG[cc][pp] > max_h_beg) max_h_beg = H_BEG[cc][pp];
653
654                if (H_END[cc][pp] < min_h_end) min_h_end = H_END[cc][pp];
655                if (H_END[cc][pp] > max_h_end) max_h_end = H_END[cc][pp];
656
657                if (V_BEG[cc][pp] < min_v_beg) min_v_beg = V_BEG[cc][pp];
658                if (V_BEG[cc][pp] > max_v_beg) max_v_beg = V_BEG[cc][pp];
659
660                if (V_END[cc][pp] < min_v_end) min_v_end = V_END[cc][pp];
661                if (V_END[cc][pp] > max_v_end) max_v_end = V_END[cc][pp];
662
663                if (D_BEG[cc][pp] < min_d_beg) min_d_beg = D_BEG[cc][pp];
664                if (D_BEG[cc][pp] > max_d_beg) max_d_beg = D_BEG[cc][pp];
665
666                if (D_END[cc][pp] < min_d_end) min_d_end = D_END[cc][pp];
667                if (D_END[cc][pp] > max_d_end) max_d_end = D_END[cc][pp];
668            }
669        }
670
671        printf(" - START : min = %d / max = %d / med = %d / delta = %d\n",
672               min_start, max_start, (min_start+max_start)/2, max_start-min_start);
673
674        printf(" - H_BEG : min = %d / max = %d / med = %d / delta = %d\n",
675               min_h_beg, max_h_beg, (min_h_beg+max_h_beg)/2, max_h_beg-min_h_beg);
676
677        printf(" - H_END : min = %d / max = %d / med = %d / delta = %d\n",
678               min_h_end, max_h_end, (min_h_end+max_h_end)/2, max_h_end-min_h_end);
679
680        printf(" - V_BEG : min = %d / max = %d / med = %d / delta = %d\n",
681               min_v_beg, max_v_beg, (min_v_beg+max_v_beg)/2, max_v_beg-min_v_beg);
682
683        printf(" - V_END : min = %d / max = %d / med = %d / delta = %d\n",
684               min_v_end, max_v_end, (min_v_end+max_v_end)/2, max_v_end-min_v_end);
685
686        printf(" - D_BEG : min = %d / max = %d / med = %d / delta = %d\n",
687               min_d_beg, max_d_beg, (min_d_beg+max_d_beg)/2, max_d_beg-min_d_beg);
688
689        printf(" - D_END : min = %d / max = %d / med = %d / delta = %d\n",
690               min_d_end, max_d_end, (min_d_end+max_d_end)/2, max_d_end-min_d_end);
691
692        printf( "\n General Scenario (Kcycles for each step)\n" );
693        printf( " - BOOT OS           = %d\n", (min_start            )/1000 );
694        printf( " - LOAD IMAGE        = %d\n", (min_h_beg - min_start)/1000 );
695        printf( " - H_FILTER          = %d\n", (max_h_end - min_h_beg)/1000 );
696        printf( " - BARRIER HORI/VERT = %d\n", (min_v_beg - max_h_end)/1000 );
697        printf( " - V_FILTER          = %d\n", (max_v_end - min_v_beg)/1000 );
698        printf( " - BARRIER VERT/DISP = %d\n", (min_d_beg - max_v_end)/1000 );
699        printf( " - DISPLAY           = %d\n", (max_d_end - min_d_beg)/1000 );
700
701} // end instrument()
702
703
704
705///////////////////////////////////////////
706__attribute__ ((constructor)) void main()
707///////////////////////////////////////////
708{
709    // get plat-form parameters
710    unsigned int x_size;                 // number of clusters in a row
711    unsigned int y_size;                 // number of clusters in a column
712    unsigned int nprocs;                 // number of processors per cluster
713    giet_procs_number( &x_size , &y_size , &nprocs );
714
715    // processor identifiers
716    unsigned int x;                      // x coordinate
717    unsigned int y;                      // y coordinate
718    unsigned int lpid;                   // local proc index
719    giet_proc_xyp( &x, &y, &lpid );
720
721    // indexes for loops
722    unsigned int cx;
723    unsigned int cy;
724    unsigned int n;
725
726    unsigned int nclusters  = x_size * y_size;         
727    unsigned int nthreads   = nclusters * nprocs;     
728
729    // parameters checking
730    if ((nprocs != 1) && (nprocs != 2) && (nprocs != 4) && (nprocs != 8))
731        giet_pthread_exit( "[CONVOL ERROR] NB_PROCS_MAX must be 1, 2, 4 or 8\n");
732
733    if ((x_size!=1) && (x_size!=2) && (x_size!=4) && (x_size!=8) && (x_size!=16))
734        giet_pthread_exit( "[CONVOL ERROR] X_SIZE must be 1, 2, 4, 8, 16\n");
735       
736    if ((y_size!=1) && (y_size!=2) && (y_size!=4) && (y_size!=8) && (y_size!=16))
737        giet_pthread_exit( "[CONVOL ERROR] Y_SIZE must be 1, 2, 4, 8, 16\n");
738
739    if ( NL % nclusters != 0 )
740        giet_pthread_exit( "[CONVOL ERROR] X_SIZE*Y_SIZE must be a divider of NL");
741
742    if ( NP % nclusters != 0 )
743        giet_pthread_exit( "[CONVOL ERROR] X_SIZE*Y_SIZE must be a divider of NP");
744
745    // get a shared TTY
746    giet_tty_alloc( 1 );
747    lock_init( &tty_lock );
748
749    // initializes the distributed heap[x,y]
750    for ( cx = 0 ; cx < x_size ; cx++ )
751    {
752        for ( cy = 0 ; cy < y_size ; cy++ )
753        {
754            heap_init( cx , cy );
755        }
756    }
757
758    // allocate trdid[] array
759    pthread_t* trdid = malloc( nthreads * sizeof(pthread_t) );
760
761    // barrier initialisation
762#if USE_SQT_BARRIER
763    sqt_barrier_init( &barrier, x_size , y_size , nprocs );
764#else
765    barrier_init( &barrier, nthreads );
766#endif
767
768    printf("\n[CONVOL] thread[0,0,0] completes initialisation at cycle %d\n" 
769           "- CLUSTERS     = %d\n"
770           "- PROCS        = %d\n" 
771           "- THREADS      = %d\n",
772           giet_proctime(), nclusters, nprocs, nthreads );
773
774    // launch other threads to run execute() function
775    for ( n = 1 ; n < nthreads ; n++ )
776    {
777        if ( giet_pthread_create( &trdid[n],
778                                  NULL,                  // no attribute
779                                  &execute,
780                                  NULL ) )               // no argument
781        {
782            printf("\n[TRANSPOSE ERROR] creating thread %x\n", trdid[n] );
783            giet_pthread_exit( NULL );
784        }
785    }
786
787    // run the execute() function
788    execute();
789
790    // wait other threads completion
791    for ( n = 1 ; n < nthreads ; n++ )
792    {
793        if ( giet_pthread_join( trdid[n], NULL ) )
794        {
795            printf("\n[TRANSPOSE ERROR] joining thread %x\n", trdid[n] );
796            giet_pthread_exit( NULL );
797        }
798        else
799        {
800            printf("\n[TRANSPOSE] thread %x joined at cycle %d\n",
801                   trdid[n] , giet_proctime() );
802        }
803    }
804
805    // call the instrument() function
806    instrument( nclusters , nprocs );
807
808    giet_pthread_exit( "completed" );
809   
810} // end main()
811
812
813
814// Local Variables:
815// tab-width: 3
816// c-basic-offset: 3
817// c-file-offsets:((innamespace . 0)(inline-open . 0))
818// indent-tabs-mode: nil
819// End:
820
821// vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3
822
823
Note: See TracBrowser for help on using the repository browser.