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