Fixed a bug in using the macro for the number of test iterations.
[charm.git] / example / simpleLoopBench / hello.C
1 #include <stdio.h>
2 #include <assert.h>
3 #include <stdlib.h>
4 #include "hello.h"
5
6 #include "hello.decl.h"
7
8 #include <omp.h>
9
10 #define TEST_REPEAT_TIMES 100
11
12 CProxy_Main mainProxy;
13 CProxy_TestInstance allTestsProxy;
14 CProxy_FuncNodeHelper nodeHelperProxy;
15 int totalElems; //the number of test instances
16 int loopTimes;
17 int numChunks;
18 int runningMode;
19
20 int threadNum; //number of threads to be used in non-SMP
21
22 int cmpDFunc(const void *a, const void *b) {
23     double n1 = *(double *)a;
24     double n2 = *(double *)b;
25     if (n1<n2) return -1;
26     if (n1>n2) return 1;
27     return 0;
28 }
29
30 void work(int start, int end, void *result) {
31     int tmp=0;
32     for (int i=start; i<=end; i++) {
33         tmp+=(int)(sqrt(1+cos(i*1.57)));
34     }
35     *(int *)result = tmp;
36     
37    //CkPrintf("From rank[%d]: start=%d, end=%d, result=%d\n", CkMyRank(), start, end, tmp);
38    //fflush(stdout);
39 }
40
41 int openMPWork(int start, int end) {
42     int result = 0;
43     
44     #pragma omp parallel for reduction (+:result)
45     for(int i=start; i<=end; i++) {
46         result += (int)(sqrt(1+cos(i*1.57)));
47     }
48     
49     return result;
50 }
51
52 extern "C" void doCalc(int first, int last, void *result, int paramNum, void * param) {    
53     //double tstart = CmiWallTimer();
54     
55         work(first, last, result);
56     
57         //tstart = CmiWallTimer() - tstart;
58     //printf("start=%d, end=%d, time: %f,result: %d on proc %d\n",first, last, tstart,result,CkMyPe());
59 }
60
61 /*mainchare*/
62 Main::Main(CkArgMsg* m) {
63     
64         //default values        
65     totalElems = 1;
66         numChunks = CkMyNodeSize();
67         loopTimes = 1000;
68         runningMode = NODEHELPER_STATIC;
69         
70     mainStep = 0;
71         numElemFinished = 0;
72         
73     curTestMode = 0;
74     
75     //process command line
76     if (m->argc >1 ){
77         processCommandLine(m->argc,m->argv);
78         }
79     else{               
80                 CkPrintf("Usage: -t(#iterations) -c(#chunks) -a(#test instances) -m(running mode, 0 (non-SMP) or 1|2 (SMP))  -p(#threads)\n");
81         }
82     delete m;
83         
84     omp_set_num_threads(numChunks);    
85     
86         mainTimes = new double[TEST_REPEAT_TIMES];
87         memset(mainTimes, 0, sizeof(double)*TEST_REPEAT_TIMES);
88         
89         CkPrintf("Using NodeHelper Lib with mode: %d, nodesize=%d\n", runningMode, CkMyNodeSize());
90         CkPrintf("Testcase info: %d test instances where the loop iterates %d times, each work is partitioned into %d tasks\n", totalElems, loopTimes, numChunks);
91         
92         nodeHelperProxy = NodeHelper_Init(runningMode, threadNum);
93     mainProxy = thishandle;
94     
95         //create test instances
96     CProxy_cyclicMap myMap = CProxy_cyclicMap::ckNew();
97     CkArrayOptions opts(totalElems);
98     opts.setMap(myMap);
99     allTestsProxy = CProxy_TestInstance::ckNew(opts);
100
101     //serial version
102         int result;
103         double starttime, endtime;
104         for(int i=0; i<3; i++){
105                 starttime = CmiWallTimer();
106                 work(0, loopTimes, &result);            
107                 endtime = CmiWallTimer();
108                 CkPrintf("Calibration %d: the loop takes %.3f us with result %d\n", i+1,  (endtime-starttime)*1e6, result);
109         }
110         int results[5];
111         starttime = CmiWallTimer();
112         for(int i=0; i<5; i++) work(0, loopTimes, results+i);
113         endtime = CmiWallTimer();
114         double avgtime = (endtime-starttime)*1e6/5; //in the unit of us
115         CkPrintf("Calibration: avg time %.3f us of 5 consecutive runs, so a 100us-loop will iterate %d times\n", avgtime, (int)(loopTimes*100.0/avgtime));
116                 
117     CmiSetCPUAffinity(0);
118     CkStartQD(CkIndex_Main::doTests((CkQdMsg *)0), &thishandle);
119 };
120
121 void Main::done(void) {
122     numElemFinished++;
123     if (numElemFinished < totalElems) {
124         return;
125     } else {
126                 mainTimes[mainStep] = (CmiWallTimer() - timestamp)*1e6;
127         mainStep++;
128         numElemFinished=0;
129         if (mainStep < TEST_REPEAT_TIMES) {
130                         doTests(NULL);
131             return;
132         }
133     }   
134     
135         //do some final output
136         allTestsProxy[0].reportSts();
137 };
138
139 void Main::exitTest(){
140         //do some final output
141         qsort(mainTimes, TEST_REPEAT_TIMES, sizeof(double), cmpDFunc);
142         double sum = 0.0;
143         for(int i=0; i<TEST_REPEAT_TIMES-3; i++) sum += mainTimes[i];
144         int maxi = TEST_REPEAT_TIMES;
145         CkPrintf("Global timestep info: avg time: %.3f [%.3f, %.3f, %.3f] (us)\n", sum/(maxi-3), mainTimes[0], mainTimes[maxi/2], mainTimes[maxi-1]);
146         
147     if(curTestMode == 0){
148             CkPrintf("Charm++ NodeHelper Test done\n\n");
149         curTestMode++;
150         mainStep = 0;
151         numElemFinished = 0;
152         doTests(NULL);
153     }else if(curTestMode == 1){        
154         CkPrintf("OpenMP Test done\n");
155         CkExit();
156     }
157 }
158
159 void Main::doTests(CkQdMsg *msg) {
160     delete msg;
161
162     //CkPrintf("===========Starting mainstep %d===========\n", mainStep);    
163
164     if(mainStep == 0){
165         if(curTestMode == 0){
166             CkPrintf("===Start NodeHelper Test===\n");
167         }else if(curTestMode == 1){
168             int numthds = 0;
169             int openmpid;
170             #pragma omp parallel private(openmpid)
171             {
172                 openmpid = omp_get_thread_num();
173                 if(openmpid == 0) numthds = omp_get_num_threads();
174             }
175             CkPrintf("===Start OpenMP Test with %d threads===\n", numthds);
176         }
177     }
178     
179         timestamp = CmiWallTimer(); //record the start time of the whole test
180     for (int i=0; i<totalElems; i++) {
181         allTestsProxy[i].doTest(mainStep, curTestMode);
182         //allTestsProxy[8].doTest(mainStep, curTestMode);
183     }
184 };
185
186 void Main::processCommandLine(int argc,char ** argv) {
187     for (int i=0; i<argc; i++) {
188         if (argv[i][0]=='-') {
189             switch (argv[i][1]) {
190             case 't':
191                 loopTimes = atoi(argv[++i]);
192                 break;
193             case 'c':
194                 numChunks = atoi(argv[++i]);
195                 break;
196             case 'm':
197                 runningMode = atoi(argv[++i]);
198                 break;
199             case 'a':
200                 totalElems = atoi(argv[++i]);
201                 break;
202             case 'p':
203                 threadNum = atoi(argv[++i]);
204                 break;
205             }
206         }
207     }
208 }
209
210
211 TestInstance::TestInstance() {
212     CkPrintf("test case %d is created on proc %d node %d\n", thisIndex, CkMyPe(),CkMyNode());
213     
214         hasTest = 0; 
215         allTimes = new double[TEST_REPEAT_TIMES];
216         allResults = new int[TEST_REPEAT_TIMES];
217         memset(allTimes, 0, sizeof(double)*TEST_REPEAT_TIMES);
218         memset(allResults, 0, sizeof(int)*TEST_REPEAT_TIMES);
219 }
220
221 void TestInstance::doTest(int curstep, int curTestMode) {
222     //printf("On proc %d node %d, begin parallel execution for test case %d %dth iteration\n", CkMyPe(), CkMyNode(), thisIndex,flag);
223         hasTest = 1;
224         int result;
225         
226     double timerec = CmiWallTimer();
227     
228     if(curTestMode == 0){
229             NodeHelper_Parallelize(nodeHelperProxy, doCalc, 0, NULL, 0, numChunks, 0, loopTimes-1, &result, NODEHELPER_INT_SUM);
230     }else if(curTestMode == 1){
231         result = openMPWork(0, loopTimes-1);
232     }
233     
234     allTimes[curstep]=(CmiWallTimer()-timerec)*1e6;
235         allResults[curstep] = result;
236         
237     mainProxy.done();
238 }
239
240 void TestInstance::reportSts(){
241         if(hasTest){
242                 //do sts output
243                 qsort(allTimes, TEST_REPEAT_TIMES, sizeof(double), cmpDFunc);
244                 double sum = 0.0;
245                 for(int i=0; i<TEST_REPEAT_TIMES-3; i++) sum += allTimes[i];
246                 
247                 double avgResult = 0.0;
248                 for(int i=0; i<TEST_REPEAT_TIMES; i++) avgResult += allResults[i];
249                 avgResult /= TEST_REPEAT_TIMES;
250                 
251                 int maxi = TEST_REPEAT_TIMES;
252                 CkPrintf("Test instance[%d]: result:%.3f, avg time: %.3f [%.3f, %.3f, %.3f] (us)\n",thisIndex, avgResult, sum/(maxi-3), allTimes[0], allTimes[maxi/2], allTimes[maxi-1]);           
253     }
254         
255         if(thisIndex == totalElems-1) mainProxy.exitTest();
256         else thisProxy[thisIndex+1].reportSts();
257 }
258
259 #include "hello.def.h"
260