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;
}
--- /dev/null
+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;
+ }
+ }
+ }
+}
--- /dev/null
+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();
+ }
+
+}
+
--- /dev/null
+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)");
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+SRC = Em3d
+default:
+ javac ${SRC}.java
+run:
+ java ${SRC} -n 20 -d 10 -p
+clean:
+ rm *.class