Polished/Updated the library and changed the example codes accordingly.
[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         starttime = CmiWallTimer();
90         for(int i=0; i<5; i++) work(0, loopTimes, &result);
91         endtime = CmiWallTimer();
92         double avgtime = (endtime-starttime)*1e6/5; //in the unit of us
93         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));
94                 
95     CmiSetCPUAffinity(0);
96     CkStartQD(CkIndex_Main::doTests((CkQdMsg *)0), &thishandle);
97 };
98
99 void Main::done(void) {
100     numElemFinished++;
101     if (numElemFinished < totalElems) {
102         return;
103     } else {
104                 mainTimes[mainStep] = (CmiWallTimer() - timestamp)*1e6;
105         mainStep++;
106         numElemFinished=0;
107         if (mainStep < TEST_REPEAT_TIMES) {
108                         doTests(NULL);
109             return;
110         }
111     }   
112         //do some final output
113         allTestsProxy[0].reportSts();
114 };
115
116 void Main::exitTest(){
117         //do some final output
118         qsort(mainTimes, TEST_REPEAT_TIMES, sizeof(double), cmpDFunc);
119         double sum = 0.0;
120         for(int i=0; i<TEST_REPEAT_TIMES; i++) sum += mainTimes[i];
121         int maxi = TEST_REPEAT_TIMES;
122         CkPrintf("Global timestep info: avg time: %.3f [%.3f, %.3f, %.3f] (us)\n", sum/(maxi-3), mainTimes[0], mainTimes[maxi/2], mainTimes[maxi-1]);
123         
124         CkPrintf("All done\n");
125         CkExit();
126 }
127
128 void Main::doTests(CkQdMsg *msg) {
129     delete msg;
130     
131         timestamp = CmiWallTimer(); //record the start time of the whole test
132     for (int i=0; i<totalElems; i++) {
133         allTestsProxy[i].doTest(mainStep);
134         //allTestsProxy[8].doTest(mainStep);
135     }
136 };
137
138 void Main::processCommandLine(int argc,char ** argv) {
139     for (int i=0; i<argc; i++) {
140         if (argv[i][0]=='-') {
141             switch (argv[i][1]) {
142             case 't':
143                 loopTimes = atoi(argv[++i]);
144                 break;
145             case 'c':
146                 numChunks = atoi(argv[++i]);
147                 break;
148             case 'm':
149                 runningMode = atoi(argv[++i]);
150                 break;
151             case 'a':
152                 totalElems = atoi(argv[++i]);
153                 break;
154             case 'p':
155                 threadNum = atoi(argv[++i]);
156                 break;
157             }
158         }
159     }
160 }
161
162
163 TestInstance::TestInstance() {
164     CkPrintf("test case %d is created on proc %d node %d\n", thisIndex, CkMyPe(),CkMyNode());
165     
166         hasTest = 0; 
167         allTimes = new double[loopTimes];
168         allResults = new int[loopTimes];
169         memset(allTimes, 0, sizeof(double)*loopTimes);
170         memset(allResults, 0, sizeof(int)*loopTimes);
171 }
172
173 void TestInstance::doTest(int curstep) {
174     //printf("On proc %d node %d, begin parallel execution for test case %d %dth iteration\n", CkMyPe(), CkMyNode(), thisIndex,flag);
175         hasTest = 1;
176     double timerec = CmiWallTimer();
177         int result;
178         
179         NodeHelper_Parallelize(nodeHelperProxy, doCalc, 0, NULL, 0, numChunks, 0, loopTimes-1, &result, NODEHELPER_INT_SUM);
180     allTimes[curstep]=(CmiWallTimer()-timerec)*1e6;
181         allResults[curstep] = result;
182         
183     mainProxy.done();
184 }
185
186 void TestInstance::reportSts(){
187         if(hasTest){
188                 //do sts output
189                 qsort(allTimes, TEST_REPEAT_TIMES, sizeof(double), cmpDFunc);
190                 double sum = 0.0;
191                 for(int i=0; i<TEST_REPEAT_TIMES; i++) sum += allTimes[i];
192                 
193                 double avgResult = 0.0;
194                 for(int i=0; i<TEST_REPEAT_TIMES; i++) avgResult += allResults[i];
195                 avgResult /= TEST_REPEAT_TIMES;
196                 
197                 int maxi = TEST_REPEAT_TIMES;
198                 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]);
199         }
200         
201         if(thisIndex == totalElems-1) mainProxy.exitTest();
202         else thisProxy[thisIndex+1].reportSts();
203 }
204
205 #include "hello.def.h"
206