I haven't tried it, but for parallelisation it's sometimes worth starting 
from more "array-oriented" code, e.g.
(defn max-diff [check-until]
  (let [val (map #(Math/sqrt %) (range 1 check-until))]
    (reduce max (map #(Math/abs (- %1 %2)) (map #(Math/pow % 2) val) (map 
#(* % %) val)))))


On Friday, 11 April 2014 07:43:44 UTC+1, Cecil Westerhof wrote:
>
> 2014-04-11 3:10 GMT+02:00 Andy Fingerhut <andy.fi...@gmail.com<javascript:>
> >:
>
>> Your check-concurrent2 is a much better way to use parallelism in your 
>> program -- create a few threads, each of which does a lot of work.
>>
>> I haven't analyzed the values you are computing in detail, but note that 
>> your program still has lots of inter-thread 'communication' because of the 
>> use of a common atom in your main-function.  If you can get the correct 
>> final answer by having each thread calculate independent values, or 
>> collections of values, and then somehow combining them together when they 
>> are all finished with a bit of quick-running sequential code, that might 
>> give you even better parallel speedup than check-concurrent2.
>>
>
> I display immediately found worse values and those are dependent on what 
> is found in the other t
> hreads, but I will 
> think about it. I am certainly impressed by the result: less as 10% 
> overhead.
>
> I do not think that the inter-thread communication is a real problem, 
> because when I calculate it for ten time as much values it takes 309 
> seconds. That is almost exactly ten times as much time, so this 
> communication is (in this case) not a bottleneck.
>
>  
>
>> The use of asterisks at beginning and end of a symbol name is 
>> traditionally used on Clojure (and Common Lisp, from whence this tradition 
>> came) if the var is dynamically bound, meaning different threads typically 
>> do things like (binding [*dynamic-var* value-to-use-in-my-thread] <code 
>> here>).  There is no need for that in your program, and leaving off the 
>> asterisks (or "earmuffs") is common practice.
>>
>
> So my code is not to bad? :-D
>
>  
>
>>  For the explanation of the 1-minute delay, see the end of the last 
>> example on ClojureDocs for the future function:
>>
>>     http://clojuredocs.org/clojure_core/clojure.core/future
>>
>
> I added (shutdown-agents) and the delay is gone.
>
>
> On Thu, Apr 10, 2014 at 4:35 PM, Cecil Westerhof 
> <cldwes...@gmail.com<javascript:>
>> > wrote:
>>
>>> 2014-04-10 16:45 GMT+02:00 Andy Fingerhut <andy.fi...@gmail.com<javascript:>
>>> >:
>>>
>>> Forcing small bits of computation to be done in parallel using the tools 
>>>> Clojure and the JVM have at hand, e.g. pmap, future, etc., which rely on 
>>>> creating JVM Thread objects, tends to slow things down rather than speed 
>>>> things up, because the extra overhead of creating threads and waiting for 
>>>> them to finish is higher than the cost of sequentially doing the small 
>>>> bits 
>>>> of computation.
>>>>
>>>> If you want to force parallelism in your example anyway, to compare the 
>>>> most-likely-slower-performance against what you have now, you can try this:
>>>>
>>>> (let [val (Math/sqrt i)
>>>>        a1 (future (Math/pow val 2))
>>>>        a2 (future (* val val))
>>>>        diff (Math/abs (- @a1 @a2))]
>>>>
>>>
>>> The first form of concurrency was very bad indeed. I attached the script
>>> I made. (With the first form of concurrency disabled.) The sequential
>>> version takes between 1:52 and 1:56 with 18% CPU.
>>>
>>> The first form of concurrency took 2 hours and 45 minutes with 26% CPU.
>>> That is about 87 times as long, so very bad indeed. A future seems to be
>>> very expensive.
>>>
>>> The second form of concurrency takes around 31 seconds with 57% CPU. So
>>> about 3.7 times as fast. So that is a good improvement. The output is
>>> not complete the same, but that is not important in this case.
>>>
>>> By the way: is this the right way to write Clojure code? Especially: are
>>> the names max-diff and max-factor correct, or should the names be called
>>> different? For example: *max-fiff*.
>>>
>>> I call the script with:
>>>     date +%T ; clojure ~/Clojure/check-power.clj ; date +%T
>>>
>>> This gives:
>>>     00:52:10
>>>     00:52:11: Start sequential
>>>     00:52:11: Different for          838 (1.136868e-13, 1.356645e-16)
>>>     00:52:11: Different for         3352 (4.547474e-13, 1.356645e-16)
>>>     00:52:11: Different for         5343 (9.094947e-13, 1.702217e-16)
>>>     00:52:11: Different for         9470 (1.818989e-12, 1.920791e-16)
>>>     00:52:11: Different for        19922 (3.637979e-12, 1.826111e-16)
>>>     00:52:11: Different for        33757 (7.275958e-12, 2.155392e-16)
>>>     00:52:11: Different for        65830 (1.455192e-11, 2.210529e-16)
>>>     00:52:11: Different for       132323 (2.910383e-11, 2.199454e-16)
>>>     00:52:11: Different for       263320 (5.820766e-11, 2.210529e-16)
>>>     00:52:12: Different for       524523 (1.164153e-10, 2.219451e-16)
>>>     00:52:12: Different for      1052879 (2.328306e-10, 2.211371e-16)
>>>     00:52:12: Different for      2097255 (4.656613e-10, 2.220337e-16)
>>>     00:52:12: Different for      4194573 (9.313226e-10, 2.220304e-16)
>>>     00:52:12: Different for      8389020 (1.862645e-09, 2.220337e-16)
>>>     00:52:13: Different for     16777781 (3.725290e-09, 2.220371e-16)
>>>     00:52:16: Different for     33554486 (7.450581e-09, 2.220442e-16)
>>>     00:52:19: Different for     67110098 (1.490116e-08, 2.220405e-16)
>>>     00:52:27: Different for    134217944 (2.980232e-08, 2.220442e-16)
>>>     00:52:42: Different for    268436271 (5.960464e-08, 2.220439e-16)
>>>     00:53:13: Different for    536871776 (1.192093e-07, 2.220442e-16)
>>>     00:54:06: Stop, max-factor: 2.220442e-16
>>>
>>>
>>>     00:54:06: Start concurrent2
>>>     00:54:06: Different for          838 (1.136868e-13, 1.356645e-16)
>>>     00:54:06: Different for         5343 (9.094947e-13, 1.702217e-16)
>>>     00:54:06: Different for         3674 (4.547474e-13, 1.237745e-16)
>>>     00:54:06: Different for        10925 (1.818989e-12, 1.664979e-16)
>>>     00:54:06: Different for        21372 (3.637979e-12, 1.702217e-16)
>>>     00:54:06: Different for        20571 (3.637979e-12, 1.768499e-16)
>>>     00:54:06: Different for        19922 (3.637979e-12, 1.826111e-16)
>>>     00:54:06: Different for        33757 (7.275958e-12, 2.155392e-16)
>>>     00:54:06: Different for        70012 (1.455192e-11, 2.078489e-16)
>>>     00:54:06: Different for       135028 (2.910383e-11, 2.155392e-16)
>>>     00:54:06: Different for       263320 (5.820766e-11, 2.210529e-16)
>>>     00:54:06: Different for       529292 (1.164153e-10, 2.199454e-16)
>>>     00:54:06: Different for      1053280 (2.328306e-10, 2.210529e-16)
>>>     00:54:06: Different for      2098092 (4.656613e-10, 2.219451e-16)
>>>     00:54:06: Different for      4211516 (9.313226e-10, 2.211371e-16)
>>>     00:54:06: Different for      4194573 (9.313226e-10, 2.220304e-16)
>>>     00:54:06: Different for      8389473 (1.862645e-09, 2.220217e-16)
>>>     00:54:07: Different for     16777781 (3.725290e-09, 2.220371e-16)
>>>     00:54:07: Different for     33555125 (7.450581e-09, 2.220400e-16)
>>>     00:54:08: Different for     67115849 (1.490116e-08, 2.220215e-16)
>>>     00:54:10: Different for    134218985 (2.980232e-08, 2.220425e-16)
>>>     00:54:14: Different for    268441753 (5.960464e-08, 2.220394e-16)
>>>     00:54:23: Different for    536872413 (1.192093e-07, 2.220440e-16)
>>>     00:54:37: Stop, max-factor: 2.220440e-16
>>>     00:55:37
>>>
>>> One thing I do not understand, between finishing (check-concurrent2) and
>>> getting back to the shell there is one minute. When calling only
>>> (check-sequential) the script returns immediately back to the shell. Why
>>> is this?
>>>  
>>>
>>> On Thu, Apr 10, 2014 at 7:35 AM, Cecil Westerhof 
>>> <cldwes...@gmail.com<javascript:>
>>>> > wrote:
>>>>
>>>>> I have the following in my code:
>>>>>        (let [val (Math/sqrt i)
>>>>>             diff (Math/abs (- (Math/pow val 2) (* val val)))]
>>>>>
>>>>> I expect that calculating the difference is the most expensive part of 
>>>>> my code. I understood that Clojure is very good in parallellisation. How 
>>>>> would I let (Math/pow val 2) and (* val val) be calculated in parallel?
>>>>>
>>>>
> -- 
> Cecil Westerhof 
>

-- 
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 unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to