000038baadbd2993ad359093558b915041e49e7f
[charm.git] / examples / multiphaseSharedArrays / histogram / histogram.C
1 // -*- mode: c++; tab-width: 4 -*-
2 //
3 #include "msa/msa.h"
4
5 typedef MSA::MSA2D<int, DefaultEntry<int>,
6         MSA_DEFAULT_ENTRIES_PER_PAGE, MSA_ROW_MAJOR> MSA2D;
7 typedef MSA::MSA1D<int, DefaultEntry<int>, MSA_DEFAULT_ENTRIES_PER_PAGE> MSA1D;
8
9 #include "histogram.decl.h"
10
11
12 const unsigned int ROWS = 2000;
13 const unsigned int COLS = 2000;
14 const unsigned int BINS = 10;
15 const unsigned int MAX_ENTRY = 1000;
16 unsigned int WORKERS = 10;
17
18
19 class Driver : public CBase_Driver
20 {
21 public:
22     Driver(CkArgMsg* m)
23     {
24         // Usage: histogram [number_of_worker_threads]
25         if (m->argc > 1) WORKERS=atoi(m->argv[1]);
26         delete m;
27
28         // Actually build the shared arrays: a 2d array to hold arbitrary
29         // data, and a 1d histogram array.
30         MSA2D data(ROWS, COLS, WORKERS);
31         MSA1D bins(BINS, WORKERS);
32  
33         // Create worker threads and start them off.
34         workers = CProxy_Histogram::ckNew(data, bins, WORKERS);
35         workers.ckSetReductionClient(
36             new CkCallback(CkIndex_Driver::done(NULL), thisProxy));
37         workers.start();
38     }
39
40     void done(CkReductionMsg* m)
41     {
42         // When the reduction is complete, everything is ready to exit.
43         CkExit();
44     }
45 };
46
47
48 class Histogram: public CBase_Histogram
49 {
50 public:
51     MSA2D data;
52     MSA1D bins;
53
54     Histogram(const MSA2D& data_, const MSA1D& bins_)
55     : data(data_), bins(bins_)
56     {}
57
58     Histogram(CkMigrateMessage* m)
59     {}
60
61     ~Histogram()
62     {}
63
64     // Note: it's important that start is a threaded entry method
65     // so that the blocking MSA calls work as intended.
66     void start()
67     {
68         data.enroll(WORKERS);
69         bins.enroll(WORKERS);
70         
71         // Fill the data array with random numbers.
72                 MSA2D::Write wd = data.getInitialWrite();
73         if (thisIndex == 0) fill_array(wd);
74
75         // Fill the histogram bins: read from the data array and
76         // accumulate to the histogram array.
77                 MSA2D::Read rd = wd.syncToRead();
78         MSA1D::Accum ab = bins.getInitialAccum();
79         fill_bins(ab, rd);
80
81         // Print the histogram.
82         MSA1D::Read rb = ab.syncToRead();
83         if (thisIndex == 0) print_array(rb);
84
85         // Contribute to Driver::done to terminate the program.
86         contribute();
87     }
88
89     void fill_array(MSA2D::Write& w)
90     {
91         // Just let one thread fill the whole data array
92         // with random entries to be histogrammed.
93         for (unsigned int r = 0; r < data.getRows(); r++) {
94             for (unsigned int c = 0; c < data.getCols(); c++) {
95                 w.set(r, c) = random() % MAX_ENTRY;
96             }
97         }
98     }
99
100     void fill_bins(MSA1D::Accum& b, MSA2D::Read& d)
101     {
102         // Determine the range of the data array that this
103         // worker should read from.
104         unsigned int range = ROWS / WORKERS;
105         unsigned int min_row = thisIndex * range;
106         unsigned int max_row = (thisIndex + 1) * range;
107         
108         // Count the entries that belong to each bin.
109         for (unsigned int r = 0; r < data.getRows(); r++) {
110             for (unsigned int c = 0; c < data.getCols(); c++) {
111                 unsigned int bin = d.get(r, c) / (MAX_ENTRY / BINS);
112                 b(bin) += 1;
113             }
114         }
115     }
116
117     void print_array(MSA1D::Read& b)
118     {
119         for (unsigned int i=0; i<BINS; ++i) {
120             CkPrintf("%d ", b.get(i)); 
121         }
122     }
123 };
124
125 #include "histogram.def.h"