Adding performance benchmarks for CmiReduce and Broadcast in commbench
[charm.git] / tests / converse / commbench / memoryAccess.c
1 /***************************************************************************
2  *
3  *  Benchmark to measure performnce of CmiAlloc/CmiFree and traversals
4  *  of associated memory
5  *
6  *  Two types of benchmarking has been done-
7  *
8  *  1. A flurry of operations of same type and on same size
9  *
10  *  2. A random but commuatatively organized  mix of operations on a range
11  *     of data size.
12  *
13  *  Author- Nikhil Jain
14  *
15  ***************************************************************************/
16
17 #include <converse.h>
18 #include "commbench.h"
19
20 #define CLUBMALLOC 1000
21 #define RANDMALLOC 1000
22 #define RANDOPS 1000
23 #define POWER 15
24 #define MAXSIZE 16384
25 typedef double myType;
26 myType value = 10;
27 int dist[] = {1,5,9,10};
28
29 CpvStaticDeclare(int, memoryIdx);
30
31 double memoryTest(){
32   double starttime, endtime;  
33   double extraOverhead;
34   myType **ptrs = NULL;
35   int i,j,k,size;
36   myType sums[200];
37   double times[POWER][4];
38   int sizes[RANDMALLOC];
39   int ops[RANDOPS][3];
40
41   ptrs = (myType **)malloc(CLUBMALLOC*sizeof(myType *));
42   for(i=0; i<CLUBMALLOC; i++) ptrs[i] = 0;
43   starttime = CmiWallTimer();
44   for(i=0; i<CLUBMALLOC; i++) ptrs[i] = (myType *)0xabcd;
45   endtime = CmiWallTimer();
46   extraOverhead = endtime - starttime;
47   
48   size = 1;
49   for(i = 0; i < POWER; i++,size*=2) {
50
51     for(j=0; j<CLUBMALLOC; j++) ptrs[j] = 0;
52     starttime = CmiWallTimer();
53     for(j=0; j<CLUBMALLOC; j++) {
54       ptrs[j] = (myType *)CmiAlloc(size*sizeof(myType));
55     }
56     endtime = CmiWallTimer();
57     times[i][0] = endtime - starttime - extraOverhead;
58     
59     for(j=0; j<CLUBMALLOC; j++) {
60       for(k = 0; k < size; k++) {
61         ptrs[j][k] = value;
62       }
63     }
64
65     starttime = CmiWallTimer();
66     for(j=0; j<CLUBMALLOC; j++) {
67       for(k = 0; k < size; k++) {
68         ptrs[j][k] = value;
69       }
70     }
71     endtime = CmiWallTimer();
72     times[i][1] = endtime - starttime - extraOverhead;
73
74     for(j = 0; j < 200; j++) {
75       sums[j] = 0;
76     }
77
78     starttime = CmiWallTimer();
79     for(j=0; j<CLUBMALLOC; j++) {
80       for(k = 0; k < size; k++) {
81         sums[k%200] += ptrs[j][k];
82       }
83     }
84     endtime = CmiWallTimer();
85     times[i][2] = endtime - starttime - extraOverhead;
86
87     starttime = CmiWallTimer();
88     for(j=0; j<CLUBMALLOC; j++) CmiFree(ptrs[j]);
89     endtime = CmiWallTimer();
90     times[i][3] = endtime - starttime - extraOverhead;
91   }
92
93   if(CmiMyPe()==0){
94     CmiPrintf("Performance number of clubbed malloc-traversal-free\n");
95     CmiPrintf("Size\tIterations\tMalloc\tWrite\tRead\tFree\n");
96     size = 1;
97     for(i = 0; i < POWER; i++,size*=2) {
98       CmiPrintf("%d\t%d\t%E\t%E\t%E\t%E\n",size,CLUBMALLOC,times[i][0],
99                times[i][1],times[i][2],times[i][3]);
100     }
101   }
102
103   free(ptrs);
104   ptrs = (myType **)malloc(RANDMALLOC*sizeof(myType *));
105
106   srand(7187);
107   for(i=0; i<RANDMALLOC; i++) {
108     sizes[i] = rand() % MAXSIZE;
109   }
110
111   for(i=0; i<RANDMALLOC; i++) {
112       ptrs[i] = (myType *)CmiAlloc(sizes[i]*sizeof(myType));
113   }
114
115   for(i=0; i<RANDOPS; i++) {
116     ops[i][0] = rand()%RANDMALLOC;
117     ops[i][1] = rand()%dist[3];
118     if(ops[i][1] < dist[0]) {
119       ops[i][1] = 0;
120       ops[i][2] =rand()%MAXSIZE;
121     } else if(ops[i][1] < dist[1]) {
122       ops[i][1] = 1;
123       ops[i][2] = sizes[ops[i][0]];
124     } if(ops[i][1] < dist[2]) {
125       ops[i][1] = 2;
126       ops[i][2] = sizes[ops[i][0]];
127     } else {
128       ops[i][1] = 3;
129     }
130   }
131
132   starttime = CmiWallTimer();
133   for(i=0; i<RANDOPS; i++) {
134     switch(ops[i][1]) {
135       case 0:
136         if(ptrs[ops[i][0]] != NULL)
137           CmiFree(ptrs[ops[i][0]]);
138         ptrs[ops[i][0]] = (myType *)CmiAlloc(ops[i][2]*sizeof(myType));
139         break;
140       case 1:
141         if(ptrs[ops[i][0]] == NULL)
142           ptrs[ops[i][0]] = (myType *)CmiAlloc(ops[i][2]*sizeof(myType));
143         for(j = 0; j < ops[i][2]; j++) {
144           ptrs[ops[i][0]][j] = value;
145         }
146         break;
147      case 2:
148         if(ptrs[ops[i][0]] == NULL)
149           ptrs[ops[i][0]] = (myType *)CmiAlloc(ops[i][2]*sizeof(myType));
150         for(j = 0; j < ops[i][2]; j++) {
151           sums[k%200] += ptrs[ops[i][0]][j];
152         }
153         break;
154     case 3:
155       if(ptrs[ops[i][0]] != NULL){
156         CmiFree(ptrs[ops[i][0]]);
157         ptrs[ops[i][0]] = NULL;
158       }
159     }
160   }
161   endtime = CmiWallTimer();
162
163   if(CmiMyPe()==0){
164     CmiPrintf("Time taken by random malloc-traversal-free benchmark with following commutative distribution: malloc %d, write %d, read %d, free %d, max malloc size %d, length of table %d, number of ops %d is %E.\n",dist[0],dist[1],dist[2],dist[3],MAXSIZE,RANDMALLOC,RANDOPS, (endtime-starttime));
165   }
166
167   for(i=0; i<RANDMALLOC; i++) {
168     if(ptrs[i] != NULL)
169       CmiFree(ptrs[i]);
170   }
171   free(ptrs);
172 }
173
174 static void memoryHandler(EmptyMsg *msg){
175         /* Make sure the memory contention on a node happens roughly at the same time */
176         CmiNodeBarrier();
177         memoryTest();   
178         CmiNodeBarrier();
179         
180         if(CmiMyPe()==0){
181     CmiSetHandler(msg, CpvAccess(ack_handler));
182     CmiSyncSend(0, sizeof(EmptyMsg), msg);
183         }
184         else {
185           CmiFree(msg);
186         }
187 }
188
189 void memoryAccess_init(void)
190 {
191   EmptyMsg msg;
192
193   CmiPrintf("Single core malloc/free/traversal performance numbers\n");
194   memoryTest();
195              
196   CmiPrintf("Multi core malloc/free/traversal performance numbers\n");
197   CmiSetHandler(&msg, CpvAccess(memoryIdx));
198   CmiSyncBroadcastAll(sizeof(EmptyMsg), &msg);
199 }
200
201 void memoryAccess_moduleinit(void)
202 {
203   CpvInitialize(int, memoryIdx);
204   CpvAccess(memoryIdx) = CmiRegisterHandler((CmiHandler)memoryHandler);
205 }
206