import edu.rice.hj.api.HjMetrics; import edu.rice.hj.runtime.config.HjSystemProperty; import edu.rice.hj.runtime.metrics.AbstractMetricsManager; import static edu.rice.hj.Module1.*; /** * BinaryTrees.java --- Parallel example of binary tree functions using futures * * @author Vivek Sarkar (vsarkar@rice.edu) * * This example program a binary tree of minimum depth 4, and checks the correctness of the tree. * The default value for the depth is 0, but any size can be provided as argv[0] * * NOTE: this example program is intended for illustrating abstract performance metrics, * and is not intended to be used as abenchmark for real performance. */ public class BinaryTrees { private final static int minDepth = 4; /** * Main function. Can take one input parameter, * which is the depth of the tree. If the depth is * not given or is less then 4, use 4, the minimum * depth * @param args input parameters */ public static void main(String[] args){ // Setup metrics System.setProperty(HjSystemProperty.abstractMetrics.propertyKey(), "true"); initializeHabanero(); int n = 0; if (args.length > 0) n = Integer.parseInt(args[0]); int maxDepth = (minDepth + 2 > n) ? minDepth + 2 : n; int stretchDepth = maxDepth + 1; int check = (TreeNode.bottomUpTree(0,stretchDepth)).itemCheck(); System.out.println("stretch tree of depth "+stretchDepth+"\t check: " + check); TreeNode longLivedTree = TreeNode.bottomUpTree(0,maxDepth); for (int depth=minDepth; depth<=maxDepth; depth+=2){ int iterations = 1 << (maxDepth - depth + minDepth); check = 0; for (int i=1; i<=iterations; i++){ check += (TreeNode.bottomUpTree(i,depth)).itemCheck(); check += (TreeNode.bottomUpTree(-i,depth)).itemCheck(); } System.out.println((iterations*2) + "\t trees of depth " + depth + "\t check: " + check); } System.out.println("long lived tree of depth " + maxDepth + "\t check: "+ longLivedTree.itemCheck()); // Print out the metrics data finalizeHabanero(); final HjMetrics actualMetrics = abstractMetrics(); AbstractMetricsManager.dumpStatistics(actualMetrics); System.out.println(actualMetrics); } /** * Object defining the node of a binary tree. The * tree itself is built as a series of nodes * hooked up together. */ private static class TreeNode { /** * Left child */ final private TreeNode left; /** * Right child */ final private TreeNode right; /** * Value at this node */ private int item; /** * Constructor for a leaf node * @param item - the value stored at this node */ TreeNode(int item){ this.item = item; this.left = null; this.right = null; } /** * Alternate constructor for a node, constructs a non-lear node * @param left - the left child, a TreeNode * @param right - the right child, a TreeNode * @param item - the value stored at this node */ TreeNode(TreeNode left, TreeNode right, int item){ this.left = left; this.right = right; this.item = item; } /** * Build a tree from the bottom up * @param item The value of the item to use in this node * @param depth the currect depth we are at (goes downwards) * @return a new TreeNode */ private static TreeNode bottomUpTree(int item, int depth){ doWork(1); if (depth>0){ final TreeNode LNode = bottomUpTree(2*item-1, depth-1); final TreeNode RNode = bottomUpTree(2*item, depth-1); return new TreeNode(LNode, RNode, item); } else { return new TreeNode(item); } } /** * Returns the value of the node for leaves, or the value of * the node plus the value of the left child minus the value * of the right child, checks that the tree was * built correctly * @return - the check value of the node */ private int itemCheck(){ // if necessary deallocate here if (left==null) return item; else return item + left.itemCheck() - right.itemCheck(); } } }