A tweak in order to disable compiler optimization when calibrating the loop consecuti...
[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 #define TEST_REPEAT_TIMES 10
9
10 CProxy_Main mainProxy;
11 CProxy_TestInstance allTestsProxy;
12 CProxy_FuncNodeHelper nodeHelperProxy;
13 int totalElems; //the number of test instances
14 int loopTimes;
15 int numChunks;
16 int runningMode;
17
18 int threadNum; //number of threads to be used in non-SMP
19
20 int cmpDFunc(const void *a, const void *b) {
21     double n1 = *(double *)a;
22     double n2 = *(double *)b;
23     if (n1<n2) return -1;
24     if (n1>n2) return 1;
25     return 0;
26 }
27
28 void work(int start, int end, void *result) {
29     int tmp=0;
30     for (int i=start; i<=end; i++) {
31         tmp+=(int)(sqrt(1+cos(i*1.57)));
32     }
33     *(int *)result = tmp;
34 }
35 extern "C" void doCalc(int first, int last, void *result, int paramNum, void * param) {    
36     //double tstart = CmiWallTimer();
37     
38         work(first, last, result);
39     
40         //tstart = CmiWallTimer() - tstart;
41     //printf("start=%d, end=%d, time: %f,result: %d on proc %d\n",first, last, tstart,result,CkMyPe());
42 }
43
44 /*mainchare*/
45 Main::Main(CkArgMsg* m) {
46     
47         //default values        
48     totalElems = 1;
49         numChunks = CkMyNodeSize();
50         loopTimes = 1000;
51         runningMode = NODEHELPER_STATIC;
52         
53     mainStep = 0;
54         numElemFinished = 0;
55         
56     //process command line
57     if (m->argc >1 ){
58         processCommandLine(m->argc,m->argv);
59         }
60     else{               
61                 CkPrintf("Usage: -t(#iterations) -c(#chunks) -a(#test instances) -m(running mode, 0 (non-SMP) or 1|2 (SMP))  -p(#threads)\n");
62         }
63     delete m;
64         
65         mainTimes = new double[loopTimes];
66         memset(mainTimes, 0, sizeof(double)*loopTimes);
67         
68         CkPrintf("Using NodeHelper Lib with mode: %d, nodesize=%d\n", runningMode, CkMyNodeSize());
69         CkPrintf("Testcase info: %d test instances where the loop iterates %d times, each work is partitioned into %d tasks\n", totalElems, loopTimes, numChunks);
70         
71         nodeHelperProxy = NodeHelper_Init(runningMode, threadNum);
72     mainProxy = thishandle;
73     
74         //create test instances
75     CProxy_cyclicMap myMap = CProxy_cyclicMap::ckNew();
76     CkArrayOptions opts(totalElems);
77     opts.setMap(myMap);
78     allTestsProxy = CProxy_TestInstance::ckNew(opts);
79
80     //serial version
81         int result;
82         double starttime, endtime;
83         for(int i=0; i<3; i++){
84                 starttime = CmiWallTimer();
85                 work(0, loopTimes, &result);            
86                 endtime = CmiWallTimer();
87                 CkPrintf("Calibration %d: the loop takes %.3f us with result %d\n", i+1,  (endtime-starttime)*1e6, result);
88         }
89         int results[5];
90         starttime = CmiWallTimer();
91         for(int i=0; i<5; i++) work(0, loopTimes, results+i);
92         endtime = CmiWallTimer();
93         double avgtime = (endtime-starttime)*1e6/5; //in the unit of us
94         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));
95                 
96     CmiSetCPUAffinity(0);
97     CkStartQD(CkIndex_Main::doTests((CkQdMsg *)0), &thishandle);
98 };
99
100 void Main::done(void) {
101     numElemFinished++;
102     if (numElemFinished < totalElems) {
103         return;
104     } else {
105                 mainTimes[mainStep] = (CmiWallTimer() - timestamp)*1e6;
106         mainStep++;
107         numElemFinished=0;
108         if (mainStep < TEST_REPEAT_TIMES) {
109                         doTests(NULL);
110             return;
111         }
112     }   
113         //do some final output
114         allTestsProxy[0].reportSts();
115 };
116
117 void Main::exitTest(){
118         //do some final output
119         qsort(mainTimes, TEST_REPEAT_TIMES, sizeof(double), cmpDFunc);
120         double sum = 0.0;
121         for(int i=0; i<TEST_REPEAT_TIMES-3; i++) sum += mainTimes[i];
122         int maxi = TEST_REPEAT_TIMES;
123         CkPrintf("Global timestep info: avg time: %.3f [%.3f, %.3f, %.3f] (us)\n", sum/(maxi-3), mainTimes[0], mainTimes[maxi/2], mainTimes[maxi-1]);
124         
125         CkPrintf("All done\n");
126         CkExit();
127 }
128
129 void Main::doTests(CkQdMsg *msg) {
130     delete msg;
131     
132         timestamp = CmiWallTimer(); //record the start time of the whole test
133     for (int i=0; i<totalElems; i++) {
134         allTestsProxy[i].doTest(mainStep);
135         //allTestsProxy[8].doTest(mainStep);
136     }
137 };
138
139 void Main::processCommandLine(int argc,char ** argv) {
140     for (int i=0; i<argc; i++) {
141         if (argv[i][0]=='-') {
142             switch (argv[i][1]) {
143             case 't':
144                 loopTimes = atoi(argv[++i]);
145                 break;
146             case 'c':
147                 numChunks = atoi(argv[++i]);
148                 break;
149             case 'm':
150                 runningMode = atoi(argv[++i]);
151                 break;
152             case 'a':
153                 totalElems = atoi(argv[++i]);
154                 break;
155             case 'p':
156                 threadNum = atoi(argv[++i]);
157                 break;
158             }
159         }
160     }
161 }
162
163
164 TestInstance::TestInstance() {
165     CkPrintf("test case %d is created on proc %d node %d\n", thisIndex, CkMyPe(),CkMyNode());
166     
167         hasTest = 0; 
168         allTimes = new double[loopTimes];
169         allResults = new int[loopTimes];
170         memset(allTimes, 0, sizeof(double)*loopTimes);
171         memset(allResults, 0, sizeof(int)*loopTimes);
172 }
173
174 void TestInstance::doTest(int curstep) {
175     //printf("On proc %d node %d, begin parallel execution for test case %d %dth iteration\n", CkMyPe(), CkMyNode(), thisIndex,flag);
176         hasTest = 1;
177     double timerec = CmiWallTimer();
178         int result;
179         
180         NodeHelper_Parallelize(nodeHelperProxy, doCalc, 0, NULL, 0, numChunks, 0, loopTimes-1, &result, NODEHELPER_INT_SUM);
181     allTimes[curstep]=(CmiWallTimer()-timerec)*1e6;
182         allResults[curstep] = result;
183         
184     mainProxy.done();
185 }
186
187 void TestInstance::reportSts(){
188         if(hasTest){
189                 //do sts output
190                 qsort(allTimes, TEST_REPEAT_TIMES, sizeof(double), cmpDFunc);
191                 double sum = 0.0;
192                 for(int i=0; i<TEST_REPEAT_TIMES-3; i++) sum += allTimes[i];
193                 
194                 double avgResult = 0.0;
195                 for(int i=0; i<TEST_REPEAT_TIMES; i++) avgResult += allResults[i];
196                 avgResult /= TEST_REPEAT_TIMES;
197                 
198                 int maxi = TEST_REPEAT_TIMES;
199                 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]);
200         }
201         
202         if(thisIndex == totalElems-1) mainProxy.exitTest();
203         else thisProxy[thisIndex+1].reportSts();
204 }
205
206 #include "hello.def.h"
207