Re: group-by vs. reducers?

2012-12-07 Thread Balint Erdi
Hey,

Reducers is fascinating and quite complex at the same time. I feel like 
best practices around it has not quite solidified yet.

Here is how I made your example work:

(ns group-by-reducers.core
  (:require [clojure.core.reducers :as r :only [fold reduce map]])
  (:require [criterium.core :as c]))

(defn group-by-naive [f coll]
  (reduce
(fn [groups a]
  (assoc groups (f a) (conj (get groups a []) a)))
{}
coll))

(defn group-by-red [f coll]
  (letfn [(reduce-groups
([] {})
([g1 g2]
  (merge-with concat g1 g2)))]
(r/fold reduce-groups (r/map #(hash-map (f %) [%]) coll

(defn -main
  [ args]
  (c/quick-bench (group-by #(mod % 29) (range 1)))
  (c/quick-bench (group-by-naive #(mod % 29) (range 1)))
  (c/quick-bench (group-by-red #(mod % 29) (range 1

(available as a gist here: https://gist.github.com/4232044)

The core and naive versions perform roughly equally (~4ms) while the 
reducers version takes 10x as much time (~40ms) on my two-core laptop.

I'm absolutely sure I'm doing something wrong (there is probably too much 
memory allocated by the map function) and would like to hear the opinion of 
someone more knowledgeable with reducers. I just did not want the subject 
to be buried.

Hope that still helps a bit,
Balint

ps. There are some tips and tricks in this 
post: http://www.thebusby.com/2012/07/tips-tricks-with-clojure-reducers.html

On Monday, December 3, 2012 5:04:17 PM UTC+1, Las wrote:

 Hi,

 As I was trying to wrap my head around the reducers library[1], I thought 
 implementing group-by would be a good exercise to gain some insight.

 After spending a few hours with it, I'm still pretty much clueless, so 
 hope to find someone here to help me out:

 So if I understood the reducer lingo introduced in [2],[3] and group-by 
 correctly, it reduces the following reducing function on a collection

 (fn group-by-reducef [keyfn ret x]
  (let [k (keyfn x)]
 (assoc ret k (conj (get ret k []) x

 where keyfn is provided by a partial function application.

 fold needs a combining function that takes two result maps that have 
 already been grouped and merges them.
 A naive implementation could look like

 (defn group-by-combinef
   ([] {})
   ([g1 g2]
  (persistent!
   (reduce (fn [res k v]
 (assoc! res k (into (get res k []) v)))
   (transient g1) g2

 (defn group-by [f coll]
   (fold (partial gr-by-reducef f) gr-by-combinef coll))

 Now couple of questions:
 1) I expected fold to actually perform the operation, how can I force it 
 to give me the result?
 2) Can somehow the actual reducing at the leaf nodes still take advantage 
 of transient collections?
 3) I took a look at flatten as it seems the closest match. Again, if I 
 call (flatten [[1 2] [2 4]]), I don't actually get the result. How do I get 
 to the result?


 Thanks!

 [1] 
 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj
 [2] 
 http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html
 [3] http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
 -- 
 László Török

 

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

Re: group-by vs. reducers?

2012-12-07 Thread Balint Erdi
BTW I understood the most about reducers (still not quite there yet, though 
:) ) from Rich Hickey's talk at EuroClojure:

https://vimeo.com/45561411

On Friday, December 7, 2012 10:21:59 AM UTC+1, Balint Erdi wrote:

 Hey,

 Reducers is fascinating and quite complex at the same time. I feel like 
 best practices around it has not quite solidified yet.

 Here is how I made your example work:

 (ns group-by-reducers.core
   (:require [clojure.core.reducers :as r :only [fold reduce map]])
   (:require [criterium.core :as c]))

 (defn group-by-naive [f coll]
   (reduce
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 {}
 coll))

 (defn group-by-red [f coll]
   (letfn [(reduce-groups
 ([] {})
 ([g1 g2]
   (merge-with concat g1 g2)))]
 (r/fold reduce-groups (r/map #(hash-map (f %) [%]) coll

 (defn -main
   [ args]
   (c/quick-bench (group-by #(mod % 29) (range 1)))
   (c/quick-bench (group-by-naive #(mod % 29) (range 1)))
   (c/quick-bench (group-by-red #(mod % 29) (range 1

 (available as a gist here: https://gist.github.com/4232044)

 The core and naive versions perform roughly equally (~4ms) while the 
 reducers version takes 10x as much time (~40ms) on my two-core laptop.

 I'm absolutely sure I'm doing something wrong (there is probably too much 
 memory allocated by the map function) and would like to hear the opinion of 
 someone more knowledgeable with reducers. I just did not want the subject 
 to be buried.

 Hope that still helps a bit,
 Balint

 ps. There are some tips and tricks in this post: 
 http://www.thebusby.com/2012/07/tips-tricks-with-clojure-reducers.html

 On Monday, December 3, 2012 5:04:17 PM UTC+1, Las wrote:

 Hi,

 As I was trying to wrap my head around the reducers library[1], I thought 
 implementing group-by would be a good exercise to gain some insight.

 After spending a few hours with it, I'm still pretty much clueless, so 
 hope to find someone here to help me out:

 So if I understood the reducer lingo introduced in [2],[3] and group-by 
 correctly, it reduces the following reducing function on a collection

 (fn group-by-reducef [keyfn ret x]
  (let [k (keyfn x)]
 (assoc ret k (conj (get ret k []) x

 where keyfn is provided by a partial function application.

 fold needs a combining function that takes two result maps that have 
 already been grouped and merges them.
 A naive implementation could look like

 (defn group-by-combinef
   ([] {})
   ([g1 g2]
  (persistent!
   (reduce (fn [res k v]
 (assoc! res k (into (get res k []) v)))
   (transient g1) g2

 (defn group-by [f coll]
   (fold (partial gr-by-reducef f) gr-by-combinef coll))

 Now couple of questions:
 1) I expected fold to actually perform the operation, how can I force it 
 to give me the result?
 2) Can somehow the actual reducing at the leaf nodes still take advantage 
 of transient collections?
 3) I took a look at flatten as it seems the closest match. Again, if I 
 call (flatten [[1 2] [2 4]]), I don't actually get the result. How do I get 
 to the result?


 Thanks!

 [1] 
 https://github.com/clojure/clojure/blob/master/src/clj/clojure/core/reducers.clj
 [2] 
 http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html
 [3] http://clojure.com/blog/2012/05/15/anatomy-of-reducer.html
 -- 
 László Török

 

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

Re: [ANN] sublime-lispindent, clojure indenting for sublime text 2

2012-12-07 Thread Jonathan Fischer Friberg
You're welcome :)


On Fri, Dec 7, 2012 at 1:12 AM, Anton Holmberg antonholmber...@gmail.comwrote:

 This is so awesome! You are my hero. Been searching for this for a while
 now.

 Den måndagen den 12:e november 2012 kl. 17:25:38 UTC+1 skrev Jonathan
 Fischer Friberg:

 Dear clojure mailing list,

 As the indenting for clojure (and lisp in general) was very lacking
 in sublime, I decided to make a plugin:

 https://github.com/odyssomay/**sublime-lispindenthttps://github.com/odyssomay/sublime-lispindent

 I hope someone finds this useful.

 By the way, if someone with a mac could try the keyboard shortcuts that
 would be great.
 I don't own a mac so I cannot test them.

 Sincerely,
 Jonathan

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

How was the skills matters conference in London (6. Dec)?

2012-12-07 Thread john
Hi,
I couldn't make it to the skill matters conference in London ))-:
just being curious,... how was it? Any news? was there a main theme?

Many  Greetings
John

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

Re: How was the skills matters conference in London (6. Dec)?

2012-12-07 Thread Thomas
It was really great, all the videos are up already:

http://skillsmatter.com/event/scala/clojure-exchange-2012

Have a look.

Thomas

On Friday, December 7, 2012 10:59:32 AM UTC, john wrote:

 Hi,
 I couldn't make it to the skill matters conference in London ))-:
 just being curious,... how was it? Any news? was there a main theme?

 Many  Greetings
 John


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

Re: group-by vs. reducers?

2012-12-07 Thread Christophe Grand
Hi,

There are indeed too much allocationfoing on in your r/map.
You don't need the rmap,

Start from a plain old reduce like your reduce-by-naive, replace reduce by
r/fold, remove the seed and add the combine-fn (which now provides the
seed):

(defn group-by-red [f coll]
  (r/fold
(partial merge-with concat)
(fn [groups a]
  (assoc groups (f a) (conj (get groups a []) a)))
coll))


Crude benchmark;
 (let [v (vec (range 100))]
  (dotimes [n 5]
(println Run n)
(time (group-by #(mod % 29) v))
(time (group-by-naive #(mod % 29) v))
(time (group-by-red #(mod % 29) v
Run 0
Elapsed time: 938.878 msecs
Elapsed time: 778.161 msecs
Elapsed time: 1035.997 msecs
Run 1
Elapsed time: 715.352 msecs
Elapsed time: 771.913 msecs
Elapsed time: 840.264 msecs
Run 2
Elapsed time: 656.588 msecs
Elapsed time: 700.114 msecs
Elapsed time: 777.323 msecs
Run 3
Elapsed time: 731.781 msecs
Elapsed time: 713.547 msecs
Elapsed time: 875.801 msecs
Run 4
Elapsed time: 689.711 msecs
Elapsed time: 710.728 msecs
Elapsed time: 1112.609 msecs
nil

Let's play with the granularity (defaults to 512)
(defn group-by-red [f coll]
  (r/fold 2048
(partial merge-with concat)
(fn [groups a]
  (assoc groups (f a) (conj (get groups a []) a)))
coll))

Re-benchmark:
Run 0
Elapsed time: 810.676 msecs
Elapsed time: 736.764 msecs
Elapsed time: 547.651 msecs
Run 1
Elapsed time: 681.249 msecs
Elapsed time: 850.046 msecs
Elapsed time: 521.27 msecs
Run 2
Elapsed time: 669.385 msecs
Elapsed time: 712.15 msecs
Elapsed time: 518.502 msecs
Run 3
Elapsed time: 673.108 msecs
Elapsed time: 745.688 msecs
Elapsed time: 542.837 msecs
Run 4
Elapsed time: 654.196 msecs
Elapsed time: 723.074 msecs
Elapsed time: 506.861 msecs

Note that you are not exactly comparing apples to apples since group-by-red
is returning maps whose values are unrealized lazy sequence (concats of
concats of ocncats of vactors) instead of vectors

(defn group-by-red [f coll]
  (r/fold 2048
(partial merge-with into)
(fn [groups a]
  (assoc groups (f a) (conj (get groups a []) a)))
coll))

Run 0
Elapsed time: 763.455 msecs
Elapsed time: 763.501 msecs
Elapsed time: 681.075 msecs
Run 1
Elapsed time: 645.52 msecs
Elapsed time: 731.545 msecs
Elapsed time: 476.381 msecs
Run 2
Elapsed time: 660.775 msecs
Elapsed time: 728.19 msecs
Elapsed time: 475.543 msecs
Run 3
Elapsed time: 657.255 msecs
Elapsed time: 725.995 msecs
Elapsed time: 494.038 msecs
Run 4
Elapsed time: 647.53 msecs
Elapsed time: 731.085 msecs
Elapsed time: 538.649 msecs

hth,

Christophe

On Fri, Dec 7, 2012 at 10:30 AM, Balint Erdi balint.e...@gmail.com wrote:

 BTW I understood the most about reducers (still not quite there yet,
 though :) ) from Rich Hickey's talk at EuroClojure:

 https://vimeo.com/45561411


 On Friday, December 7, 2012 10:21:59 AM UTC+1, Balint Erdi wrote:

 Hey,

 Reducers is fascinating and quite complex at the same time. I feel like
 best practices around it has not quite solidified yet.

 Here is how I made your example work:

 (ns group-by-reducers.core
   (:require [clojure.core.reducers :as r :only [fold reduce map]])
   (:require [criterium.core :as c]))

 (defn group-by-naive [f coll]
   (reduce
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 {}
 coll))

 (defn group-by-red [f coll]
   (letfn [(reduce-groups
 ([] {})
 ([g1 g2]
   (merge-with concat g1 g2)))]
 (r/fold reduce-groups (r/map #(hash-map (f %) [%]) coll

 (defn -main
   [ args]
   (c/quick-bench (group-by #(mod % 29) (range 1)))
   (c/quick-bench (group-by-naive #(mod % 29) (range 1)))
   (c/quick-bench (group-by-red #(mod % 29) (range 1

 (available as a gist here: 
 https://gist.github.com/**4232044https://gist.github.com/4232044
 )

 The core and naive versions perform roughly equally (~4ms) while the
 reducers version takes 10x as much time (~40ms) on my two-core laptop.

 I'm absolutely sure I'm doing something wrong (there is probably too much
 memory allocated by the map function) and would like to hear the opinion of
 someone more knowledgeable with reducers. I just did not want the subject
 to be buried.

 Hope that still helps a bit,
 Balint

 ps. There are some tips and tricks in this post: http://www.thebusby.com/
 **2012/07/tips-tricks-with-**clojure-reducers.htmlhttp://www.thebusby.com/2012/07/tips-tricks-with-clojure-reducers.html

 On Monday, December 3, 2012 5:04:17 PM UTC+1, Las wrote:

 Hi,

 As I was trying to wrap my head around the reducers library[1], I
 thought implementing group-by would be a good exercise to gain some insight.

 After spending a few hours with it, I'm still pretty much clueless, so
 hope to find someone here to help me out:

 So if I understood the reducer lingo introduced in [2],[3] and group-by
 correctly, it reduces the following reducing function on a collection

 (fn group-by-reducef [keyfn ret x]
  (let [k (keyfn x)]
 (assoc ret 

Re: How was the skills matters conference in London (6. Dec)?

2012-12-07 Thread john
Thanks a lot Thomas
... I am looking forward to the not yet published podcast 18:00 - late 
Clojurex drinks 

Am Freitag, 7. Dezember 2012 12:33:20 UTC+1 schrieb Thomas:

 It was really great, all the videos are up already:

 http://skillsmatter.com/event/scala/clojure-exchange-2012

 Have a look.

 Thomas

 On Friday, December 7, 2012 10:59:32 AM UTC, john wrote:

 Hi,
 I couldn't make it to the skill matters conference in London ))-:
 just being curious,... how was it? Any news? was there a main theme?

 Many  Greetings
 John



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

Re: group-by vs. reducers?

2012-12-07 Thread László Török
Hi,

shouldn't

(fn [groups a]
  (assoc groups (f a) (conj (get groups a []) a)))

be

(fn [groups a]
  (let [k (f a)]
(assoc groups k (conj (get groups k []) a

?

Las

2012/12/7 Christophe Grand christo...@cgrand.net

 Hi,

 There are indeed too much allocationfoing on in your r/map.
 You don't need the rmap,

 Start from a plain old reduce like your reduce-by-naive, replace reduce by
 r/fold, remove the seed and add the combine-fn (which now provides the
 seed):

 (defn group-by-red [f coll]
   (r/fold
 (partial merge-with concat)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))


 Crude benchmark;
  (let [v (vec (range 100))]
   (dotimes [n 5]
 (println Run n)
 (time (group-by #(mod % 29) v))
 (time (group-by-naive #(mod % 29) v))
 (time (group-by-red #(mod % 29) v
 Run 0
 Elapsed time: 938.878 msecs
 Elapsed time: 778.161 msecs
 Elapsed time: 1035.997 msecs
 Run 1
 Elapsed time: 715.352 msecs
 Elapsed time: 771.913 msecs
 Elapsed time: 840.264 msecs
 Run 2
 Elapsed time: 656.588 msecs
 Elapsed time: 700.114 msecs
 Elapsed time: 777.323 msecs
 Run 3
 Elapsed time: 731.781 msecs
 Elapsed time: 713.547 msecs
 Elapsed time: 875.801 msecs
 Run 4
 Elapsed time: 689.711 msecs
 Elapsed time: 710.728 msecs
 Elapsed time: 1112.609 msecs
 nil

 Let's play with the granularity (defaults to 512)
 (defn group-by-red [f coll]
   (r/fold 2048
 (partial merge-with concat)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))

 Re-benchmark:
 Run 0
 Elapsed time: 810.676 msecs
 Elapsed time: 736.764 msecs
 Elapsed time: 547.651 msecs
 Run 1
 Elapsed time: 681.249 msecs
 Elapsed time: 850.046 msecs
 Elapsed time: 521.27 msecs
 Run 2
 Elapsed time: 669.385 msecs
 Elapsed time: 712.15 msecs
 Elapsed time: 518.502 msecs
 Run 3
 Elapsed time: 673.108 msecs
 Elapsed time: 745.688 msecs
 Elapsed time: 542.837 msecs
 Run 4
 Elapsed time: 654.196 msecs
 Elapsed time: 723.074 msecs
 Elapsed time: 506.861 msecs

 Note that you are not exactly comparing apples to apples since
 group-by-red is returning maps whose values are unrealized lazy sequence
 (concats of concats of ocncats of vactors) instead of vectors

 (defn group-by-red [f coll]
   (r/fold 2048
 (partial merge-with into)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))

 Run 0
 Elapsed time: 763.455 msecs
 Elapsed time: 763.501 msecs
 Elapsed time: 681.075 msecs
 Run 1
 Elapsed time: 645.52 msecs
 Elapsed time: 731.545 msecs
 Elapsed time: 476.381 msecs
 Run 2
 Elapsed time: 660.775 msecs
 Elapsed time: 728.19 msecs
 Elapsed time: 475.543 msecs
 Run 3
 Elapsed time: 657.255 msecs
 Elapsed time: 725.995 msecs
 Elapsed time: 494.038 msecs
 Run 4
 Elapsed time: 647.53 msecs
 Elapsed time: 731.085 msecs
 Elapsed time: 538.649 msecs

 hth,

 Christophe


 On Fri, Dec 7, 2012 at 10:30 AM, Balint Erdi balint.e...@gmail.comwrote:

 BTW I understood the most about reducers (still not quite there yet,
 though :) ) from Rich Hickey's talk at EuroClojure:

 https://vimeo.com/45561411


 On Friday, December 7, 2012 10:21:59 AM UTC+1, Balint Erdi wrote:

 Hey,

 Reducers is fascinating and quite complex at the same time. I feel like
 best practices around it has not quite solidified yet.

 Here is how I made your example work:

 (ns group-by-reducers.core
   (:require [clojure.core.reducers :as r :only [fold reduce map]])
   (:require [criterium.core :as c]))

 (defn group-by-naive [f coll]
   (reduce
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 {}
 coll))

 (defn group-by-red [f coll]
   (letfn [(reduce-groups
 ([] {})
 ([g1 g2]
   (merge-with concat g1 g2)))]
 (r/fold reduce-groups (r/map #(hash-map (f %) [%]) coll

 (defn -main
   [ args]
   (c/quick-bench (group-by #(mod % 29) (range 1)))
   (c/quick-bench (group-by-naive #(mod % 29) (range 1)))
   (c/quick-bench (group-by-red #(mod % 29) (range 1

 (available as a gist here: 
 https://gist.github.com/**4232044https://gist.github.com/4232044
 )

 The core and naive versions perform roughly equally (~4ms) while the
 reducers version takes 10x as much time (~40ms) on my two-core laptop.

 I'm absolutely sure I'm doing something wrong (there is probably too
 much memory allocated by the map function) and would like to hear the
 opinion of someone more knowledgeable with reducers. I just did not want
 the subject to be buried.

 Hope that still helps a bit,
 Balint

 ps. There are some tips and tricks in this post:
 http://www.thebusby.com/**2012/07/tips-tricks-with-**
 clojure-reducers.htmlhttp://www.thebusby.com/2012/07/tips-tricks-with-clojure-reducers.html

 On Monday, December 3, 2012 5:04:17 PM UTC+1, Las wrote:

 Hi,

 As I was trying to wrap my head around the reducers library[1], I
 thought implementing group-by would be a good exercise to gain some 
 

Re: group-by vs. reducers?

2012-12-07 Thread Christophe Grand
Absolutely


On Fri, Dec 7, 2012 at 1:29 PM, László Török ltoro...@gmail.com wrote:

 Hi,

 shouldn't

 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))

 be

 (fn [groups a]
   (let [k (f a)]
 (assoc groups k (conj (get groups k []) a

 ?

 Las

 2012/12/7 Christophe Grand christo...@cgrand.net

 Hi,

 There are indeed too much allocationfoing on in your r/map.
 You don't need the rmap,

 Start from a plain old reduce like your reduce-by-naive, replace reduce
 by r/fold, remove the seed and add the combine-fn (which now provides the
 seed):

 (defn group-by-red [f coll]
   (r/fold
 (partial merge-with concat)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))


 Crude benchmark;
  (let [v (vec (range 100))]
   (dotimes [n 5]
 (println Run n)
 (time (group-by #(mod % 29) v))
 (time (group-by-naive #(mod % 29) v))
 (time (group-by-red #(mod % 29) v
 Run 0
 Elapsed time: 938.878 msecs
 Elapsed time: 778.161 msecs
 Elapsed time: 1035.997 msecs
 Run 1
 Elapsed time: 715.352 msecs
 Elapsed time: 771.913 msecs
 Elapsed time: 840.264 msecs
 Run 2
 Elapsed time: 656.588 msecs
 Elapsed time: 700.114 msecs
 Elapsed time: 777.323 msecs
 Run 3
 Elapsed time: 731.781 msecs
 Elapsed time: 713.547 msecs
 Elapsed time: 875.801 msecs
 Run 4
 Elapsed time: 689.711 msecs
 Elapsed time: 710.728 msecs
 Elapsed time: 1112.609 msecs
 nil

 Let's play with the granularity (defaults to 512)
 (defn group-by-red [f coll]
   (r/fold 2048
 (partial merge-with concat)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))

 Re-benchmark:
 Run 0
 Elapsed time: 810.676 msecs
 Elapsed time: 736.764 msecs
 Elapsed time: 547.651 msecs
 Run 1
 Elapsed time: 681.249 msecs
 Elapsed time: 850.046 msecs
 Elapsed time: 521.27 msecs
 Run 2
 Elapsed time: 669.385 msecs
 Elapsed time: 712.15 msecs
 Elapsed time: 518.502 msecs
 Run 3
 Elapsed time: 673.108 msecs
 Elapsed time: 745.688 msecs
 Elapsed time: 542.837 msecs
 Run 4
 Elapsed time: 654.196 msecs
 Elapsed time: 723.074 msecs
 Elapsed time: 506.861 msecs

 Note that you are not exactly comparing apples to apples since
 group-by-red is returning maps whose values are unrealized lazy sequence
 (concats of concats of ocncats of vactors) instead of vectors

 (defn group-by-red [f coll]
   (r/fold 2048
 (partial merge-with into)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))

 Run 0
 Elapsed time: 763.455 msecs
 Elapsed time: 763.501 msecs
 Elapsed time: 681.075 msecs
 Run 1
 Elapsed time: 645.52 msecs
 Elapsed time: 731.545 msecs
 Elapsed time: 476.381 msecs
 Run 2
 Elapsed time: 660.775 msecs
 Elapsed time: 728.19 msecs
 Elapsed time: 475.543 msecs
 Run 3
 Elapsed time: 657.255 msecs
 Elapsed time: 725.995 msecs
 Elapsed time: 494.038 msecs
 Run 4
 Elapsed time: 647.53 msecs
 Elapsed time: 731.085 msecs
 Elapsed time: 538.649 msecs

 hth,

 Christophe


 On Fri, Dec 7, 2012 at 10:30 AM, Balint Erdi balint.e...@gmail.comwrote:

 BTW I understood the most about reducers (still not quite there yet,
 though :) ) from Rich Hickey's talk at EuroClojure:

 https://vimeo.com/45561411


 On Friday, December 7, 2012 10:21:59 AM UTC+1, Balint Erdi wrote:

 Hey,

 Reducers is fascinating and quite complex at the same time. I feel like
 best practices around it has not quite solidified yet.

 Here is how I made your example work:

 (ns group-by-reducers.core
   (:require [clojure.core.reducers :as r :only [fold reduce map]])
   (:require [criterium.core :as c]))

 (defn group-by-naive [f coll]
   (reduce
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 {}
 coll))

 (defn group-by-red [f coll]
   (letfn [(reduce-groups
 ([] {})
 ([g1 g2]
   (merge-with concat g1 g2)))]
 (r/fold reduce-groups (r/map #(hash-map (f %) [%]) coll

 (defn -main
   [ args]
   (c/quick-bench (group-by #(mod % 29) (range 1)))
   (c/quick-bench (group-by-naive #(mod % 29) (range 1)))
   (c/quick-bench (group-by-red #(mod % 29) (range 1

 (available as a gist here: 
 https://gist.github.com/**4232044https://gist.github.com/4232044
 )

 The core and naive versions perform roughly equally (~4ms) while the
 reducers version takes 10x as much time (~40ms) on my two-core laptop.

 I'm absolutely sure I'm doing something wrong (there is probably too
 much memory allocated by the map function) and would like to hear the
 opinion of someone more knowledgeable with reducers. I just did not want
 the subject to be buried.

 Hope that still helps a bit,
 Balint

 ps. There are some tips and tricks in this post:
 http://www.thebusby.com/**2012/07/tips-tricks-with-**
 clojure-reducers.htmlhttp://www.thebusby.com/2012/07/tips-tricks-with-clojure-reducers.html

 On Monday, December 3, 2012 5:04:17 PM UTC+1, Las wrote:

 Hi,

 As I was trying to wrap my head around the 

Re: group-by vs. reducers?

2012-12-07 Thread Balint Erdi
Thank you, Christophe, that makes total sense.

Interestingly, on my machine, the reducers version is still slower:

Run # 0
Elapsed time: 1105.586 msecs
Elapsed time: 685.8 msecs
Elapsed time: 549.969 msecs
Run # 1
Elapsed time: 497.831 msecs
Elapsed time: 489.932 msecs
Elapsed time: 520.38 msecs
Run # 2
Elapsed time: 363.873 msecs
Elapsed time: 489.529 msecs
Elapsed time: 556.117 msecs
Run # 3
Elapsed time: 357.822 msecs
Elapsed time: 429.894 msecs
Elapsed time: 540.975 msecs
Run # 4
Elapsed time: 425.276 msecs
Elapsed time: 431.819 msecs
Elapsed time: 528.8 msecs

I guess the JVM finds some serious optimizations during the runs for the 
non-reducer versions. I saw the same difference when using criterium for 
benchmarking.

Balint

On Friday, December 7, 2012 1:44:58 PM UTC+1, Christophe Grand wrote:

 Absolutely


 On Fri, Dec 7, 2012 at 1:29 PM, László Török ltor...@gmail.comjavascript:
  wrote:

 Hi,

 shouldn't 

 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))

 be 

 (fn [groups a]
   (let [k (f a)]
 (assoc groups k (conj (get groups k []) a

 ?

 Las

 2012/12/7 Christophe Grand chris...@cgrand.net javascript:

 Hi,

 There are indeed too much allocationfoing on in your r/map.
 You don't need the rmap,

 Start from a plain old reduce like your reduce-by-naive, replace reduce 
 by r/fold, remove the seed and add the combine-fn (which now provides the 
 seed):

 (defn group-by-red [f coll]
   (r/fold
 (partial merge-with concat)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))


 Crude benchmark;
  (let [v (vec (range 100))] 
   (dotimes [n 5]
 (println Run n)
 (time (group-by #(mod % 29) v))
 (time (group-by-naive #(mod % 29) v))
 (time (group-by-red #(mod % 29) v
 Run 0
 Elapsed time: 938.878 msecs
 Elapsed time: 778.161 msecs
 Elapsed time: 1035.997 msecs
 Run 1
 Elapsed time: 715.352 msecs
 Elapsed time: 771.913 msecs
 Elapsed time: 840.264 msecs
 Run 2
 Elapsed time: 656.588 msecs
 Elapsed time: 700.114 msecs
 Elapsed time: 777.323 msecs
 Run 3
 Elapsed time: 731.781 msecs
 Elapsed time: 713.547 msecs
 Elapsed time: 875.801 msecs
 Run 4
 Elapsed time: 689.711 msecs
 Elapsed time: 710.728 msecs
 Elapsed time: 1112.609 msecs
 nil

 Let's play with the granularity (defaults to 512)
 (defn group-by-red [f coll]
   (r/fold 2048
 (partial merge-with concat)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))

 Re-benchmark:
 Run 0
 Elapsed time: 810.676 msecs
 Elapsed time: 736.764 msecs
 Elapsed time: 547.651 msecs
 Run 1
 Elapsed time: 681.249 msecs
 Elapsed time: 850.046 msecs
 Elapsed time: 521.27 msecs
 Run 2
 Elapsed time: 669.385 msecs
 Elapsed time: 712.15 msecs
 Elapsed time: 518.502 msecs
 Run 3
 Elapsed time: 673.108 msecs
 Elapsed time: 745.688 msecs
 Elapsed time: 542.837 msecs
 Run 4
 Elapsed time: 654.196 msecs
 Elapsed time: 723.074 msecs
 Elapsed time: 506.861 msecs

 Note that you are not exactly comparing apples to apples since 
 group-by-red is returning maps whose values are unrealized lazy sequence 
 (concats of concats of ocncats of vactors) instead of vectors

 (defn group-by-red [f coll]
   (r/fold 2048
 (partial merge-with into)
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 coll))

 Run 0
 Elapsed time: 763.455 msecs
 Elapsed time: 763.501 msecs
 Elapsed time: 681.075 msecs
 Run 1
 Elapsed time: 645.52 msecs
 Elapsed time: 731.545 msecs
 Elapsed time: 476.381 msecs
 Run 2
 Elapsed time: 660.775 msecs
 Elapsed time: 728.19 msecs
 Elapsed time: 475.543 msecs
 Run 3
 Elapsed time: 657.255 msecs
 Elapsed time: 725.995 msecs
 Elapsed time: 494.038 msecs
 Run 4
 Elapsed time: 647.53 msecs
 Elapsed time: 731.085 msecs
 Elapsed time: 538.649 msecs

 hth,

 Christophe


 On Fri, Dec 7, 2012 at 10:30 AM, Balint Erdi 
 balin...@gmail.comjavascript:
  wrote:

 BTW I understood the most about reducers (still not quite there yet, 
 though :) ) from Rich Hickey's talk at EuroClojure:

 https://vimeo.com/45561411


 On Friday, December 7, 2012 10:21:59 AM UTC+1, Balint Erdi wrote:

 Hey,

 Reducers is fascinating and quite complex at the same time. I feel 
 like best practices around it has not quite solidified yet.

 Here is how I made your example work:

 (ns group-by-reducers.core
   (:require [clojure.core.reducers :as r :only [fold reduce map]])
   (:require [criterium.core :as c]))

 (defn group-by-naive [f coll]
   (reduce
 (fn [groups a]
   (assoc groups (f a) (conj (get groups a []) a)))
 {}
 coll))

 (defn group-by-red [f coll]
   (letfn [(reduce-groups
 ([] {})
 ([g1 g2]
   (merge-with concat g1 g2)))]
 (r/fold reduce-groups (r/map #(hash-map (f %) [%]) coll

 (defn -main
   [ args]
   (c/quick-bench (group-by #(mod % 29) (range 1)))
   (c/quick-bench (group-by-naive #(mod % 29) (range 1)))
   (c/quick-bench (group-by-red 

Re: [lein-cljsbuild] exclude a cljs from compilation

2012-12-07 Thread Mimmo Cosenza
Hi Evan,
Brenton Ashworth said that this kind of options should not be added to the 
compiler, but to the tools that use the compiler.

Could yowl  please give me some advice from where to start patching 
lein-cljsbuild following Brenton advice?

Thank so much

Mimmo

Here is Brenton comment on :exclude option.


http://dev.clojure.org/jira/browse/CLJS-419?focusedCommentId=30185page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-30185
On Dec 7, 2012, at 7:04 AM, Evan Mezeske emeze...@gmail.com wrote:

 Yeah, I saw that.  Very cool stuff!  Glad you could contribute.
 
 On Thursday, December 6, 2012 7:14:21 PM UTC-8, Mimmo Cosenza wrote:
 Hi Evan,
 just to let you that I submitted on clojurescript repo the patch to exclude a 
 file and/or a directory of cljs from compilation. 
 
 the new compiler option is :exclude and accepts both a name of a file or 
 directory o a vector of files and/or directories.
 
 Hope it helps
 
 mimmo 
 
  
 On Nov 16, 2012, at 10:39 AM, Mimmo Cosenza mimmo@gmail.com wrote:
 
 
 On Friday, November 16, 2012 8:28:18 AM UTC+1, Evan Mezeske wrote:
 If you wouldn't mind, please create a new issue, or maybe just add to this 
 one: https://github.com/emezeske/lein-cljsbuild/issues/108 .
 
 done. added issue #157 with reference to #108 and viceversa.
 
 thanks 
 mimmo
  
 
 Thanks,
 -Evan
 
 On Thursday, November 15, 2012 6:56:45 AM UTC-7, Mimmo Cosenza wrote:
 Hi all, 
 my question is the following: 
 
 - I like to have the usual brepl connect to the browser during development 
 - I like to have the same source-base (e.g. :source-path src/cljs) for 
 both the development and production builds (e.g. :builds {:prod {.} 
 {:dev {.} of :cljsbuild keyword) 
 
 Is there a way in lein-cljsbuild to reach this goal? I'd like to write 
 something like this in :prod build 
 
 (defproject 
 
   :cljsbuild {:builds 
   {:dev {:source-path src/cljs 
  :compiler :output-to 
 resources/public/js/main_debug.js 
:optimizations :whitespace 
:pretty-print true}} 
 :prod {:source-path src/cljs 
 ;;; here a key/values to exclude some file in 
 :source-path from compilation, something like :exclude [afil.cljs 
 another-file.cljs] 
 :compiler :output-to 
 resources/public/js/main.js 
:optimizations :advanced}}) 
 
 
 Thanks for the attention 
 
 Mimmo 
 
 
 -- 
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@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+u...@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

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

[ANN] New functional programming group (Western Massachusetts)

2012-12-07 Thread Chas Emerick
With help from some friends, I am starting a new FP group here in Western 
Massachusetts:

  http://www.meetup.com/Functional-Programming-Connoisseurs/

From the meetup.com description:

  Open to any and all that have functional and logical tastes in programming
  languages and data models. Clojure, Scala, Erlang, Schemes, Prologs, F#, MLs,
  concatenative (e.g. Factor), and so on. Many of us have experience and 
interest
  in building distributed, large-scale systems. Many of us also happen to be
  independent contractors, solo/entrepreneurs, business owners, and otherwise
  interested in building killer businesses as well as awesome software. 
Depending
  on the week/month, expect a mix of free-for-all conversation and hacking,
  lightning talks, and the occasional prepared presentation.

Our first meeting will be in January (date and location TBD).  If you're in the 
area and on this list, stop by and say 'hi'!  Of course, if you would like to 
give a relevant talk, presentation, or demonstration, by all means shoot me an 
email.

Cheers,

- Chas

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


Re: [lein-cljsbuild] exclude a cljs from compilation

2012-12-07 Thread David Nolen
I chimed in on the patch. Taking Brenton's approach sounds like it would be
significantly simpler and require a very small patch to lein-cljsbuild.


On Fri, Dec 7, 2012 at 1:24 PM, Mimmo Cosenza mimmo.cose...@gmail.comwrote:

 Hi Evan,
 Brenton Ashworth said that this kind of options should not be added to the
 compiler, but to the tools that use the compiler.

 Could yowl  please give me some advice from where to start
 patching lein-cljsbuild following Brenton advice?

 Thank so much

 Mimmo

 Here is Brenton comment on :exclude option.



 http://dev.clojure.org/jira/browse/CLJS-419?focusedCommentId=30185page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-30185

 On Dec 7, 2012, at 7:04 AM, Evan Mezeske emeze...@gmail.com wrote:

 Yeah, I saw that.  Very cool stuff!  Glad you could contribute.

 On Thursday, December 6, 2012 7:14:21 PM UTC-8, Mimmo Cosenza wrote:

 Hi Evan,
 just to let you that I submitted on clojurescript repo the patch to
 exclude a file and/or a directory of cljs from compilation.

 the new compiler option is :exclude and accepts both a name of a file or
 directory o a vector of files and/or directories.

 Hope it helps

 mimmo


 On Nov 16, 2012, at 10:39 AM, Mimmo Cosenza mimmo@gmail.com wrote:


 On Friday, November 16, 2012 8:28:18 AM UTC+1, Evan Mezeske wrote:

 If you wouldn't mind, please create a new issue, or maybe just add to
 this one: 
 https://github.com/**emezeske/lein-cljsbuild/**issues/108https://github.com/emezeske/lein-cljsbuild/issues/108.


 done. added issue #157 with reference to #108 and viceversa.

 thanks
 mimmo



 Thanks,
 -Evan

 On Thursday, November 15, 2012 6:56:45 AM UTC-7, Mimmo Cosenza wrote:

 Hi all,
 my question is the following:

 - I like to have the usual brepl connect to the browser during
 development
 - I like to have the same source-base (e.g. :source-path src/cljs)
 for both the development and production builds (e.g. :builds {:prod {.}
 {:dev {.} of :cljsbuild keyword)

 Is there a way in lein-cljsbuild to reach this goal? I'd like to write
 something like this in :prod build

 (defproject

   :cljsbuild {:builds
   {:dev {:source-path src/cljs
  :compiler :output-to resources/public/js/main_
 **debug.js
:optimizations :whitespace
:pretty-print true}}
 :prod {:source-path src/cljs
 ;;; here a key/values to exclude some file
 in :source-path from compilation, something like :exclude [afil.cljs
 another-file.cljs]
 :compiler :output-to
 resources/public/js/main.js
:optimizations :advanced}})


 Thanks for the attention

 Mimmo


 --
 You received this message because you are subscribed to the Google
 Groups Clojure group.
 To post to this group, send email to clo...@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+u...@**googlegroups.com
 For more options, visit this group at
 http://groups.google.com/**group/clojure?hl=enhttp://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


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

Re: [ANN] sublime-lispindent, clojure indenting for sublime text 2

2012-12-07 Thread Anthony Grimes
I opened a report on ST2's userecho a long time ago about the terrible 
indentation. If you'd like to see if fixed in Sublime Text 2 itself, please 
upvote: 
http://sublimetext.userecho.com/topic/98139-clojure-auto-indentation-is-almost-never-correct/

On Monday, November 12, 2012 10:25:38 AM UTC-6, Jonathan Fischer Friberg 
wrote:

 Dear clojure mailing list,

 As the indenting for clojure (and lisp in general) was very lacking
 in sublime, I decided to make a plugin:

 https://github.com/odyssomay/sublime-lispindent

 I hope someone finds this useful.

 By the way, if someone with a mac could try the keyboard shortcuts that 
 would be great.
 I don't own a mac so I cannot test them.

 Sincerely,
 Jonathan


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

Re: How was the skills matters conference in London (6. Dec)?

2012-12-07 Thread SkillsMatterMike
'Late Clojurex drinks' was an incredible talk. It changed the very way I 
view and interact with the the world.

On another note all the recordings are now actually up!

I particularly enjoyed Sam Aaron's one
http://skillsmatter.com/podcast/home-27/live-programming-with-clojure/mh-6189

On Friday, December 7, 2012 12:05:26 PM UTC, john wrote:

 Thanks a lot Thomas
 ... I am looking forward to the not yet published podcast 18:00 - late 
 Clojurex drinks 

 Am Freitag, 7. Dezember 2012 12:33:20 UTC+1 schrieb Thomas:

 It was really great, all the videos are up already:

 http://skillsmatter.com/event/scala/clojure-exchange-2012

 Have a look.

 Thomas

 On Friday, December 7, 2012 10:59:32 AM UTC, john wrote:

 Hi,
 I couldn't make it to the skill matters conference in London ))-:
 just being curious,... how was it? Any news? was there a main theme?

 Many  Greetings
 John



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

let binding for functions

2012-12-07 Thread Jingjing
I'm a clojure newbie. Why does the compiler complain about being unable to 
resolve cube-root-recur on line 17? thanks

  1 (def cube-root 

  2   (fn [n]   
   
  3 (let   

  4   [abs 

  5(fn [n] 

  6  (if ( n 0) n (- 0 n)))   

  7good-enough? 
   
  8(fn [guess] 

  9  ( (abs (- (* guess guess guess) n)) 0.0001)) 

 10improve-guess   

 11(fn [guess] 

 12  (/ (+ (/ n (* guess guess)) (* 2 guess)) 3))   
   
 13cube-root-recur 

 14(fn [guess] 

 15  (cond 

 16(good-enough? guess) guess   
   
 17:else (cube-root-recur (improve-guess guess] 
   
 18   (cube-root-recur 1   

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

A Practical Optional Type System for Clojure - Final Honours Dissertation

2012-12-07 Thread Ambrose Bonnaire-Sergeant
Hi everyone,

Very pleased to have handed in my final honours dissertation today. Thanks
to all that submitted corrections and offered encouragement.

https://github.com/downloads/frenchy64/papers/ambrose-honours.pdf

Cheers,
Ambrose

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

Re: [ANN] New functional programming group (Western Massachusetts)

2012-12-07 Thread Christopher Meiklejohn
On Friday, December 7, 2012 at 2:35 PM, Chas Emerick wrote:
 With help from some friends, I am starting a new FP group here in Western 
 Massachusetts:

I just thought that I would mention that I've also recently started a FP group 
in Providence, Rhode Island; our second meeting is on Jan. 28 at Swipely's 
offices.

http://www.meetup.com/Providence-Functional-Programmers/

- Chris

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


Re: A Practical Optional Type System for Clojure - Final Honours Dissertation

2012-12-07 Thread David Nolen
Congrats! :)

David


On Fri, Dec 7, 2012 at 7:33 AM, Ambrose Bonnaire-Sergeant 
abonnaireserge...@gmail.com wrote:

 Hi everyone,

 Very pleased to have handed in my final honours dissertation today. Thanks
 to all that submitted corrections and offered encouragement.

 https://github.com/downloads/frenchy64/papers/ambrose-honours.pdf

 Cheers,
 Ambrose

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

abysmal multicore performance, especially on AMD processors

2012-12-07 Thread Lee Spector

I've been running compute intensive (multi-day), highly parallelizable Clojure 
processes on high-core-count machines and blithely assuming that since I saw 
near maximal CPU utilization in top and the like that I was probably getting 
good speedups. 

But a colleague recently did some tests and the results are really quite 
alarming. 

On intel machines we're seeing speedups but much less than I expected -- about 
a 2x speedup going from 1 to 8 cores.

But on AMD processors we're seeing SLOWDOWNS, with the same tests taking almost 
twice as long on 8 cores as on 1.

I'm baffled, and unhappy that my runs are probably going slower on 48-core and 
64-core nodes than on single-core nodes. 

It's possible that I'm just doing something wrong in the way that I dispatch 
the tasks, or that I've missed some Clojure or JVM setting... but right now I'm 
mystified and would really appreciate some help.

I'm aware that there's overhead for multicore distribution and that one can 
expect slowdowns if the computations that are being distributed are fast 
relative to the dispatch overhead, but this should not be the case here. We're 
distributing computations that take seconds or minutes, and not huge numbers of 
them (at least in our tests while trying to figure out what's going on).

I'm also aware that the test that produced the data I give below, insofar as it 
uses pmap to do the distribution, may leave cores idle for a bit if some tasks 
take a lot longer than others, because of the way that pmap allocates cores to 
threads. But that also shouldn't be a big issue here because for this test all 
of the threads are doing the exact same computation. And I also tried using an 
agent-based dispatch approach that shouldn't have the pmap thread allocation 
issue, and the results were about the same.

Note also that all of the computations in this test are purely functional and 
independent -- there shouldn't be any resource contention issues.

The test: I wrote a time-consuming function that just does a bunch of math and 
list manipulation (which is what takes a lot of time in my real applications):

(defn burn 
  ([] (loop [i 0
 value '()]
(if (= i 1)
  (count (last (take 1 (iterate reverse value
  (recur (inc i)
 (cons 
   (* (int i) 
  (+ (float i) 
 (- (int i) 
(/ (float i) 
   (inc (int i))
   value)
  ([_] (burn)))

Then I have a main function like this:

(defn -main 
  [ args]
  (time (doall (pmap burn (range 8
  (System/exit 0))

We run it with lein run (we've tried both leingingen 1.7.1 and 
2.0.0-preview10) with Java 1.7.0_03 Java HotSpot(TM) 64-Bit Server VM. We also 
tried Java 1.6.0_22. We've tried various JVM memory options (via :jvm-opts with 
-Xmx and -Xms settings) and also with and without -XX:+UseParallelGC. None of 
this seems to change the picture substantially.

The results that we get generally look like this:

- On an Intel Core i7 3770K with 8 cores and 16GB of RAM, running the code 
above, it takes about 45 seconds (and all cores appear to be fully loaded as it 
does so). If we change the pmap to just plain map, so that we use only a single 
core, the time goes up to about 1 minute and 36 seconds. So the speedup for 8 
cores is just about 2x, even though there are 8 completely independent tasks. 
So that's pretty depressing.

- But much worse: on a 4 x Opteron 6272 with 48 cores and 32GB of RAM, running 
the same test (with pmap) takes about 4 minutes and 2 seconds. That's really 
slow! Changing the pmap to map here produces a runtime of about 2 minutes and 
20 seconds. So it's quite a bit faster on one core than on 8! And all of these 
times are terrible compared to those on the intel.

Another strange observation is that we can run multiple instances of the test 
on the same machine and (up to some limit, presumably) they don't seem to slow 
each other down, even though just one instance of the test appears to be maxing 
out all of the CPU according to top. I suppose that means that top isn't 
telling me what I thought -- my colleague says it can mean that something is 
blocked in some way with a full instruction queue. But I'm not interested in 
running multiple instances. I have single computations that involve multiple 
expensive but independent subcomputations, and I want to farm those 
subcomputations out to multiple cores -- and get speedups as a result. My 
subcomputations are so completely independent that I think I should be able to 
get speedups approaching a factor of n for n cores, but what I see is a factor 
of only about 2 on intel machines, and a bizarre factor of about 1/2 on AMD 
machines.

Any help would be greatly appreciated!

Thanks,

 -Lee

--
Lee Spector, Professor of Computer Science
Cognitive Science, Hampshire College
893 West Street, Amherst, MA 01002-3359

Re: abysmal multicore performance, especially on AMD processors

2012-12-07 Thread Andy Fingerhut
Lee:

I'll just give a brief description right now, but one thing I've found in the 
past on a 2-core machine that was achieving much less than 2x speedup was 
memory bandwidth being the limiting factor.

Not all Clojure code allocates memory, but a lot does.  If the hardware in a 
system can write at rate X from a multicore processor to main memory, and a 
single-threaded Clojure program writes to memory at rate 0.5*X, then the most 
speedup you will ever get out of multicore execution of the same code on N 
cores will be 2x, no matter how large N is.

As one way to see if this is the problem, you could try changing your burn 
function so that instead of doing cons to build up a list result, first 
allocate a Java mutable array before the loop that is as large as you need it 
to be at the end, and write values into that.  You can convert it to some other 
Clojure type at the end of the loop if you prefer.


I have some C benchmark programs that test memory read and write bandwidth on 
single and multiple cores you can run on your Intel machine to see if that 
might be the issue.  If this is the issue, I would expect to see at least a 
little speedup from 1 core to multiple cores, but capped at some maximum 
speedup that is determined by the memory bandwidth, not the number of cores you 
run in parallel.

I don't currently have any guess about what might be happening with the AMD 
multicore machine.  If you are interested in wild guessing, perhaps there could 
be some kind of multicore cache coherency protocol that is badly configured, 
causing cache lines to be frequently invalidated when multiple cores are 
sharing memory?  That would make more sense if multiple cores were reading from 
and writing to the same cache lines, which doesn't seem terribly likely for a 
typical Clojure program.

Let me know if you are interested and I will find those C programs for you to 
try out.  I got them from somewhere on the Internet and may have tweaked them a 
little bit.

Andy


On Dec 7, 2012, at 5:25 PM, Lee Spector wrote:

 
 I've been running compute intensive (multi-day), highly parallelizable 
 Clojure processes on high-core-count machines and blithely assuming that 
 since I saw near maximal CPU utilization in top and the like that I was 
 probably getting good speedups. 
 
 But a colleague recently did some tests and the results are really quite 
 alarming. 
 
 On intel machines we're seeing speedups but much less than I expected -- 
 about a 2x speedup going from 1 to 8 cores.
 
 But on AMD processors we're seeing SLOWDOWNS, with the same tests taking 
 almost twice as long on 8 cores as on 1.
 
 I'm baffled, and unhappy that my runs are probably going slower on 48-core 
 and 64-core nodes than on single-core nodes. 
 
 It's possible that I'm just doing something wrong in the way that I dispatch 
 the tasks, or that I've missed some Clojure or JVM setting... but right now 
 I'm mystified and would really appreciate some help.
 
 I'm aware that there's overhead for multicore distribution and that one can 
 expect slowdowns if the computations that are being distributed are fast 
 relative to the dispatch overhead, but this should not be the case here. 
 We're distributing computations that take seconds or minutes, and not huge 
 numbers of them (at least in our tests while trying to figure out what's 
 going on).
 
 I'm also aware that the test that produced the data I give below, insofar as 
 it uses pmap to do the distribution, may leave cores idle for a bit if some 
 tasks take a lot longer than others, because of the way that pmap allocates 
 cores to threads. But that also shouldn't be a big issue here because for 
 this test all of the threads are doing the exact same computation. And I also 
 tried using an agent-based dispatch approach that shouldn't have the pmap 
 thread allocation issue, and the results were about the same.
 
 Note also that all of the computations in this test are purely functional and 
 independent -- there shouldn't be any resource contention issues.
 
 The test: I wrote a time-consuming function that just does a bunch of math 
 and list manipulation (which is what takes a lot of time in my real 
 applications):
 
 (defn burn 
  ([] (loop [i 0
 value '()]
(if (= i 1)
  (count (last (take 1 (iterate reverse value
  (recur (inc i)
 (cons 
   (* (int i) 
  (+ (float i) 
 (- (int i) 
(/ (float i) 
   (inc (int i))
   value)
  ([_] (burn)))
 
 Then I have a main function like this:
 
 (defn -main 
  [ args]
  (time (doall (pmap burn (range 8
  (System/exit 0))
 
 We run it with lein run (we've tried both leingingen 1.7.1 and 
 2.0.0-preview10) with Java 1.7.0_03 Java HotSpot(TM) 64-Bit Server VM. We 
 also tried Java 1.6.0_22. We've tried various JVM memory options (via 
 

Re: abysmal multicore performance, especially on AMD processors

2012-12-07 Thread Lee Spector

Thanks Andy.

My applications definitely allocate a lot of memory, which is reflected in all 
of that consing in the test I was using. It'd be hard to do what we do in any 
other way. I can see how a test using a Java mutable array would help to 
diagnose the problem, but if that IS the problem then it sounds like there'd be 
no solution short of radically re-engineering our systems. That would be sad!

My colleague who's running the tests is out for the weekend but we'll talk 
early next week and get back to you if we want to try your C programs etc.

 -Lee


On Dec 7, 2012, at 8:41 PM, Andy Fingerhut wrote:

 Lee:
 
 I'll just give a brief description right now, but one thing I've found in the 
 past on a 2-core machine that was achieving much less than 2x speedup was 
 memory bandwidth being the limiting factor.
 
 Not all Clojure code allocates memory, but a lot does.  If the hardware in a 
 system can write at rate X from a multicore processor to main memory, and a 
 single-threaded Clojure program writes to memory at rate 0.5*X, then the most 
 speedup you will ever get out of multicore execution of the same code on N 
 cores will be 2x, no matter how large N is.
 
 As one way to see if this is the problem, you could try changing your burn 
 function so that instead of doing cons to build up a list result, first 
 allocate a Java mutable array before the loop that is as large as you need it 
 to be at the end, and write values into that.  You can convert it to some 
 other Clojure type at the end of the loop if you prefer.
 
 
 I have some C benchmark programs that test memory read and write bandwidth on 
 single and multiple cores you can run on your Intel machine to see if that 
 might be the issue.  If this is the issue, I would expect to see at least a 
 little speedup from 1 core to multiple cores, but capped at some maximum 
 speedup that is determined by the memory bandwidth, not the number of cores 
 you run in parallel.
 
 I don't currently have any guess about what might be happening with the AMD 
 multicore machine.  If you are interested in wild guessing, perhaps there 
 could be some kind of multicore cache coherency protocol that is badly 
 configured, causing cache lines to be frequently invalidated when multiple 
 cores are sharing memory?  That would make more sense if multiple cores were 
 reading from and writing to the same cache lines, which doesn't seem terribly 
 likely for a typical Clojure program.
 
 Let me know if you are interested and I will find those C programs for you to 
 try out.  I got them from somewhere on the Internet and may have tweaked them 
 a little bit.
 
 Andy
 

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


Re: abysmal multicore performance, especially on AMD processors

2012-12-07 Thread Andy Fingerhut

On Dec 7, 2012, at 5:25 PM, Lee Spector wrote:

 
 Another strange observation is that we can run multiple instances of the test 
 on the same machine and (up to some limit, presumably) they don't seem to 
 slow each other down, even though just one instance of the test appears to be 
 maxing out all of the CPU according to top. I suppose that means that top 
 isn't telling me what I thought -- my colleague says it can mean that 
 something is blocked in some way with a full instruction queue. But I'm not 
 interested in running multiple instances. I have single computations that 
 involve multiple expensive but independent subcomputations, and I want to 
 farm those subcomputations out to multiple cores -- and get speedups as a 
 result. My subcomputations are so completely independent that I think I 
 should be able to get speedups approaching a factor of n for n cores, but 
 what I see is a factor of only about 2 on intel machines, and a bizarre 
 factor of about 1/2 on AMD machines.

Lee:

When you say we can run multiple instances of the test on the same machine, 
do you mean that, for example, on an 8 core machine you run 8 different JVMs in 
parallel, each doing a single-threaded 'map' in your Clojure code and not a 
'pmap'?

And what kinds of speedups does that achieve?

The results could help indicate whether the problem you are seeing is due to 
the hardware/OS, or something about multiple threads within a single JVM.

Andy

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