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