Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

Monday, April 2, 2012

Concurrent PI-Calculator in Clojure

Inspired by a tutorial about akka tutorial in Scala about making a concurrent PI calculator, I made similar on in Clojure without actor model but just with thread and atom.

(ns pi.core
  (:import [java.util.concurrent Executors])
  (:gen-class))

(def sum (partial reduce +))

(defn f [n]
  (/ (if (even? n) 1 -1) (inc (* 2 n))))

(defn solver1 [n]
  (double (* 4 (sum (map f (range 0 n))))))

(defn solver2 [n]
  (def a (atom 0))
  (def tasks
    (let [unit (/ n 4)]
      (for [m (range 0 4)]
        (fn []
          (swap! a (partial + (sum (map f (range (* unit m) (* unit (inc m)))))))))))

  (let [pool (Executors/newFixedThreadPool (count tasks))]
    (doseq [f (.invokeAll pool tasks)]
      (.get f))
    (.shutdown pool))
  (double (* 4 @a)))

(defn -main []
  (let [n 2000]
    (prn (solver1 n))
    (prn (solver2 n))))

Commenting out the line of solver1/solver2, I got the following results on my 2-core with hyper-threading machine; virtually it's 4 core machine.

solver1

real 3.80
user 4.66
sys 0.09
3.141092653621043

solver2

real 2.01
user 3.44
sys 0.05
3.141092653621043

Comparing to the sequential version, the concurrent version was almost 2 times faster.

Followers