4a8ae48e4d70b1573b49ad91256d4fbc68d59a42
[charm.git] / examples / bigsim / emulator / prime.C
1 #include <stdlib.h>
2 #include "blue.h"
3
4 int computeNumPrimeID;
5 int contributeID;
6 int reduceID;
7
8 extern "C" void reduce(char *) ;
9 extern "C" void computeNumPrime(char *) ;
10 extern "C" void contribute(char *) ;
11
12 class Msg
13 {
14 public:
15   char core[CmiBlueGeneMsgHeaderSizeBytes];
16   int pc;       //number of primes
17   int min, max; //range of numbers
18   void *operator new(size_t s) { return CmiAlloc(s); }
19   void operator delete(void* ptr) { CmiFree(ptr); }
20 };
21
22 BnvStaticDeclare(int, pc);
23 BnvStaticDeclare(int, count);
24
25 void BgEmulatorInit(int argc, char **argv)
26 {
27   if (argc < 7) { 
28     CmiPrintf("Usage: <program> <x> <y> <z> <numCommTh> <numWorkTh> <range>\n");
29     BgShutdown();
30   }
31
32   BgSetSize(atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
33   BgSetNumCommThread(atoi(argv[4]));
34   BgSetNumWorkThread(atoi(argv[5]));
35
36 }
37
38 void BgNodeStart(int argc, char **argv) 
39 {
40   reduceID = BgRegisterHandler(reduce);
41   computeNumPrimeID = BgRegisterHandler(computeNumPrime);
42   contributeID = BgRegisterHandler(contribute);
43
44   int x,y,z;
45   BgGetMyXYZ(&x, &y, &z);
46
47   //CmiPrintf("BgNodeStart in %d %d %d\n", x,y,z);
48
49   //declare node private data
50   BnvInitialize(int, pc);
51   BnvInitialize(int, count);
52   BnvAccess(count) = 0;
53   BnvAccess(pc)    = 0;
54   const int RANGE = atoi(argv[6]); 
55
56   //Decide range of number for this node
57   int min, max;
58   int numBgX, numBgY, numBgZ;
59   BgGetSize(&numBgX, &numBgY, &numBgZ);
60   int slot = RANGE/(numBgX * numBgY * numBgZ);
61   if(0==slot) { slot = 1; }
62
63   min = slot*(x*numBgY*numBgZ + y*numBgZ + z);
64   max = min + slot;
65
66   if(x==numBgX-1 &&
67      y==numBgZ-1 &&
68      z==numBgY-1) 
69        max = RANGE;     
70
71   if(max>RANGE)  { max = RANGE; }
72   if(min>=RANGE) { min=max=0; }
73
74   //ckout << "Range for node " <<x<< ", " <<y<< ", " <<z<< " is " << min <<", "<< max << endl;
75
76   //Divide range to each worker thread and Fire....
77   int numWTh = BgGetNumWorkThread();
78   if(max-min>0)
79   {
80         int numWTh = BgGetNumWorkThread();
81
82         slot = slot/numWTh;
83         if(0==slot) { slot = 1; }
84
85         for(int i=0; i<numWTh; i++)
86         {       
87           Msg *msg = new Msg;
88           msg->min = min + i*slot;
89           msg->max = msg->min + slot;
90
91           if(i==numWTh-1)
92                 msg->max = max;
93
94           if(msg->max>max) { msg->max=max; }                    
95           if(msg->min>=max) { msg->min=msg->max=0; }                    
96
97           BgSendLocalPacket(ANYTHREAD,computeNumPrimeID, LARGE_WORK, sizeof(Msg), (char *)msg);
98
99         }
100   }
101   else
102   {
103         for(int i=0; i<numWTh; i++)
104         {
105           Msg *msg = new Msg;
106           msg->min=msg->max=0;
107           BgSendLocalPacket(ANYTHREAD,computeNumPrimeID, LARGE_WORK, sizeof(Msg), (char *)msg);
108         }
109   }
110
111 }
112
113
114 /* Utility: isPrime
115  * Checks whether a given number is prime or not
116  * Assumption: Any number<=1 is not prime
117  */
118 int isPrime(const int number)
119 {
120   if(number<=1) return 0;
121
122   for(int i=2; i<number; i++)
123   {
124         if(0 == number%i)
125           return 0;
126   }
127
128   return 1;
129 }
130
131 /* Utility: computeNumberOfPrimesIn
132  * Computes number of prime number in a given range
133  */
134 int computeNumberOfPrimesIn(const int min, const int max)       
135 {
136   int count=0;
137   for(int i=min; i<max; i++)
138   {
139      if(isPrime(i))
140      {
141         count++;
142         //ckout << i << " is prime"<< endl;
143      }
144      else
145         //ckout << i << " is not prime"<< endl;
146         ;
147   }
148
149   return count;
150 }
151
152
153 /* Handler: computeNumPrime
154  * Compute the number of primes in the assigned range and contribute
155  */
156 void computeNumPrime(char *info) 
157 {
158   int x,y,z;
159   BgGetMyXYZ(&x,&y,&z);
160   //CmiPrintf("computeNumPrime in %d %d %d\n", x,y,z);
161
162   Msg *msg = (Msg*)info;
163
164   //compute number of primes in the assigned range of numbers
165   int min = msg->min;
166   int max = msg->max;
167   int pc = computeNumberOfPrimesIn(min, max);
168
169   // contribute the results for reduction : reusing the same message for optimization
170   msg->pc = pc;
171   BgSendLocalPacket(ANYTHREAD,contributeID,LARGE_WORK, sizeof(Msg), (char *)msg);
172 }
173
174 /* Handler: contribute
175  * If the number of contributions received is equal to expected number
176  *    call the reduction handler
177  * Else contribute the contribution to node private data and update counter
178  */
179 void contribute(char *info)
180 {
181   int x,y,z;
182   BgGetMyXYZ(&x,&y,&z);
183   //ckout << "contribute in " << x << ", " << y << ", " << z << endl ;
184
185   BnvAccess(pc) += ((Msg*)info)->pc;
186   BnvAccess(count)++;
187
188   //compute expected contributions
189   //more: This computation need not be repeated everytime. Change it after this pgm works
190   int reqCount ;
191   int numBgX, numBgY, numBgZ;
192   BgGetSize(&numBgX, &numBgY, &numBgZ);
193   if(z==numBgZ-1)
194     reqCount = 0 ;  
195   else if(z>0 || (z==0 && x==numBgX-1))
196     reqCount = 1 ;
197   else if(x>0 || (x==0 && y==numBgY-1))
198     reqCount = 2 ;  
199   else
200     reqCount = 3 ;
201
202   reqCount += BgGetNumWorkThread();
203
204   if(BnvAccess(count)==reqCount)  //if data for reduction is ready
205   {
206     Msg *msg = (Msg*)info ;
207     msg->pc = BnvAccess(pc);
208     BgSendLocalPacket(ANYTHREAD,reduceID, LARGE_WORK, sizeof(Msg), (char *)msg);
209     return ;
210   }
211   else
212     delete (Msg*)info;
213 }
214
215 /* Handler: reduce
216  * If reduction has finished, print the number of primes
217  * Else send the number of primes to next node in reduction sequence
218  */
219 void reduce(char *info) 
220 {
221   int pc = BnvAccess(pc);
222
223   int x,y,z;
224   BgGetMyXYZ(&x,&y,&z);
225   //ckout << "reduce in " << x << ", " << y << ", " << z 
226   //      << " number of primes " << pc << endl;
227
228   if(x==0 && y==0 && z==0)
229   {
230   delete (Msg*)info;
231   CmiPrintf("Finished : The number of primes is %d\n",pc);
232   CmiPrintf("Emulation Time : %f seconds\n", BgGetTime());
233   BgShutdown();
234   return;
235   }
236   //send pc to destination(decide) 
237   if(z>0)
238     z--;   
239   else if(x>0)
240     x--;
241   else
242     y--;
243
244   Msg *msg = (Msg*)info;
245   msg->pc = pc;
246   BgSendPacket(x,y,z, ANYTHREAD,contributeID, LARGE_WORK, sizeof(Msg), (char *)msg);
247 }
248