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