performance measurements

Each table row shows performance measurements for this Clojure program with a particular command-line input value N.

 N  CPU secs Elapsed secs Memory KB Code B ≈ CPU Load

Read the ↓ make, command line, and program output logs to see how this program was run.

Read mandelbrot benchmark to see what this program should do.

 notes

java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) Server VM (build 25.25-b02, mixed mode)

Clojure 1.6.0

 mandelbrot Clojure #2 program source code

;;   The Computer Language Benchmarks Game
;;   http://shootout.alioth.debian.org/

;; contributed by Andy Fingerhut

;; The function 'dot' is based on suggestions and improvements made by
;; these people posting to the Clojure Google group in April, 2009:
;; dmitri.sotnikov, William D. Lipe, Paul Stadig, michael.messinides
;; David Sletten, John Harrop

(ns mandelbrot
  (:gen-class)
  (:import (java.io BufferedOutputStream)))


(def max-iterations 50)
(def limit-square (double 4.0))

(defn dot [r i]
  (let [f2 (double 2.0)
        limit-square (double limit-square)
        iterations-remaining (int max-iterations)
        pr (double r)
        pi (double i)]
    ;; The loop below is similar to the one in the Perl subroutine dot
    ;; in mandelbrot.perl, with these name correspondences:
    ;; pr <-> Cr, pi <-> Ci, zi <-> Zi, zr <-> Zr, zr2 <-> Tr, zi2 <-> Ti
    (loop [zr (double 0.0)
           zi (double 0.0)
           i (int (inc iterations-remaining))]
      (let [zr2 (* zr zr)
            zi2 (* zi zi)]
        (if (and (not (zero? i))
                 (< (+ zr2 zi2) limit-square))
          (recur (+ (- zr2 zi2) pr)
                 (+ (* (* f2 zr) zi) pi)
                 (unchecked-dec i))
          (zero? i))))))


(defn index-to-val [i scale-fac offset]
  (+ (* i scale-fac) offset))


(defn ubyte
  [val]
  (if (>= val 128)
    (byte (- val 256))
    (byte val)))


(defn compute-row
  [x-vals y]
    (loop [b (int 0)
           num-filled-bits (int 0)
           result (transient [])
           x-vals x-vals]
      (if-let [s (seq x-vals)]
        ;; then
        (let [new-bit (int (if (dot (first s) y) 1 0))
              new-b (int (+ (bit-shift-left b 1) new-bit))]
          (if (== num-filled-bits 7)
            (recur (int 0)
                   (int 0)
                   (conj! result (ubyte new-b))
                   (rest s))
            (recur new-b
                   (int (inc num-filled-bits))
                   result
                   (rest s))))
        ;; else
        (if (zero? num-filled-bits)
          (persistent! result)
          (persistent! (conj! result
                              (ubyte (bit-shift-left b (- 8 num-filled-bits)))))
          ))))


(defn my-lazy-map
  [f coll]
  (lazy-seq
    (when-let [s (seq coll)]
      (cons (f (first s)) (my-lazy-map f (rest s))))))


(defn modified-pmap
;   "Like pmap from Clojure 1.1, but with only as much parallelism as
;   there are available processors.  Uses my-lazy-map instead of map
;   from core.clj, since that version of map can use unwanted additional
;   parallelism for chunked collections, like ranges."
  ([num-threads f coll]
     (if (== num-threads 1)
       (map f coll)
       (let [n (if (>= num-threads 2) (dec num-threads) 1)
             rets (my-lazy-map #(future (f %)) coll)
             step (fn step [[x & xs :as vs] fs]
                    (lazy-seq
                      (if-let [s (seq fs)]
                        (cons (deref x) (step xs (rest s)))
                        (map deref vs))))]
         (step rets (drop n rets)))))
  ([num-threads f coll & colls]
     (let [step (fn step [cs]
                  (lazy-seq
                    (let [ss (my-lazy-map seq cs)]
                      (when (every? identity ss)
                        (cons (my-lazy-map first ss)
                              (step (my-lazy-map rest ss)))))))]
       (modified-pmap num-threads #(apply f %) (step (cons coll colls))))))
  

(defn compute-rows [size num-threads]
  (let [two-over-size (double (/ 2.0 size))
        x-offset (double -1.5)
        y-offset (double -1.0)
        x-vals (map #(index-to-val % two-over-size x-offset) (range size))]
    (modified-pmap num-threads
                   #(compute-row x-vals
                                 (index-to-val % two-over-size y-offset))
                   (range size))))


(defn do-mandelbrot [size num-threads]
  (let [rows (compute-rows size num-threads)]
    (println "P4")
    (println (format "%d %d" size size))
    (let [ostream (BufferedOutputStream. System/out)]
      (doseq [r rows]
        (. ostream write (into-array Byte/TYPE r) 0 (count r)))
      (. ostream close))
    (flush)))


(def *default-modified-pmap-num-threads*
     (+ 2 (.. Runtime getRuntime availableProcessors)))

(defn usage [exit-code]
  (println (format "usage: %s size [num-threads]"
                   *file*))
  (println (format "    size must be a positive integer"))
  (println (format "    num-threads is the maximum threads to use at once"))
  (println (format "        during the computation.  If 0 or not given, it"))
  (println (format "        defaults to the number of available cores plus 2,"))
  (println (format "        which is %d"
                   *default-modified-pmap-num-threads*))
  (. System (exit exit-code)))


(defn -main [& args]
  (when (or (< (count args) 1) (> (count args) 2))
    (usage 1))
  (when (not (re-matches #"^\d+$" (nth args 0)))
    (usage 1))
  (def size (. Integer valueOf (nth args 0) 10))
  (when (< size 1)
    (usage 1))
  (def num-threads
       (if (>= (count args) 2)
         (do
           (when (not (re-matches #"^\d+$" (nth args 1)))
             (usage 1))
           (let [n (. Integer valueOf (nth args 1) 10)]
             (if (== n 0)
               *default-modified-pmap-num-threads*
               n)))
         *default-modified-pmap-num-threads*))
  (do-mandelbrot size num-threads)
  (. System (exit 0)))

 make, command-line, and program output logs





Revised BSD license

  Home   Conclusions   License   Play