Merge branch 'charm' of charmgit:charm into charm
[charm.git] / tests / charm++ / loadbalancing / jacobi2D / Jacobi2D.C
1
2 #include "Jacobi2D.h"
3
4 #define ITERATIONS 10
5
6   TheMain::TheMain(CkArgMsg *)
7   {
8    CkPrintf("ChareArray %d sq, data array %d sq, iterations %d\n", TheMain::NUM_CHUNKS, TheMain::CHUNK_SIZE, ITERATIONS);
9    CProxy_JacobiChunk jc = CProxy_JacobiChunk::ckNew(TheMain::NUM_CHUNKS,TheMain::NUM_CHUNKS);
10    jc(0,0).setStartTime(CmiWallTimer());
11    jc.startNextIter();
12   }
13   void TheMain::pup(PUP::er &p) {
14    CBase_TheMain::pup(p);
15   }
16
17   JacobiChunk::JacobiChunk() {
18    int i;
19    int j;
20    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   for(j = 1;(j <= TheMain::CHUNK_SIZE);(j++))   data[i][j] = (100.0 + (((i + j) % 2)?(-1):1));
21    numGot = 0;
22    numIters = 0;
23    numDone = 0;
24    numNeighbors = 4;
25    if (((thisIndex.x == 0) || (thisIndex.x == (TheMain::NUM_CHUNKS - 1))))
26    (--numNeighbors);
27    if (((thisIndex.y == 0) || (thisIndex.y == (TheMain::NUM_CHUNKS - 1))))
28    (--numNeighbors);
29    maxDelta = 0.0;
30    numIters = ITERATIONS;
31    usesAtSync = true;
32    usesAutoMeasure = true;
33   }
34
35   void JacobiChunk::setStartTime(double t)
36   {
37      CkPrintf("Start time = %f\n", t);
38      startTime = t;
39   }
40
41   void JacobiChunk::startNextIter()
42   {
43     int i;
44     startT = CmiWallTimer();
45     if (thisIndex.x == 0 && thisIndex.y == 0) CmiPrintf("startNextIter: %d\n", numIters);
46     if ((thisIndex.x > 0))
47     thisProxy((thisIndex.x - 1),thisIndex.y).getBottom(data[1]);
48     if ((thisIndex.x < (TheMain::NUM_CHUNKS - 1)))
49     thisProxy((thisIndex.x + 1),thisIndex.y).getTop(data[TheMain::CHUNK_SIZE]);
50     float tmp[TheMain::CHUNK_SIZE + 2];
51     if ((thisIndex.y > 0))
52     {
53      for(i = 0;(i <= (TheMain::CHUNK_SIZE + 1));(i++))     tmp[i] = data[i][1];
54      thisProxy(thisIndex.x,(thisIndex.y - 1)).getRight(tmp);
55     }
56     if ((thisIndex.y < (TheMain::NUM_CHUNKS - 1)))
57     {
58      for(i = 0;(i <= (TheMain::CHUNK_SIZE + 1));(i++))     tmp[i] = data[i][TheMain::CHUNK_SIZE];
59      thisProxy(thisIndex.x,(thisIndex.y + 1)).getLeft(tmp);
60     }
61   }
62
63   void JacobiChunk::getLeft(float left[])
64   {
65    int i;
66    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   data[i][0] = left[i];
67    if (((++numGot) == numNeighbors))
68    {
69     numGot = 0;
70     refine();
71    }
72   }
73   void JacobiChunk::getRight(float right[])
74   {
75    int i;
76    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   data[i][(TheMain::CHUNK_SIZE + 1)] = right[i];
77    if (((++numGot) == numNeighbors))
78    {
79     numGot = 0;
80     refine();
81    }
82   }
83   void JacobiChunk::getTop(float top[])
84   {
85    int i;
86    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   data[0][i] = top[i];
87    if (((++numGot) == numNeighbors))
88    {
89     numGot = 0;
90     refine();
91    }
92   }
93   void JacobiChunk::getBottom(float bottom[])
94   {
95    int i;
96    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   data[(TheMain::CHUNK_SIZE + 1)][i] = bottom[i];
97    if (((++numGot) == numNeighbors))
98    {
99     numGot = 0;
100     refine();
101    }
102   }
103   void JacobiChunk::refine()
104   {
105 //      double t = CmiWallTimer();
106    int i;
107    int j;
108    if ((thisIndex.y == 0))
109    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   data[i][0] = data[i][1];
110    else
111    if ((thisIndex.y == (TheMain::NUM_CHUNKS - 1)))
112    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   data[i][(TheMain::CHUNK_SIZE + 1)] = data[i][TheMain::CHUNK_SIZE];
113    if ((thisIndex.x == 0))
114    for(i = 0;(i <= TheMain::CHUNK_SIZE);(i++))   data[0][i] = data[1][i];
115    else
116    if ((thisIndex.x == (TheMain::NUM_CHUNKS - 1)))
117    for(i = 0;(i <= TheMain::CHUNK_SIZE);(i++))   data[(TheMain::CHUNK_SIZE + 1)][i] = data[TheMain::CHUNK_SIZE][i];
118    for (int k=0; k<(thisIndex.x*TheMain::NUM_CHUNKS + thisIndex.y)*100; k++)
119    for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))   for(j = 1;(j <= TheMain::CHUNK_SIZE);(j++))   data[i][j] = (((((data[(i - 1)][j] + data[i][j]) + data[(i + 1)][j]) + data[i][(j - 1)]) + data[i][(j + 1)]) / 5.0);
120 //     CkPrintf("Iteration time in microsecs = %d\n", (int )((CmiWallTimer() - t) * 1.0e6));
121    if (false)
122    {
123      int i,j;
124      maxDelta = 0;
125      for(i = 1;(i <= TheMain::CHUNK_SIZE);(i++))    for(j = 1;(j <= TheMain::CHUNK_SIZE);(j++))    {
126       float delta = (data[i][j] - data[(i - 1)][j]);
127       if ((delta < 0))
128       delta *= (-1);
129       if ((delta > maxDelta))
130       maxDelta = delta;
131      }
132    }
133
134    double t = CmiWallTimer() - startT;
135    CkCallback cb2(CkIndex_JacobiChunk::print(NULL), thisProxy(0,0));
136    contribute(sizeof(double), &t, CkReduction::max_double, cb2);
137
138      // reduction
139    CkCallback cb(CkIndex_JacobiChunk::stepping(NULL), thisProxy(0,0));
140    contribute(sizeof(float), &maxDelta, CkReduction::max_float, cb);
141   }
142
143   void JacobiChunk::done(float delta)
144   {
145    if ((delta > maxDelta))
146      maxDelta = delta;
147    double t = CmiWallTimer();
148    CkPrintf("From %d %d: %f\n", thisIndex.x, thisIndex.y, maxDelta);
149    CkPrintf("End time = %f, Total time in microsecs = %u\n", t, (unsigned long)((t - startTime) * 1.0e6));
150    CkExit();
151   }
152   void JacobiChunk::pup(PUP::er &p) {
153    CBase_JacobiChunk::pup(p);
154    p|startTime;
155    p|numNeighbors;
156    p|numDone;
157    p|numGot;
158    p|numIters;
159    p|maxDelta;
160    p((char*)data, (TheMain::CHUNK_SIZE+2)*(TheMain::CHUNK_SIZE+2)*sizeof(float));
161   }
162
163   void JacobiChunk::ResumeFromSync() {
164    startNextIter();
165   }
166
167   // a callback function to set object load
168   void JacobiChunk::UserSetLBLoad() {
169     setObjTime(1.0);
170   }
171
172   void JacobiChunk::print(CkReductionMsg *m) {   // on PE 0
173    double maxT = *(double*)m->getData();
174    CmiPrintf("Iter: %d takes %fs.\n", numIters, maxT);
175   }
176
177   void JacobiChunk::stepping(CkReductionMsg *m) {   // on PE 0
178    float max_delta = *(float*)m->getData();
179    delete m;
180    numIters --;
181    if (numIters > 0) {
182      if (numIters % MIGRATE_STEPS == 5) {
183        thisProxy.AtSync();
184      }
185      else
186        thisProxy.startNextIter();
187    }
188    else
189        done(max_delta);
190   }
191
192
193 #include "Jacobi2D.def.h"