Hi Stuart, A lot of parallel processing problems seem to lend themselves to a mapreduce approach. I've written a few blog entries on mapreduce in the past:
http://bc.tech.coop/blog/060105.html http://bc.tech.coop/blog/070520.html http://bc.tech.coop/blog/070601.html Bill On Tue, Oct 28, 2008 at 8:08 AM, Stuart Halloway <[EMAIL PROTECTED]> wrote: > > Hi Bill, > > Thanks, that's a good point re: await. It would also be interesting to > have the agents run for a certain length of time, rather than a > certain number of iterations. > > What do you think of using a map argument to a reduce fn? Idiomatic > Clojure seems to prefer using a vector, but I am biased toward a map > based on Ruby experience. I haven't decided which is more readable. > > Stuart > >> Hi Stuart, >> >> On Mon, Oct 27, 2008 at 7:06 PM, Stuart Halloway >> <[EMAIL PROTECTED]> wrote: >>> >>> Hi all, >>> >>> The code below implements a Monte Carlo simulation to estimate the >>> value of pi. It works, and it was easy to reuse the original single- >>> threaded approach across multiple agents. >>> >>> How idiomatic is this use of agents? Other than bringing in ForkJoin, >>> are there other idiomatic ways to parallelize divide-and-conquer in >>> Clojure? >>> >>> Cheers, >>> Stuart >>> >>> (defn in-circle? [[x y]] >>> (<= (Math/sqrt (+ (* x x) (* y y))) 1)) >>> >>> (defn random-point [] >>> [(dec (rand 2)) (dec (rand 2))]) >>> >>> ; take samples, tracking number that land >>> ; :in circle and :total number >>> (defn sample-for-pi [count] >>> (reduce (fn [{in :in total :total} point] >>> {:in (if (in-circle? point) (inc in) in) >>> :total (inc total)}) >>> {:in 0 :total 0} >>> (take count (repeatedly random-point)))) >>> >>> >>> (defn guess-from-samples [samples] >>> (assoc samples :guess (/ (* 4.0 (:in samples)) (:total samples)))) >>> >>> ; guess pi by running Monte Carlo simulation count times >>> (defn guess-pi [count] >>> (guess-from-samples (sample-for-pi count))) >>> >>> ; guess pi by running Monte Carlo simulation count times >>> ; spread across n agents >>> (defn guess-pi-agent [n count] >>> (let [count (quot count n) >>> agents (for [_ (range n)] (agent count))] >>> (doseq a agents (send a sample-for-pi)) >>> (apply await agents) >>> (guess-from-samples (reduce (fn [a1 a2] >>> {:in (+ (:in @a1) (:in @a2)) >>> :total (+ (:total @a1) (:total >>> @a2))}) >>> agents)))) >> >> I've not gotten around to playing with the concurrency features of >> Clojure yet, so I'm just commenting "theoretically" on your code. In >> "guess-pi-agent", you use "await" to wait for the results from the >> agents. If one of the agents "dies", won't your code wait forever? I >> would think that it would be preferable to use "await-for" (with a >> timeout) so that the result can still be guessed based on the samples >> that have come back from the other agents. If you plan to use a >> variation of this code in a multi-processor example, some degree of >> agent failure is even more likely. >> >> -- >> Bill Clementson >> >> > > > > > > --~--~---------~--~----~------------~-------~--~----~ 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 [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---