Add TSP benchmark from JOlden for the multicore gc
authorjzhou <jzhou>
Wed, 28 Jul 2010 00:19:35 +0000 (00:19 +0000)
committerjzhou <jzhou>
Wed, 28 Jul 2010 00:19:35 +0000 (00:19 +0000)
Robust/src/Benchmarks/Scheduling/GC/tsp/Makefile [new file with mode: 0644]
Robust/src/Benchmarks/Scheduling/GC/tsp/TSPBench.java [new file with mode: 0644]
Robust/src/Benchmarks/Scheduling/GC/tsp/TestRunner.java [new file with mode: 0644]
Robust/src/Benchmarks/Scheduling/GC/tsp/Tree_tsp.java [new file with mode: 0644]
Robust/src/Benchmarks/Scheduling/GC/tsp/benchmark.py [new file with mode: 0644]

diff --git a/Robust/src/Benchmarks/Scheduling/GC/tsp/Makefile b/Robust/src/Benchmarks/Scheduling/GC/tsp/Makefile
new file mode 100644 (file)
index 0000000..f84382b
--- /dev/null
@@ -0,0 +1,4 @@
+BMARK = TSP
+PARMS = -c 10000 -m
+include ../Makefile.common
+
diff --git a/Robust/src/Benchmarks/Scheduling/GC/tsp/TSPBench.java b/Robust/src/Benchmarks/Scheduling/GC/tsp/TSPBench.java
new file mode 100644 (file)
index 0000000..f00f631
--- /dev/null
@@ -0,0 +1,23 @@
+/** Bamboo Version  
+ * Ported by: Jin Zhou  07/27/10
+ * 
+ * This is ported from the JOlden
+ * **/
+
+task t1(StartupObject s{initialstate}) {
+  //System.printString("task t1\n");
+
+  int threadnum = 62; // 56;
+  int ncities = 4080;
+  for(int i = 0; i < threadnum; ++i) {
+    TestRunner tr = new TestRunner(ncities){run};
+  }
+
+  taskexit(s{!initialstate});
+}
+
+task t2(TestRunner tr{run}) {
+  //System.printString("task t2\n");
+  tr.run();
+  taskexit(tr{!run});
+}
diff --git a/Robust/src/Benchmarks/Scheduling/GC/tsp/TestRunner.java b/Robust/src/Benchmarks/Scheduling/GC/tsp/TestRunner.java
new file mode 100644 (file)
index 0000000..e9e106d
--- /dev/null
@@ -0,0 +1,108 @@
+
+//import java.io.*;
+
+/**
+ * A Java implementation of the <tt>tsp</tt> Olden benchmark, the traveling
+ * salesman problem.
+ * <p>
+ * <cite>
+ * R. Karp, "Probabilistic analysis of partitioning algorithms for the 
+ * traveling-salesman problem in the plane."  Mathematics of Operations Research 
+ * 2(3):209-224, August 1977
+ * </cite>
+ **/
+public class TestRunner
+{
+  flag run;
+  
+  /**
+   * Number of cities in the problem.
+   **/
+  public int cities;
+  /**
+   * Set to true if the result should be printed
+   **/
+  //private static boolean printResult = false;
+  /**
+   * Set to true to print informative messages
+   **/
+  //private static boolean printMsgs = false;
+  
+  public TestRunner(int cities) {
+    this.cities = cities;
+  }
+
+  /**
+   * The main routine which creates a tree and traverses it.
+   * @param args the arguments to the program
+   **/
+  public void run()
+  {
+    /*parseCmdLine(args);
+
+    if (printMsgs)
+      System.out.println("Building tree of size " + cities);
+    
+    long start0 = System.currentTimeMillis();*/
+    Tree_tsp  t = Tree_tsp.buildTree(this.cities, false, 0.0f, 1.0f, 0.0f, 1.0f);
+    /*long end0 = System.currentTimeMillis();
+
+    long start1 = System.currentTimeMillis();*/
+    t.tsp(150);
+    /*long end1 = System.currentTimeMillis();
+
+    if (printResult) {
+      // if the user specifies, print the final result
+      t.printVisitOrder();
+    }
+
+    if (printMsgs) {
+      System.out.println("Tsp build time  " + (end0 - start0)/1000.0);
+      System.out.println("Tsp time " + (end1 - start1)/1000.0);
+      System.out.println("Tsp total time " + (end1 - start0)/1000.0);
+    }
+    System.out.println("Done!");*/
+  }
+
+  /**
+   * Parse the command line options.
+   * @param args the command line options.
+   **/
+  /*private static final void parseCmdLine(String args[])
+  {
+    int i = 0;
+    String arg;
+
+    while (i < args.length && args[i].startsWith("-")) {
+      arg = args[i++];
+
+      if (arg.equals("-c")) {
+       if (i < args.length)
+         cities = new Integer(args[i++]).intValue();
+       else throw new Error("-c requires the size of tree");
+      } else if (arg.equals("-p")) {
+       printResult = true;
+      } else if (arg.equals("-m")) {
+       printMsgs = true;
+      } else if (arg.equals("-h")) {
+       usage();
+      }
+    }
+    if (cities == 0) usage();
+  }*/
+
+  /**
+   * The usage routine which describes the program options.
+   **/
+  /*private static final void usage()
+  {
+    System.err.println("usage: java TSP -c <num> [-p] [-m] [-h]");
+    System.err.println("    -c number of cities (rounds up to the next power of 2 minus 1)");
+    System.err.println("    -p (print the final result)");
+    System.err.println("    -m (print informative messages)");
+    System.err.println("    -h (print this message)");
+    System.exit(0);
+  }*/
+
+}
+
diff --git a/Robust/src/Benchmarks/Scheduling/GC/tsp/Tree_tsp.java b/Robust/src/Benchmarks/Scheduling/GC/tsp/Tree_tsp.java
new file mode 100644 (file)
index 0000000..706ba05
--- /dev/null
@@ -0,0 +1,456 @@
+
+//import java.util.Random;
+
+/**
+ * A class that represents a node in a binary tree.  Each node represents
+ * a city in the TSP benchmark.
+ **/
+final class Tree_tsp
+{
+  /**
+   * The number of nodes (cities) in this subtree
+   **/
+  private int sz;
+  /**
+   * The coordinates that this node represents
+   **/
+  private float x,y;
+  /**
+   * Left child of the tree
+   **/
+  private Tree_tsp  left;
+  /**
+   * Right child of tree
+   **/
+  private Tree_tsp  right;
+  /**
+   * The next pointer in a linked list of nodes in the subtree.  The list
+   * contains the order of the cities to visit.
+   **/
+  private Tree_tsp  next;
+  /**
+   * The previous pointer in a linked list of nodes in the subtree. The list
+   * contains the order of the cities to visit.
+   **/
+  private Tree_tsp  prev;
+
+  // used by the random number generator
+  //private static final float  M_E2; //  = 7.3890560989306502274;
+  //private static final float  M_E3; //  = 20.08553692318766774179;
+  //private static final float  M_E6; //  = 403.42879349273512264299;
+  //private static final float  M_E12; // = 162754.79141900392083592475;
+
+  /**
+   * Construct a Tree node (a city) with the specified size
+   * @param size the number of nodes in the (sub)tree
+   * @param x the x coordinate of the city
+   * @param y the y coordinate of the city
+   * @param left the left subtree
+   * @param right the right subtree
+   **/
+  Tree_tsp(int size, float x, float y, Tree_tsp l, Tree_tsp r)
+  {
+    /*M_E2  = 7.3890560989306502274f;
+    M_E3  = 20.08553692318766774179f;
+    M_E6  = 403.42879349273512264299f;
+    M_E12 = 162754.79141900392083592475f;*/
+    
+    sz = size;
+    this.x = x;
+    this.y = y;
+    left = l;
+    right = r;
+    next = null;
+    prev = null;
+  }
+
+  /**
+   * Find Euclidean distance between this node and the specified node.
+   * @param b the specified node
+   * @return the Euclidean distance between two tree nodes.
+   **/
+  float distance(Tree_tsp b) 
+  {
+    return (Math.sqrtf((float)((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y))));
+  }
+
+  /**
+   * Create a list of tree nodes.  Requires root to be the tail of the list.
+   * Only fills in next field, not prev.
+   * @return the linked list of nodes
+   **/
+  Tree_tsp makeList() 
+  {
+    Tree_tsp myleft, myright;
+    Tree_tsp tleft,tright;
+    Tree_tsp retval = this;
+
+    // head of left list
+    if (left != null) 
+      myleft = left.makeList();
+    else
+      myleft = null;
+
+    // head of right list
+    if (right != null)
+      myright = right.makeList();
+    else
+      myright = null;
+
+    if (myright != null) { 
+      retval = myright; 
+      right.next = this;
+    }
+
+    if (myleft != null) { 
+      retval = myleft; 
+      if (myright != null)
+        left.next = myright;
+      else
+        left.next = this;
+    }  
+    next = null;
+
+    return retval;
+  }
+
+  /**
+   * Reverse the linked list.  Assumes that there is a dummy "prev"
+   * node at the beginning.
+   **/
+  void reverse() 
+  {
+    Tree_tsp prev = this.prev;
+    prev.next = null;
+    this.prev = null;
+    Tree_tsp back = this;
+    Tree_tsp tmp = this;
+    // reverse the list for the other nodes
+    Tree_tsp next;
+    for (Tree_tsp t = this.next; t != null; back = t, t = next) {
+      next = t.next;
+      t.next = back;
+      back.prev = t;
+    }
+    // reverse the list for this node
+    tmp.next = prev;
+    prev.prev = tmp;
+  }
+
+  /** 
+   * Use closest-point heuristic from Cormen, Leiserson, and Rivest.
+   * @return a 
+   **/
+  Tree_tsp conquer() 
+  {
+    // create the list of nodes
+    Tree_tsp t = makeList();
+
+    // Create initial cycle 
+    Tree_tsp cycle = t;
+    t = t.next;
+    cycle.next = cycle;
+    cycle.prev = cycle;
+
+    // Loop over remaining points 
+    Tree_tsp donext;
+    for (; t != null; t = donext) {
+      donext = t.next; /* value won't be around later */
+      Tree_tsp min = cycle;
+      float mindist = t.distance(cycle);
+      for (Tree_tsp tmp = cycle.next; tmp != cycle; tmp=tmp.next) {
+        float test = tmp.distance(t);
+        if (test < mindist) {
+          mindist = test;
+          min = tmp;
+        } /* if */
+      } /* for tmp... */
+
+      Tree_tsp next = min.next;
+      Tree_tsp prev = min.prev;
+
+      float mintonext = min.distance(next);
+      float mintoprev = min.distance(prev);
+      float ttonext = t.distance(next);
+      float ttoprev = t.distance(prev);
+
+      if ((float)(ttoprev - mintoprev) < (float)(ttonext - mintonext)) {
+        /* insert between min and prev */
+        prev.next = t;
+        t.next = min;
+        t.prev = prev;
+        min.prev = t;
+      } else {
+        next.prev = t;
+        t.next = next;
+        min.next = t;
+        t.prev = min;
+      }
+    } /* for t... */
+
+    return cycle;
+  }
+
+  /** 
+   * Merge two cycles as per Karp.
+   * @param a a subtree with one cycle
+   * @param b a subtree with the other cycle
+   **/
+  Tree_tsp merge(Tree_tsp a, Tree_tsp b) 
+  {
+    // Compute location for first cycle
+    Tree_tsp   min = a;
+    float mindist = distance(a);
+    Tree_tsp   tmp = a;
+    for (a = a.next; a != tmp; a = a.next) {
+      float test = distance(a);
+      if (test < mindist) {
+        mindist = test;
+        min = a;
+      }
+    }
+
+    Tree_tsp next = min.next;
+    Tree_tsp prev = min.prev;
+    float mintonext = min.distance(next);
+    float mintoprev = min.distance(prev);
+    float ttonext   = distance(next);
+    float ttoprev   = distance(prev);
+
+    Tree_tsp p1, n1;
+    float tton1, ttop1;
+    if ((ttoprev - mintoprev) < (ttonext - mintonext)) {
+      // would insert between min and prev
+      p1 = prev;
+      n1 = min;
+      tton1 = mindist;
+      ttop1 = ttoprev;
+    } else { 
+      // would insert between min and next
+      p1 = min;
+      n1 = next;
+      ttop1 = mindist;
+      tton1 = ttonext;
+    }
+
+    // Compute location for second cycle
+    min = b;
+    mindist = distance(b);
+    tmp = b;
+    for (b = b.next; b != tmp; b = b.next) {
+      float test = distance(b);
+      if (test < mindist) {
+        mindist = test;
+        min = b;
+      }
+    }
+
+    next = min.next;
+    prev = min.prev;
+    mintonext = min.distance(next);
+    mintoprev = min.distance(prev);
+    ttonext = this.distance(next);
+    ttoprev = this.distance(prev);
+
+    Tree_tsp p2, n2;
+    float tton2, ttop2;
+    if ((ttoprev - mintoprev) < (ttonext - mintonext)) {
+      // would insert between min and prev
+      p2 = prev;
+      n2 = min;
+      tton2 = mindist;
+      ttop2 = ttoprev;
+    } else { 
+      // would insert between min andn ext 
+      p2 = min;
+      n2 = next;
+      ttop2 = mindist;
+      tton2 = ttonext;
+    }
+
+    // Now we have 4 choices to complete:
+    // 1:t,p1 t,p2 n1,n2
+    // 2:t,p1 t,n2 n1,p2
+    // 3:t,n1 t,p2 p1,n2
+    // 4:t,n1 t,n2 p1,p2 
+    float n1ton2 = n1.distance(n2);
+    float n1top2 = n1.distance(p2);
+    float p1ton2 = p1.distance(n2);
+    float p1top2 = p1.distance(p2);
+
+    mindist = (float)(ttop1 + ttop2 + n1ton2); 
+    int choice = 1;
+
+    float test = (float)(ttop1 + tton2 + n1top2);
+    if (test < mindist) {
+      choice = 2;
+      mindist = test;
+    }
+
+    test = tton1 + ttop2 + p1ton2;
+    if (test < mindist) {
+      choice = 3;
+      mindist = test;
+    }
+
+    test = tton1 + tton2 + p1top2;
+    if (test < mindist) 
+      choice = 4;
+
+    if (choice == 1) {
+    //case 1:
+      // 1:p1,this this,p2 n2,n1 -- reverse 2!
+      n2.reverse();
+      p1.next = this;
+      this.prev = p1;
+      this.next = p2;
+      p2.prev = this;
+      n2.next = n1;
+      n1.prev = n2;
+      //break;
+    } else if(choice == 2) {
+    //case 2:
+      // 2:p1,this this,n2 p2,n1 -- OK
+      p1.next = this;
+      this.prev = p1;
+      this.next = n2;
+      n2.prev = this;
+      p2.next = n1;
+      n1.prev = p2;
+      //break;
+    } else if(choice == 3) {
+    //case 3:
+      // 3:p2,this this,n1 p1,n2 -- OK
+      p2.next = this;
+      this.prev = p2;
+      this.next = n1;
+      n1.prev = this;
+      p1.next = n2;
+      n2.prev = p1;
+      //break;
+    } else if(choice == 4) {
+    //case 4:
+      // 4:n1,this this,n2 p2,p1 -- reverse 1!
+      n1.reverse();
+      n1.next = this;
+      this.prev = n1;
+      this.next = n2;
+      n2.prev = this;
+      p2.next = p1;
+      p1.prev = p2;
+      //break;
+    }
+    return this;
+  }
+
+  /**
+   * Compute TSP for the tree t. Use conquer for problems <= sz 
+   * @param sz the cutoff point for using conquer vs. merge
+   **/
+  Tree_tsp tsp(int sz) 
+  {
+    if (this.sz <= sz) return conquer();
+
+    Tree_tsp leftval  = left.tsp(sz);
+    Tree_tsp rightval = right.tsp(sz); 
+
+    return merge(leftval, rightval);
+  }
+
+  /**
+   * Print the list of cities to visit from the current node.  The
+   * list is the result of computing the TSP problem.
+   * The list for the root node (city) should contain every other node
+   * (city).
+   **/
+  /*void printVisitOrder()
+  {
+    System.out.println("x = " + x + " y = " + y);
+    for (Tree_tsp tmp = next; tmp != this; tmp = tmp.next) {
+      System.out.println("x = " + tmp.x + " y = " + tmp.y);
+    }
+  }*/
+
+  //
+  // static methods
+  //
+
+  /**
+   * Return an estimate of median of n values distributed in [min,max)
+   * @param min the minimum value 
+   * @param max the maximum value
+   * @param n 
+   * @return an estimate of median of n values distributed in [min,max)
+   **/
+  private static float median(float min, float max, int n) 
+  {
+    float M_E2  = 7.3890560989306502274f;
+    float M_E3  = 20.08553692318766774179f;
+    float M_E6  = 403.42879349273512264299f;
+    float M_E12 = 162754.79141900392083592475f;
+    
+    // get random value in [0.0, 1.0)
+    float t = (new Random()).nextFloat();
+
+    float retval;
+    if (t > 0.5) {
+      retval = /*java.lang.*/(float)(Math.log(1.0-(2.0*(M_E12-1)*(t-0.5)/M_E12))/12.0f);   
+    } else {
+      retval = (float)(-/*java.lang.*/Math.log(1.0-(2.0*(M_E12-1)*t/M_E12))/12.0f);
+    }
+    // We now have something distributed on (-1.0,1.0)
+    retval = (float)((retval+1.0f) * (max-min)/2.0f);
+    retval = retval + min;
+    return retval;
+  }
+
+  /**
+   * Get float uniformly distributed over [min,max) 
+   * @return float uniformily distributed over [min,max)
+   **/
+  private static float uniform(float min, float max) 
+  {
+    // get random value between [0.0,1.0)
+    float retval = (new Random()).nextFloat(); 
+    retval = retval * (max-min);
+    return retval + min;
+  }
+
+  /**
+   * Builds a 2D tree of n nodes in specified range with dir as primary 
+   * axis (false for x, true for y)
+   *
+   * @param n the size of the subtree to create
+   * @param dir the primary axis
+   * @param min_x the minimum x coordinate
+   * @param max_x the maximum x coordinate
+   * @param min_y the minimum y coordinate
+   * @param max_y the maximum y coordinate
+   * @return a reference to the root of the subtree
+   **/
+  public static Tree_tsp buildTree(int n, boolean dir, float min_x,
+      float max_x, float min_y, float max_y) 
+  {
+    if (n==0) return null;
+
+    Tree_tsp left, right;
+    float x, y;
+    if (dir) {
+      dir = !dir;
+      float med = median(min_x,max_x,n);
+      left = buildTree(n/2, dir, min_x, med, min_y, max_y);
+      right = buildTree(n/2, dir, med, max_x, min_y, max_y);
+      x = med;
+      y = uniform(min_y, max_y);
+    } else {
+      dir = !dir;
+      float med = median(min_y,max_y,n);
+      left = buildTree(n/2, dir, min_x, max_x, min_y, med);
+      right = buildTree(n/2, dir, min_x, max_x, med, max_y);
+      y = med;
+      x = uniform(min_x, max_x);
+    }
+    return new Tree_tsp(n, x, y, left, right);
+  }
+
+}
diff --git a/Robust/src/Benchmarks/Scheduling/GC/tsp/benchmark.py b/Robust/src/Benchmarks/Scheduling/GC/tsp/benchmark.py
new file mode 100644 (file)
index 0000000..1acab5d
--- /dev/null
@@ -0,0 +1,3 @@
+from ashes2.lang.java.JOldenBenchmark import JOldenBenchmark
+
+benchmark = JOldenBenchmark("tsp", "TSP", params = ("-c", "1000", "-m"))