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