start of new file
[IRC.git] / Robust / src / Benchmarks / Prefetch / Em3d / dsm / Em3dN.java
1 /** 
2  *
3  *
4  * Java implementation of the <tt>em3d</tt> Olden benchmark.  This Olden
5  * benchmark models the propagation of electromagnetic waves through
6  * objects in 3 dimensions. It is a simple computation on an irregular
7  * bipartite graph containing nodes representing electric and magnetic
8  * field values.
9  *
10  * <p><cite>
11  * D. Culler, A. Dusseau, S. Goldstein, A. Krishnamurthy, S. Lumetta, T. von 
12  * Eicken and K. Yelick. "Parallel Programming in Split-C".  Supercomputing
13  * 1993, pages 262-273.
14  * </cite>
15  **/
16 public class Em3d extends Thread
17 {
18
19   /**
20    * The number of nodes (E and H) 
21    **/
22   private int numNodes;
23   /**
24    * The out-degree of each node.
25    **/
26   private int numDegree;
27   /**
28    * The number of compute iterations 
29    **/
30   private int numIter;
31   /**
32    * Should we print the results and other runtime messages
33    **/
34   private boolean printResult;
35   /**
36    * Print information messages?
37    **/
38   private boolean printMsgs;
39
40     int numThreads;
41
42   BiGraph bg;
43   int upperlimit;
44   int lowerlimit;
45   Barrier mybarr;
46
47   Random r;
48
49   // yipes! static members are not supported so
50   // using the following constants:
51   // runMode == 1 is RUNMODE_ALLOC
52   // runMode == 2 is RUNMODE_NEIGHBORS
53   // runMode == 3 is RUNMODE_MAKEFROM
54   // runMode == 4 is RUNMODE_FROMLINKS
55   // runMode == 5 is RUNMODE_WORK
56   int runMode;
57
58
59   public Em3d() {
60     numNodes = 0;
61     numDegree = 0;
62     numIter = 1;
63     printResult = false;
64     printMsgs = false;
65     runMode = 0;
66   }
67
68   public Em3d(BiGraph bg, int lowerlimit, int upperlimit, int numIter, Barrier mybarr, int numDegree, Random r, int runMode) {
69     this.bg = bg;
70     this.lowerlimit = lowerlimit;
71     this.upperlimit = upperlimit;
72     this.numIter = numIter;
73     this.mybarr = mybarr;
74     this.runMode = runMode;
75     this.numDegree = numDegree;
76     this.r = r;
77   }
78
79   public void run() {
80     int iteration;
81     Barrier barr;
82     int degree;
83     Random random;
84     int mode;
85
86     atomic {
87       iteration = numIter;
88       barr=mybarr;
89       degree = numDegree;
90       random = r;
91       mode = runMode;
92     }
93
94     if( mode == 1 ) {
95         atomic {
96             bg.allocate( lowerlimit, upperlimit, degree, r );
97         }
98         Barrier.enterBarrier(barr);
99         System.clearPrefetchCache();
100
101     } else if( mode == 2 ) {
102         atomic {
103             bg.makeNeighbors( lowerlimit, upperlimit, r );
104         }
105         Barrier.enterBarrier(barr);
106         System.clearPrefetchCache();
107
108     } else if( mode == 3 ) {
109         atomic {
110             bg.makeFromNodes( lowerlimit, upperlimit );
111         }
112         Barrier.enterBarrier(barr);
113         System.clearPrefetchCache();
114
115     } else if( mode == 4 ) {
116         atomic {
117             bg.makeFromLinks( lowerlimit, upperlimit, r );
118         }
119         Barrier.enterBarrier(barr);
120         System.clearPrefetchCache();
121
122     } else if( mode == 5 ) {
123
124         for (int i = 0; i < iteration; i++) {
125             /* for  eNodes */
126             atomic {
127                 for(int j = lowerlimit; j<upperlimit; j++) {
128                     Node n = bg.eNodes[j];
129                     
130                     for (int k = 0; k < n.fromCount; k++) {
131                         n.value -= n.coeffs[k] * n.fromNodes[k].value;
132                     }
133                 }
134             }
135             
136             Barrier.enterBarrier(barr);
137             System.clearPrefetchCache();
138             
139             /* for  hNodes */
140             atomic {
141                 for(int j = lowerlimit; j<upperlimit; j++) {
142                     Node n = bg.hNodes[j];
143                     for (int k = 0; k < n.fromCount; k++) {
144                         n.value -= n.coeffs[k] * n.fromNodes[k].value;
145                     }
146                 }
147             }
148             Barrier.enterBarrier(barr);
149             System.clearPrefetchCache();
150         }
151         
152     }
153   }
154
155   /**
156    * The main roitine that creates the irregular, linked data structure
157    * that represents the electric and magnetic fields and propagates the
158    * waves through the graph.
159    * @param args the command line arguments
160    **/
161   public static void main(String args[]) {
162     Em3d em = new Em3d();
163     Em3d.parseCmdLine(args, em);
164     if (em.printMsgs) 
165       System.printString("Initializing em3d random graph...\n");
166     long start0 = System.currentTimeMillis();
167     int numThreads = em.numThreads;
168     int[] mid = new int[4];
169     mid[0] = (128<<24)|(195<<16)|(175<<8)|79;//dw-1
170     mid[1] = (128<<24)|(195<<16)|(175<<8)|80;//dw-2
171     mid[2] = (128<<24)|(195<<16)|(175<<8)|73;
172     mid[3] = (128<<24)|(195<<16)|(175<<8)|78;
173     System.printString("DEBUG -> numThreads = " + numThreads+"\n");
174     Barrier mybarr;
175     BiGraph graph;
176     Random rand;
177
178     
179     // initialization step 1: allocate BiGraph
180    // System.printString( "Allocating BiGraph.\n" );
181
182     atomic {
183       mybarr = global new Barrier(numThreads);
184       rand = global new Random(783);
185       graph =  BiGraph.create(em.numNodes, em.numDegree, em.printResult, rand);
186     }
187
188     Em3d[] em3d;    
189     Em3d tmp;
190     int base;
191     int increment;
192
193
194         increment = em.numNodes/numThreads;
195
196
197     // initialization step 2: divide work of allocating nodes
198    // System.printString( "Launching distributed allocation of nodes.\n" );
199
200     atomic {
201       em3d = global new Em3d[numThreads];
202       base=0;
203       for(int i=0;i<numThreads;i++) {
204           if ((i+1)==numThreads)
205               em3d[i] = global new Em3d(graph, base, em.numNodes, em.numIter, mybarr, em.numDegree, rand, 1);
206           else
207               em3d[i] = global new Em3d(graph, base, base+increment, em.numIter, mybarr, em.numDegree, rand, 1);
208           base+=increment;
209       }
210     }
211
212     for(int i = 0; i<numThreads; i++) {
213       atomic {
214         tmp = em3d[i];
215       }
216       tmp.start(mid[i]);
217     }
218
219     for(int i = 0; i<numThreads; i++) {
220       atomic { 
221         tmp = em3d[i];
222       }
223       tmp.join();
224     }
225
226     // initialization step 3: link together the ends of segments
227     // that were allocated and internally linked in step 2
228     // System.printString( "Linking together allocated segments.\n" );
229
230     base = 0;
231     for(int i = 0; i < numThreads - 1; i++) {
232         atomic {
233             graph.linkSegments( base + increment );
234             base += increment;              
235         }
236     }    
237
238     // initialization step 4: divide work of making links
239    // System.printString( "Launching distributed neighbor initialization.\n" );
240
241     atomic {
242       em3d = global new Em3d[numThreads];
243       base=0;
244       for(int i=0;i<numThreads;i++) {
245           if ((i+1)==numThreads)
246               em3d[i] = global new Em3d(graph, base, em.numNodes, em.numIter, mybarr, em.numDegree, rand, 2);
247           else
248               em3d[i] = global new Em3d(graph, base, base+increment, em.numIter, mybarr, em.numDegree, rand, 2);
249           base+=increment;
250       }
251     }
252
253     for(int i = 0; i<numThreads; i++) {
254       atomic {
255         tmp = em3d[i];
256       }
257       tmp.start(mid[i]);
258     }
259
260     for(int i = 0; i<numThreads; i++) {
261       atomic { 
262         tmp = em3d[i];
263       }
264       tmp.join();
265     }
266
267     // initialization step 5: divide work of making from links
268     //System.printString( "Launching distributed makeFromNodes initialization.\n" );
269
270     atomic {
271       em3d = global new Em3d[numThreads];
272       base=0;
273       for(int i=0;i<numThreads;i++) {
274           if ((i+1)==numThreads)
275               em3d[i] = global new Em3d(graph, base, em.numNodes, em.numIter, mybarr, em.numDegree, rand, 3);
276           else
277               em3d[i] = global new Em3d(graph, base, base+increment, em.numIter, mybarr, em.numDegree, rand, 3);
278           base+=increment;
279       }
280     }
281
282     for(int i = 0; i<numThreads; i++) {
283       atomic {
284         tmp = em3d[i];
285       }
286       tmp.start(mid[i]);
287     }
288
289     for(int i = 0; i<numThreads; i++) {
290       atomic { 
291         tmp = em3d[i];
292       }
293       tmp.join();
294     }
295
296     // initialization step 6: divide work of making from links
297     //System.printString( "Launching distributed fromLink initialization.\n" );
298
299     atomic {
300       em3d = global new Em3d[numThreads];
301       base=0;
302       for(int i=0;i<numThreads;i++) {
303           if ((i+1)==numThreads)
304               em3d[i] = global new Em3d(graph, base, em.numNodes, em.numIter, mybarr, em.numDegree, rand, 4);
305           else
306               em3d[i] = global new Em3d(graph, base, base+increment, em.numIter, mybarr, em.numDegree, rand, 4);
307           base+=increment;
308       }
309     }
310
311     for(int i = 0; i<numThreads; i++) {
312       atomic {
313         tmp = em3d[i];
314       }
315       tmp.start(mid[i]);
316     }
317
318     for(int i = 0; i<numThreads; i++) {
319       atomic { 
320         tmp = em3d[i];
321       }
322       tmp.join();
323     }
324
325     // initialization complete
326     //System.printString( "Initialization complete.\n" );
327
328     long end0 = System.currentTimeMillis();
329
330
331     // compute a single iteration of electro-magnetic propagation
332     if (em.printMsgs) 
333       System.printString("Propagating field values for " + em.numIter + 
334           " iteration(s)...\n");
335     long start1 = System.currentTimeMillis();
336
337     atomic {
338       em3d = global new Em3d[numThreads];
339       base=0;
340       for(int i=0;i<numThreads;i++) {
341           if ((i+1)==numThreads)
342               em3d[i] = global new Em3d(graph, base, em.numNodes, em.numIter, mybarr, em.numDegree, rand, 5);
343           else
344               em3d[i] = global new Em3d(graph, base, base+increment, em.numIter, mybarr, em.numDegree, rand, 5);
345           base+=increment;
346       }
347     }
348
349     for(int i = 0; i<numThreads; i++) {
350       atomic {
351         tmp = em3d[i];
352       }
353       tmp.start(mid[i]);
354     }
355
356     for(int i = 0; i<numThreads; i++) {
357       atomic { 
358         tmp = em3d[i];
359       }
360       tmp.join();
361     }
362     long end1 = System.currentTimeMillis();
363
364     // print current field values
365     if (em.printResult) {
366       StringBuffer retval = new StringBuffer();
367       double dvalue;
368       atomic {
369         dvalue = graph.hNodes[0].value;
370       }
371       int intvalue = (int)dvalue;
372     }
373
374     if (em.printMsgs) {
375       System.printString("EM3D build time "+ (long)((end0 - start0)/1000.0) + "\n");
376       System.printString("EM3D compute time " + (long)((end1 - start1)/1000.0) + "\n");
377       System.printString("EM3D total time " + (long)((end1 - start0)/1000.0) + "\n");
378     }
379     System.printString("Done!"+ "\n");
380   }
381
382
383   /**
384    * Parse the command line options.
385    * @param args the command line options.
386    **/
387
388   public static void parseCmdLine(String args[], Em3d em)
389   {
390     int i = 0;
391     String arg;
392
393     while (i < args.length && args[i].startsWith("-")) {
394       arg = args[i++];
395
396       // check for options that require arguments
397       if (arg.equals("-N")) {
398         if (i < args.length) {
399                 em.numNodes = new Integer(args[i++]).intValue();
400         }
401       } else if (arg.equals("-T")) {
402         if (i < args.length) {
403                 em.numThreads = new Integer(args[i++]).intValue();
404         }
405       } else if (arg.equals("-d")) {
406         if (i < args.length) {
407                 em.numDegree = new Integer(args[i++]).intValue();
408         }
409       } else if (arg.equals("-i")) {
410         if (i < args.length) {
411             em.numIter = new Integer(args[i++]).intValue();
412         }
413       } else if (arg.equals("-p")) {
414               em.printResult = true;
415       } else if (arg.equals("-m")) {
416               em.printMsgs = true;
417       } else if (arg.equals("-h")) {
418         em.usage();
419       }
420     }
421
422     if (em.numNodes == 0 || em.numDegree == 0) 
423       em.usage();
424   }
425
426   /**
427    * The usage routine which describes the program options.
428    **/
429   public void usage()
430   {
431     System.printString("usage: java Em3d -T <threads> -N <nodes> -d <degree> [-p] [-m] [-h]\n");
432     System.printString("    -N the number of nodes\n");
433     System.printString("    -T the number of threads\n");
434     System.printString("    -d the out-degree of each node\n");
435     System.printString("    -i the number of iterations\n");
436     System.printString("    -p (print detailed results\n)");
437     System.printString("    -m (print informative messages)\n");
438     System.printString("    -h (this message)\n");
439   }
440
441 }