Marshall:

I'm not practiced in recognizing megamorphic call sites, so I could be missing 
some in the example code below, modified from Lee's original code.  It doesn't 
use reverse or conj, and as far as I can tell doesn't use PersistentList, 
either, only Cons.

(defn burn-cons [size]
  (let [size (long size)]
    (loop [i (long 0)
           value nil]
      (if (>= i size)
        (last value)
        (recur (inc i) (clojure.lang.Cons.
                        (* (int i)
                           (+ (float i)
                              (- (int i)
                                 (/ (float i)
                                    (inc (int i))))))
                        value))))))

(a) invoke (burn-cons 2000000) sequentially 64 times in a single JVM

(b) invoke (burn-cons 2000000) 64 times using a modified version of pmap that 
limits the number of active threads to 2 (see below), in a single JVM.  I would 
hope that this would take about half the elapsed time than (a), but the elapsed 
time is longer than (a)

(c) start up two JVMs simultaneously and invoke (burn-cons 2000000) 
sequentially 32 times in each.  The elapsed time here is less than (a), as I 
would expect.

(Clojure 1.4, Oracle/Apple JDK 1.6.0_37, Mac OS X 10.6.8, running on a machine 
with Intel core i7 with 4 physical cores but OS X reports it as 8 I think 
because of 2 hyperthreads per core -- more details available on request).

Can you try to reproduce to see if you get similar results?  If so, do you know 
why we get bad parallelism in a single JVM for this code?  If there are no 
megamorphic call sites, then it is examples like this that lead me to wonder 
about locking in memory allocation and/or GC.


With the functions below, my part (b) was measured by doing:

(time (doall (nthreads-pmap 2 (burn-cons 2000000) (unchunk (range 64)))))

Andy



(defn unchunk [s]
  (when (seq s)
    (lazy-seq
     (cons (first s)
           (unchunk (next s))))))

(defn nthreads-pmap
  "Like pmap, except can take an argument nthreads to control the
  maximum number of parallel threads used."
  ([f coll]
     (let [n (+ 2 (.. Runtime getRuntime availableProcessors))]
       (nthreads-pmap n f coll)))
  ([nthreads f coll]
     (if (= nthreads 1)
       (map f coll)
       (let [n (dec nthreads)
             rets (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)))))
  ([nthreads f coll & colls]
   (let [step (fn step [cs]
                (lazy-seq
                 (let [ss (map seq cs)]
                   (when (every? identity ss)
                     (cons (map first ss) (step (map rest ss)))))))]
     (nthreads-pmap nthreads #(apply f %) (step (cons coll colls))))))


On Dec 11, 2012, at 10:06 AM, Marshall Bockrath-Vandegrift wrote:

> Lee Spector <lspec...@hampshire.edu> writes:
> 
>> If the application does lots of "list processing" but does so with a
>> mix of Clojure list and sequence manipulation functions, then one
>> would have to write private, list/cons-only versions of all of these
>> things? That is -- overstating it a bit, to be sure, but perhaps not
>> entirely unfairly -- re-implement Clojure's Lisp?
> 
> I just did a quick look over clojure/core.clj, and `reverse` is the only
> function which stood out to me as hitting the most pathological case.
> Every other `conj` loop over a user-provided datastructure is `conj`ing
> into an explicit non-list/`Cons` type.
> 
> So I think if you replace your calls to `reverse` and any `conj` loops
> you have in your own code, you should see a perfectly reasonable
> speedup.
> 
> -Marshall
> 
> -- 
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with your 
> first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to