user=> (time (dot-product vec1 vec2))
"Elapsed time: 2646.265984 msecs"
114333308833334500000

user=>  (time (inner-product vec1 vec2))
"Elapsed time: 5098.085298 msecs"
114333308833334500000

Java command is:

rlwrap --remember -c -b "(){}[],^%0@"";:''|\"
-f /home/lprefontaine/.clojure/.clj_completions java -Dpid=14824 -server
-Xms500m -Xmx1g
-cp 
.:/tmpfs/clojure/lib/clojure-contrib.jar:/home/lprefontaine/.clojure/lib/*:/tmpfs/clojure/clojure.jar
 clojure.lang.Repl

I ran the (time xxx) lines several times and I picked consistent
measures.

I have a quad-core Q660 (2.4 GHz) with 4MB L2 cache. The inner product
function saturated all the CPUs for a few seconds.

dot-product is still a clear winner... agents hurts more than it helps.

You would expect agents to be faster on this kind of task ?
I would choose agents to decrease wall clock time (assuming it's a main
goal)
only if each agent had a significant workload to achieve or to deal with
variable wait times of any kind
that could slow down sequential processing.

Your code is made of tight loops... dispatching to agents kills the
elapsed
time no ? The cache probably gets flushed as agents are brought in and
this will never win 
over tight loops and recursion.

The agent model is great and it may that warrant compromising on
performance.

In this case if you want the best performance, then it's not the model
to use.
Or I may miss a trick here to make the agent model perform better.
Maybe inner-product can be made more efficient ;)) but I would be
surprised that
you beat dot-product...

Luc

On Mon, 2009-01-26 at 16:08 -0800, redhotmonk wrote:

> Could someone who has a machine with more than 2 cores please
> run the following code? It calculates the inner product of two given
> vectors.
> Usage: (inner-product [1 2 3] [4 5 6]) => 32
> 
> You can change the "9000" which is sprinkled over the code (I know
> it's not beautiful, but I'm new to clojure so
> please go easy...). This number defines the max. length of a pair of
> sub vectors, which is then given to an
> agent as its initial state, whereafter the "dot-product" function is
> send to that agent.
> I have a 2 core machine with 6 MB shared level 2 cache. So I suppose
> that an agent which holds 18000 (9000 integers a vector)
> should fit easily into 3 MB level 2 cache. When I run the commented
> code at the bottom,
> "dot-product" performs better. It would be interesting to see whether
> this changes on 4 or 8 core machines.
> 
> My Setup:
> CPU: 2.53 GHz
> RAM: 4 GByte, 1067 MHz
> Mac OS X 10.5.6
> java version 1.6.0_07
> 
> I run the code with "java -server".
> 
> Thank you, Oliver.
> 
> 
> 
> 
> (defn- dot-product
>   "Takes two vectors and returns their dot product.
>     For example: (dot-product [1 2 3] [4 5 6]) => 32"
>     ([vector1 vector2] (reduce + (map * vector1 vector2)))
>     ([sequence] (dot-product (first sequence) (second sequence))))
> 
> ;; The '9000' in next two function definitions is the lenght of a sub-
> vector which should fit(?) in the level 2 cache.
> 
> (defn- create-agent-send-dot-product! [set-with-agents remaining-
> vector1 remaining-vector2]
>   "Takes a set which contains agents and two vectors of numbers, then
> (as a SIDE EFFECT)
>    creates an agent(with a list of the two vectors as an initial
> state) and sends it the 'dot-product' function.
>    It then returns a new set by conjing the created agent to the
> supplied set."
>   (conj set-with-agents (send (agent (map vec (list (take 9000
> remaining-vector1) (take 9000 remaining-vector2)))) dot-product)))
> 
> 
> (defn inner-product [vector1 vector2]
>   (loop [number-of-agents (quot (count vector1) 9000)
>          set-with-agents #{}
>          remaining-vector1 vector1
>          remaining-vector2 vector2]
>          (if (zero? number-of-agents)
>            (do (apply await set-with-agents)
>                (reduce + (conj (map deref set-with-agents) (dot-
> product remaining-vector1 remaining-vector2))))
>          (recur (dec number-of-agents)
>                 (create-agent-send-dot-product! set-with-agents
> remaining-vector1 remaining-vector2)
>                 (drop 9000 remaining-vector1)
>                 (drop 9000 remaining-vector2)))))
> 
> 
> 
> (comment
> 
> (def vec1 (doall (range 7000000)))
> (def vec2 (doall (range 7000000)))
> 
> (time (dot-product vec1 vec2))      ;; Single threaded calculation. =>
> 3722 msec
> (time (inner-product vec1 vec2))    ;; Multi threaded calculation. =>
> 4452 msec
> 
> )
> 
> > 
> 

--~--~---------~--~----~------------~-------~--~----~
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
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