diff --git a/auto_parallel.Rproj b/auto_parallel.Rproj new file mode 100644 index 0000000..8e3c2eb --- /dev/null +++ b/auto_parallel.Rproj @@ -0,0 +1,13 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX diff --git a/paper/paper.pdf b/paper/paper.pdf index 88df1a1..cc552b8 100644 Binary files a/paper/paper.pdf and b/paper/paper.pdf differ diff --git a/paper/paper.tex b/paper/paper.tex index cbac691..d7045b7 100644 --- a/paper/paper.tex +++ b/paper/paper.tex @@ -45,7 +45,8 @@ \section{Introduction} % even if it is expressed in control flow, it is still data parallelism probably Using Clojure's macro system, we have implemented a set of macros which allow developers to take advantage of Clojure's parallelism potential when their existing code is written such that parallelism is exposed through control flow. -We have shown that it is possible to attain noticeable degrees of parallelism with minimal code changes (with respect to serial code), without the need for sophisticated dependency analysis often required in other parallelism systems. +We have shown that it is possible to attain reasonable degrees of parallelism with minimal code changes (with respect to serial code). +These transformation can be applied to idiomatic Clojure code without the need for sophisticated dependency analysis often required in other parallelism systems. % indicate that we cooperate with STM and other clojure constructs % the other existing libraries are also a testament to this statement diff --git a/project.clj b/project.clj index 0671477..c8ce8ab 100644 --- a/project.clj +++ b/project.clj @@ -2,6 +2,7 @@ :dependencies [[org.clojure/tools.trace "0.7.9"] [org.clojure/clojure "1.8.0"] + [com.google.caliper/caliper "0.5-rc1"] [criterium "0.4.3"]] :main ^:skip-aot com.dpzmick.parallel-macros @@ -13,8 +14,11 @@ :jvm-opts ["-server"]}} :aliases {"benchmark" ["with-profile" "benchmark" "run" "-m" "benchmark.core"] + "jbenchmark" ["with-profile" "benchmark" "run" "-m" "com.dpzmick.auto_parallel_java.App"] "slamhound" ["run" "-m" "slam.hound"]} :jvm-opts ["-server"] + :java-source-paths ["src_java/"] + :plugins [[lein-cloverage "1.0.2"]]) diff --git a/build_machine.sh b/scripts/build_machine.sh similarity index 100% rename from build_machine.sh rename to scripts/build_machine.sh diff --git a/scripts/run_java_suite.sh b/scripts/run_java_suite.sh new file mode 100755 index 0000000..0dbc172 --- /dev/null +++ b/scripts/run_java_suite.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +# TODO log cpu usage +# TODO log git commit hash + +display_usage() { + echo -e "usage $0 output_dir" + echo -e "where" + echo -e "\toutput_dir - directory to dump results to" +} + +if [ $# -lt 1 ] +then + display_usage + exit 1 +fi + +# first, load the environment needed for benchmarks +# the set -a thing is to force them to export +set -a +source ./env +set +a + +output_dir=$1 +output_dir=$output_dir/$(date +"%s")-$(hostname) +log_file=$output_dir/log + +echo "Running -- writing into $output_dir" + +# make a new directory for this run +mkdir -p $output_dir +cp env $output_dir/env +touch $output_dir/is_java + +echo "run starting" | tee $log_file +date +"%m-%d-%y %H:%m:%S" | tee -a $log_file +date +"%s" | tee -a $log_file + +echo | tee -a $log_file + +lein javac | tee -a $log_file + +cat /proc/cpuinfo | tee -a $log_file + +# run the spec and do the output +lein jbenchmark | tee $log_file.bench + +echo "finished test" >> $log_file diff --git a/run_remote.sh b/scripts/run_remote.sh similarity index 97% rename from run_remote.sh rename to scripts/run_remote.sh index 45b724a..5bf116a 100755 --- a/run_remote.sh +++ b/scripts/run_remote.sh @@ -1,5 +1,7 @@ #!/bin/bash +# should never be run from the scripts directory + display_usage() { echo -e "usage $0 num_cpus num_boxes local_out specs" echo -e "where" diff --git a/run_suite.sh b/scripts/run_suite.sh similarity index 100% rename from run_suite.sh rename to scripts/run_suite.sh diff --git a/scripts/run_while_away.sh b/scripts/run_while_away.sh new file mode 100755 index 0000000..5319203 --- /dev/null +++ b/scripts/run_while_away.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +./run_remote.sh 1 23 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 2 12 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 4 6 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 6 4 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 1 23 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 2 12 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 4 6 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 6 4 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 1 23 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 2 12 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 4 6 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 6 4 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 1 23 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 2 12 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 4 6 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} +./run_remote.sh 6 4 out-tmp benchmark_specs/fib/big/{serial.csv,parfun.csv} diff --git a/src_java/com/dpzmick/auto_parallel_java/App.java b/src_java/com/dpzmick/auto_parallel_java/App.java new file mode 100644 index 0000000..4e0d8f9 --- /dev/null +++ b/src_java/com/dpzmick/auto_parallel_java/App.java @@ -0,0 +1,72 @@ +package com.dpzmick.auto_parallel_java; + +import java.util.concurrent.RecursiveTask; +import java.util.concurrent.ForkJoinPool; + +import com.google.caliper.Runner; +import com.google.caliper.SimpleBenchmark; + +class FibTask extends RecursiveTask { + private int grain_; + private int n_; + + public FibTask(int n, int grain) { + grain_ = grain; + n_ = n; + } + + static Integer serialCompute(int n) { + if (n == 0 || n == 1) + return 1; + + return serialCompute(n - 1) + serialCompute(n - 2); + } + + @Override + public Integer compute() { + if (n_ == 0 || n_ == 1) { + return 1; + } + + if (n_ <= grain_) { + return serialCompute(n_); + } + + FibTask f1 = new FibTask(n_ - 1, grain_); + FibTask f2 = new FibTask(n_ - 2, grain_); + f1.fork(); + return f1.join() + f2.compute(); + } +} + + +public class App { + public static class Benchmark extends SimpleBenchmark { + private int n; + + @Override + protected void setUp() throws Exception { + n = Integer.parseInt(System.getenv("BIG_FIB")); + } + + public void timeFibFJ(int reps) { + for (int i = 0; i < reps; i++) { + ForkJoinPool pool = new ForkJoinPool(); + FibTask f = new FibTask(n, 31); + Integer res = pool.invoke(f); + System.out.println(res); + } + } + + public void timeFibSerial(int reps) { + for (int i = 0; i < reps; i++) { + System.out.println(FibTask.serialCompute(n)); + } + } + + } + + public static void main(String[] args) { + Runner.main(Benchmark.class, new String[0]); + } +}