From 30d93ea4d6aa19f9729b3285e5aa811e834127b8 Mon Sep 17 00:00:00 2001 From: adash <adash> Date: Sun, 13 Apr 2008 04:40:23 +0000 Subject: [PATCH] java version of Em3d benchmark --- .../Benchmarks/Prefetch/Em3d/dsm/Barrier.java | 6 +- .../Prefetch/Em3d/java/Barrier.java | 52 +++++ .../Prefetch/Em3d/java/BiGraph.java | 132 +++++++++++ .../Benchmarks/Prefetch/Em3d/java/Em3d.java | 211 ++++++++++++++++++ .../Benchmarks/Prefetch/Em3d/java/Node.java | 210 +++++++++++++++++ .../Benchmarks/Prefetch/Em3d/java/makefile | 7 + 6 files changed, 616 insertions(+), 2 deletions(-) create mode 100644 Robust/src/Benchmarks/Prefetch/Em3d/java/Barrier.java create mode 100644 Robust/src/Benchmarks/Prefetch/Em3d/java/BiGraph.java create mode 100644 Robust/src/Benchmarks/Prefetch/Em3d/java/Em3d.java create mode 100644 Robust/src/Benchmarks/Prefetch/Em3d/java/Node.java create mode 100644 Robust/src/Benchmarks/Prefetch/Em3d/java/makefile diff --git a/Robust/src/Benchmarks/Prefetch/Em3d/dsm/Barrier.java b/Robust/src/Benchmarks/Prefetch/Em3d/dsm/Barrier.java index 482b695a..2f0f05dd 100644 --- a/Robust/src/Benchmarks/Prefetch/Em3d/dsm/Barrier.java +++ b/Robust/src/Benchmarks/Prefetch/Em3d/dsm/Barrier.java @@ -21,14 +21,16 @@ public class Barrier { int tmp; boolean retry=true; + if(b.numthreads == 1) + return; + do { atomic { if (!b.cleared) { b.entercount++; tmp = b.entercount; if (tmp==b.numthreads) { - if(b.numthreads > 1) - b.cleared=true; + b.cleared=true; b.entercount--; return; } diff --git a/Robust/src/Benchmarks/Prefetch/Em3d/java/Barrier.java b/Robust/src/Benchmarks/Prefetch/Em3d/java/Barrier.java new file mode 100644 index 00000000..732c0051 --- /dev/null +++ b/Robust/src/Benchmarks/Prefetch/Em3d/java/Barrier.java @@ -0,0 +1,52 @@ +public class Barrier { + int numthreads; + int entercount; + boolean cleared; + + public Barrier(int n) { + numthreads=n; + cleared = false; + } + + public Barrier() { + + } + + public void reset() { + cleared = false; + entercount = 0; + } + + public static void enterBarrier(Barrier b) { + int tmp; + boolean retry=true; + + if (b.numthreads == 1) + return; + + do { + //System.out.println("Inside do"); + if (!b.cleared) { + b.entercount++; + tmp = b.entercount; + if (tmp==b.numthreads) { + b.cleared=true; + b.entercount--; + return; + } + retry=false; + } + } while(retry); + + while(true) { + //System.out.println("Inside while"); + if (b.cleared) { + b.entercount--; + int count = b.entercount; + if (count==0) + b.cleared=false; + return; + } + } + } +} diff --git a/Robust/src/Benchmarks/Prefetch/Em3d/java/BiGraph.java b/Robust/src/Benchmarks/Prefetch/Em3d/java/BiGraph.java new file mode 100644 index 00000000..a8a81070 --- /dev/null +++ b/Robust/src/Benchmarks/Prefetch/Em3d/java/BiGraph.java @@ -0,0 +1,132 @@ +import java.util.Random; +/** + * A class that represents the irregular bipartite graph used in + * EM3D. The graph contains two linked structures that represent the + * E nodes and the N nodes in the application. + **/ +public class BiGraph +{ + public BiGraph() { + } + /** + * Nodes that represent the electrical field. + **/ + Node eNodes; + /** + * Nodes that representhe the magnetic field. + **/ + Node hNodes; + + /** + * Construct the bipartite graph. + * @param e the nodes representing the electric fields + * @param h the nodes representing the magnetic fields + **/ + BiGraph(Node e, Node h) + { + eNodes = e; + hNodes = h; + } + + /** + * Create the bi graph that contains the linked list of + * e and h nodes. + * @param numNodes the number of nodes to create + * @param numDegree the out-degree of each node + * @param verbose should we print out runtime messages + * @return the bi graph that we've created. + **/ + + BiGraph create(int numNodes, int numDegree, boolean verbose, Random r) + { + Node newnode = new Node(); + + // making nodes (we create a table) + if (verbose) System.out.println("making nodes (tables in orig. version)"); + Node[] hTable = newnode.fillTable(numNodes, numDegree, r); + Node[] eTable = newnode.fillTable(numNodes, numDegree, r); + + // making neighbors + if (verbose) System.out.println("updating from and coeffs"); + for(int i = 0; i< numNodes; i++) { + Node n = hTable[i]; + n.makeUniqueNeighbors(eTable, r); + } + + for (int i = 0; i < numNodes; i++) { + Node n = eTable[i]; + n.makeUniqueNeighbors(hTable, r); + } + + // Create the fromNodes and coeff field + if (verbose) System.out.println("filling from fields"); + for(int i = 0; i< numNodes; i++) { + Node n = hTable[i]; + n.makeFromNodes(); + } + + for (int i = 0; i < numNodes; i++) { + Node n = eTable[i]; + n.makeFromNodes(); + } + + // Update the fromNodes + for (int i = 0; i < numNodes; i++) { + Node n = hTable[i]; + n.updateFromNodes(r); + } + for (int i = 0; i < numNodes; i++) { + Node n = eTable[i]; + n.updateFromNodes(r); + } + + BiGraph g = new BiGraph(eTable[0], hTable[0]); + return g; + } + + /** + * Update the field values of e-nodes based on the values of + * neighboring h-nodes and vice-versa. + **/ + /* + void compute() + { + Node tmp = eNodes; + while(tmp!= null) { + Node n = tmp; + n.computeNewValue(); + tmp = tmp.next; + } + tmp = hNodes; + while(tmp!=null) { + Node n = tmp; + n.computeNewValue(); + tmp = tmp.next; + } + } + */ + + /** + * Override the toString method to print out the values of the e and h nodes. + * @return a string contain the values of the e and h nodes. + **/ + public String toString() + { + StringBuffer retval = new StringBuffer(); + Node tmp = eNodes; + while(tmp!=null) { + Node n = tmp; + retval.append("E: " + n + "\n"); + tmp = tmp.next; + } + tmp = hNodes; + while(tmp!=null) { + Node n = tmp; + retval.append("H: " + n + "\n"); + tmp = tmp.next; + } + return retval.toString(); + } + +} + diff --git a/Robust/src/Benchmarks/Prefetch/Em3d/java/Em3d.java b/Robust/src/Benchmarks/Prefetch/Em3d/java/Em3d.java new file mode 100644 index 00000000..8ca449d1 --- /dev/null +++ b/Robust/src/Benchmarks/Prefetch/Em3d/java/Em3d.java @@ -0,0 +1,211 @@ +import java.io.*; +import java.util.Random; + +/** + * + * + * Java implementation of the <tt>em3d</tt> Olden benchmark. This Olden + * benchmark models the propagation of electromagnetic waves through + * objects in 3 dimensions. It is a simple computation on an irregular + * bipartite graph containing nodes representing electric and magnetic + * field values. + * + * <p><cite> + * D. Culler, A. Dusseau, S. Goldstein, A. Krishnamurthy, S. Lumetta, T. von + * Eicken and K. Yelick. "Parallel Programming in Split-C". Supercomputing + * 1993, pages 262-273. + * </cite> + **/ +public class Em3d extends Thread +{ + + BiGraph bg; + int upperlimit; + int lowerlimit; + Random rand; + Barrier mybarr; + + public Em3d() { + numNodes = 0; + numDegree = 0; + numIter = 1; + printResult = false; + printMsgs = false; + } + + public Em3d(BiGraph bg, int lowerlimit, int upperlimit, int numIter, Barrier mybarr) { + this.bg = bg; + this.lowerlimit = lowerlimit; + this.upperlimit = upperlimit; + this.numIter = numIter; + this.mybarr = mybarr; + } + + public void run() { + for (int i = 0; i < numIter; i++) { + Barrier runBarrier = new Barrier(); + /* for eNodes */ + Node prev = bg.eNodes; + Node curr = null; + for(int j = 0; j<lowerlimit; j++){ + curr = prev; + prev = prev.next; + } + for(int j = lowerlimit; j<=upperlimit; j++) { + Node n = curr; + for (int k = 0; k < n.fromCount; k++) { + n.value -= n.coeffs[k] * n.fromNodes[k].value; + } + curr = curr.next; + } + runBarrier.enterBarrier(mybarr); + //mybarr.reset(); + + /* for hNodes */ + prev = bg.hNodes; + curr = null; + for(int j = 0; j<lowerlimit; j++){ + curr = prev; + prev = prev.next; + } + for(int j = lowerlimit; j<=upperlimit; j++) { + Node n = curr; + for (int k = 0; k < n.fromCount; k++) { + n.value -= n.coeffs[k] * n.fromNodes[k].value; + } + curr = curr.next; + } + runBarrier.enterBarrier(mybarr); + //mybarr.reset(); + } + } + + /** + * The number of nodes (E and H) + **/ + private int numNodes; + /** + * The out-degree of each node. + **/ + private int numDegree; + /** + * The number of compute iterations + **/ + private int numIter; + /** + * Should we print the results and other runtime messages + **/ + private boolean printResult; + /** + * Print information messages? + **/ + private boolean printMsgs; + + /** + * The main roitine that creates the irregular, linked data structure + * that represents the electric and magnetic fields and propagates the + * waves through the graph. + * @param args the command line arguments + **/ + public static void main(String args[]) + { + Random rand = new Random(783); + Em3d em = new Em3d(); + em.parseCmdLine(args, em); + if (em.printMsgs) + System.out.println("Initializing em3d random graph..."); + long start0 = System.currentTimeMillis(); + BiGraph graph1 = new BiGraph(); + int num_threads = 2; + Barrier mybarr = new Barrier(num_threads); + System.out.println("DEBUG -> num_threads = " + num_threads); + BiGraph graph = graph1.create(em.numNodes, em.numDegree, em.printResult, rand); + + long end0 = System.currentTimeMillis(); + + // compute a single iteration of electro-magnetic propagation + if (em.printMsgs) + System.out.println("Propagating field values for " + em.numIter + + " iteration(s)..."); + long start1 = System.currentTimeMillis(); + Em3d[] em3d = new Em3d[num_threads]; + //em3d[0] = new Em3d(graph, 1, em.numNodes, em.numIter, mybarr); + em3d[0] = new Em3d(graph, 1, em.numNodes/2, em.numIter, mybarr); + em3d[1] = new Em3d(graph, (em.numNodes/2)+1, em.numNodes, em.numIter, mybarr); + for(int i = 0; i<num_threads; i++) { + em3d[i].start(); + } + for(int i = 0; i<num_threads; i++) { + try { + em3d[i].join(); + } catch (InterruptedException e) {} + } + long end1 = System.currentTimeMillis(); + + // print current field values + if (em.printResult) { + System.out.println(graph); + } + + if (em.printMsgs) { + System.out.println("EM3D build time "+ (end0 - start0)/1000.0); + System.out.println("EM3D compute time " + (end1 - start1)/1000.0); + System.out.println("EM3D total time " + (end1 - start0)/1000.0); + } + System.out.println("Done!"); + } + + + /** + * Parse the command line options. + * @param args the command line options. + **/ + + public void parseCmdLine(String args[], Em3d em) + { + int i = 0; + String arg; + + while (i < args.length && args[i].startsWith("-")) { + arg = args[i++]; + + // check for options that require arguments + if (arg.equals("-n")) { + if (i < args.length) { + em.numNodes = new Integer(args[i++]).intValue(); + } + } else if (arg.equals("-d")) { + if (i < args.length) { + em.numDegree = new Integer(args[i++]).intValue(); + } + } else if (arg.equals("-i")) { + if (i < args.length) { + em.numIter = new Integer(args[i++]).intValue(); + } + } else if (arg.equals("-p")) { + em.printResult = true; + } else if (arg.equals("-m")) { + em.printMsgs = true; + } else if (arg.equals("-h")) { + em.usage(); + } + } + if (em.numNodes == 0 || em.numDegree == 0) + em.usage(); + } + + /** + * The usage routine which describes the program options. + **/ + public void usage() + { + System.out.println("usage: java Em3d -n <nodes> -d <degree> [-p] [-m] [-h]"); + System.out.println(" -n the number of nodes"); + System.out.println(" -d the out-degree of each node"); + System.out.println(" -i the number of iterations"); + System.out.println(" -p (print detailed results)"); + System.out.println(" -m (print informative messages)"); + System.out.println(" -h (this message)"); + } + +} diff --git a/Robust/src/Benchmarks/Prefetch/Em3d/java/Node.java b/Robust/src/Benchmarks/Prefetch/Em3d/java/Node.java new file mode 100644 index 00000000..24201df6 --- /dev/null +++ b/Robust/src/Benchmarks/Prefetch/Em3d/java/Node.java @@ -0,0 +1,210 @@ +import java.util.Random; +/** + * This class implements nodes (both E- and H-nodes) of the EM graph. Sets + * up random neighbors and propagates field values among neighbors. + */ +public class Node { + /** + * The value of the node. + **/ + double value; + /** + * The next node in the list. + **/ + protected Node next; + /** + * Array of nodes to which we send our value. + **/ + Node[] toNodes; + /** + * Array of nodes from which we receive values. + **/ + Node[] fromNodes; + /** + * Coefficients on the fromNodes edges + **/ + double[] coeffs; + /** + * The number of fromNodes edges + **/ + int fromCount; + /** + * Used to create the fromEdges - keeps track of the number of edges that have + * been added + **/ + int fromLength; + + public Node() { + + } + + /** + * Constructor for a node with given `degree'. The value of the + * node is initialized to a random value. + **/ + public Node(int degree, Random r) + { + value = r.nextDouble(); + // create empty array for holding toNodes + toNodes = new Node[degree]; + + next = null; + for (int i = 0; i<fromCount; i++) { + fromNodes[i] = null; + coeffs[i] = 0.0; + } + + //coeffs = null; + fromCount = 0; + fromLength = 0; + } + + /** + * Create the linked list of E or H nodes. We create a table which is used + * later to create links among the nodes. + * @param size the no. of nodes to create + * @param degree the out degree of each node + * @return a table containing all the nodes. + **/ + public Node[] fillTable(int size, int degree, Random r) + { + Node[] table = new Node[size]; + + Node prevNode = new Node(degree, r); + table[0] = prevNode; + for (int i = 1; i < size; i++) { + Node curNode = new Node(degree, r); + table[i] = curNode; + prevNode.next = curNode; + prevNode = curNode; + } + return table; + } + + /** + * Create unique `degree' neighbors from the nodes given in nodeTable. + * We do this by selecting a random node from the give nodeTable to + * be neighbor. If this neighbor has been previously selected, then + * a different random neighbor is chosen. + * @param nodeTable the list of nodes to choose from. + **/ + public void makeUniqueNeighbors(Node[] nodeTable, Random rand) + { + for (int filled = 0; filled < toNodes.length; filled++) { + int k; + Node otherNode; + + do { + // generate a random number in the correct range + int index = rand.nextInt(); + if (index < 0) index = -index; + index = index % nodeTable.length; + + // find a node with the random index in the given table + otherNode = nodeTable[index]; + + for (k = 0; k < filled; k++) { + if (otherNode == toNodes[filled]) + break; + } + } while (k < filled); + + // other node is definitely unique among "filled" toNodes + toNodes[filled] = otherNode; + + // update fromCount for the other node + otherNode.fromCount++; + } + } + + public void makeUniqueNeighborsThread(Node[] nodeTable, Random rand, int l, int u) + { + for (int filled = 0; filled < toNodes.length; filled++) { + int k; + Node otherNode; + + do { + // generate a random number in the correct range + int index = rand.nextInt(); + if (index < 0) index = -index; + index = index % nodeTable.length; + + // find a node with the random index in the given table + otherNode = nodeTable[index]; + + for (k = 0; k < filled; k++) { + if (otherNode == toNodes[filled]) + break; + } + } while (k < filled); + + // other node is definitely unique among "filled" toNodes + toNodes[filled] = otherNode; + + // update fromCount for the other node + otherNode.fromCount++; + } + } + + + /** + * Allocate the right number of FromNodes for this node. This + * step can only happen once we know the right number of from nodes + * to allocate. Can be done after unique neighbors are created and known. + * + * It also initializes random coefficients on the edges. + **/ + public void makeFromNodes() + { + fromNodes = new Node[fromCount]; // nodes fill be filled in later + coeffs = new double[fromCount]; + } + + /** + * Fill in the fromNode field in "other" nodes which are pointed to + * by this node. + **/ + public void updateFromNodes(Random rand) + { + for (int i = 0; i < toNodes.length; i++) { + Node otherNode = toNodes[i]; + int count = otherNode.fromLength++; + otherNode.fromNodes[count] = this; + otherNode.coeffs[count] = rand.nextDouble(); + } + } + + /** + * Get the new value of the current node based on its neighboring + * from_nodes and coefficients. + **/ + /* + public void run() { + Node tmp = this; + while(tmp!= null) { + Node n = tmp; + for (int i = 0; i < n.fromCount; i++) { + n.value -= n.coeffs[i] * n.fromNodes[i].value; + } + tmp = tmp.next; + } + } + */ + + public void computeNewValue() + { + for (int i = 0; i < fromCount; i++) { + value -= coeffs[i] * fromNodes[i].value; + } + } + + /** + * Override the toString method to return the value of the node. + * @return the value of the node. + **/ + public String toString() + { + return "value " + value + ", from_count " + fromCount; + } + +} diff --git a/Robust/src/Benchmarks/Prefetch/Em3d/java/makefile b/Robust/src/Benchmarks/Prefetch/Em3d/java/makefile new file mode 100644 index 00000000..cbb9fd5c --- /dev/null +++ b/Robust/src/Benchmarks/Prefetch/Em3d/java/makefile @@ -0,0 +1,7 @@ +SRC = Em3d +default: + javac ${SRC}.java +run: + java ${SRC} -n 20 -d 10 -p +clean: + rm *.class -- 2.34.1