<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">Hi Matthew,<div><br></div><div>Thanks a lot for the reply!</div><div><br></div><div>This works! Thanks a lot.</div><div><br></div><div>Regards,</div><div>Alexey</div><div><br></div><div><br><div><div>On 12 Nov 2014, at 18:52, Matthew Flatt <<a href="mailto:mflatt@cs.utah.edu">mflatt@cs.utah.edu</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">I'll push a repair to the development version.<br><br><br>The problem isn't so much that message copying/transfer is slow, but<br>that the rule to trigger an all-places GC doesn't accommodate a large,<br>not-yet-delivered message. I'll repair that rule.<br><br>Most of the process time in your example shows up as GC time, because<br>the GC was continuously firing while the message waited for the new<br>place to start and receive it (and the constant GCs slowed the place<br>start-up).<br><br><br>If upgrading is not an option, you can work around the problem by<br>waiting for a "ready" message from the new place before sending the<br>vector as a message. For example, change `test-place1` to<br><br>(define (test-places1)<br>  (define p1<br>    (place ch1<br>           (place-channel-put ch1 'ready)<br>           (define v (place-channel-get ch1))<br>           (define w (long-computation v))<br>           (place-channel-put ch1 w)))  <br>  (place-channel-get p1) ; => 'ready<br>  (place-channel-put p1 v1)<br>  (time (place-channel-get p1)))<br><br>That way, `v1` doesn't sit in the message channel long enough to cause<br>a problem.<br><br>At Tue, 11 Nov 2014 17:41:11 -0700, Matthew Flatt wrote:<br><blockquote type="cite">This does seem extremely slow. A place-message send must copy the<br>vector to send it as a message, but the copy shouldn't take so long.<br>I'll investigate further.<br><br>Meanwhile, an option in this case might be to created a "shared<br>flvector", which can be passed directly (i.e., without copying) to<br>another place. I've enclosed a variant of your example to illustrate.<br><br>At Mon, 10 Nov 2014 11:58:21 +0200, Alexey Cherkaev wrote:<br><blockquote type="cite">Hi,<br><br>I am looking at parallelising some numerical computation with Racket. I’ve<span class="Apple-converted-space"> </span><br>tried future/touch first. However, the data for computation is passed as<span class="Apple-converted-space"> </span><br>vectors and in my experiments with future/touch it would always find<span class="Apple-converted-space"> </span><br>"synchronisation task” upon which all multicore-threads collapse into one<span class="Apple-converted-space"> </span><br></blockquote>core<span class="Apple-converted-space"> </span><br><blockquote type="cite">serialised computation.<br><br>Now, I decided to try place. My idea is to make it similar to Common Lisp’s<span class="Apple-converted-space"> </span><br>LPARALLEL: create workers <= number of cores and distribute tasks into those<span class="Apple-converted-space"> </span><br>workers. The problem I have encountered, however, is that place-channel-get<span class="Apple-converted-space"> </span><br>seems to take forever to compute. Here is an example of some simulated<span class="Apple-converted-space"> </span><br>computation on a vector using two places and trying to run them in parallel:<br><br>#lang racket<br><br>(require racket/place)<br><br>(provide test-places1 test-places2 long-computation v1 v2 random-vector)<br><br>;;; Utilities:<span class="Apple-converted-space"> </span><br>(define (random-list n)<br> (let loop ((i n) (r '()))<br>   (if (zero? i)<br>       r<br>       (loop (sub1 i) (cons (random) r)))))<br><br>(define (random-vector n)<br> (let ((l (random-list n)))<br>   (list->vector l)))<br><br>(define (vector-reduce f init v)<br> (let ((n (vector-length v)))<br>   (let loop ((i 0) (r init))<br>     (if (= i n)<br>         r<br>         (loop (add1 i) (f r (vector-ref v i)))))))<br><br>;;; This is  computation to be run in each place:<br>(define (long-computation v)<br> (let ((n (vector-length v))<br>       (v1 (vector-copy v)))  ; v is immutable, if want to mutate, must copy<span class="Apple-converted-space"> </span><br></blockquote>it<br><blockquote type="cite">   (let loop ((i 0))<br>     (if (= i n)<br>         (begin<br>           (sleep 2)         ; make it work for a bit longer<br>           (vector-reduce + 0.0 v1)) ; to make result printable<br>         (begin<br>           (vector-set! v1 i (* (exp (- (vector-ref v1 i)))<br>                                (sin (* pi (vector-ref v1 i)))))   ;flonum<span class="Apple-converted-space"> </span><br>computation<br>           (loop (add1 i)))))))<br><br>;;; two vectors to be sent to long-computation<br>(define v1 (random-vector 100000))<br>(define v2 (random-vector 100000))<br><br>;;; Test using one place:<br>(define (test-places1)<br> (define p1<br>   (place ch1<br>          (define v (place-channel-get ch1))<br>          (define w (long-computation v))<br>          (place-channel-put ch1 w)))  <br> (place-channel-put p1 v1)<br> (time (place-channel-get p1)))<br><br>;;; Test using 2 places:<br>(define (test-places2)<br> (define p1<br>   (place ch1<br>          (define v (place-channel-get ch1))<br>          (define w (long-computation v))<br>          (place-channel-put ch1 w)))<br> (define p2<br>   (place ch2<br>          (define v (place-channel-get ch2))<br>          (define w (long-computation v))<br>          (place-channel-put ch2 w)))<br> (place-channel-put p1 v1)<br> (place-channel-put p2 v2)<br> (sleep 2) ; hypothetically, after this results shoud be ready immidiately!<br> (time (list (place-channel-get p1) (place-channel-get p2))))<br><br>Exectution from racket on MacBook Pro with Intel Core 2 Duo:<br><br>-> (time (long-computation v1))<br>cpu time: 42 real time: 2043 gc time: 0<br>39523.12275516648<br>-> (test-places1)<br>cpu time: 7593 real time: 7475 gc time: 7001<br>39523.12275516648<br>-> (test-places2)<br>cpu time: 16591 real time: 12492 gc time: 15485<br>'(39523.12275516648 39505.415738171105)<br><br>So, the time of execution of (long-computation v1) and the time of getting<span class="Apple-converted-space"> </span><br></blockquote>the<span class="Apple-converted-space"> </span><br><blockquote type="cite">result out of the channel in (test-places1) should be more or less the same,<span class="Apple-converted-space"> </span><br>but it is not. Furthermore, (test-places2) takes almost twice as<span class="Apple-converted-space"> </span><br></blockquote>(test-places1)<span class="Apple-converted-space"> </span><br><blockquote type="cite">(note, I put (time …) around just getting the value, so it does not include<span class="Apple-converted-space"> </span><br></blockquote>the<span class="Apple-converted-space"> </span><br><blockquote type="cite">time of creating the place).<br><br>Am I doing something wrong?<br><br>Cheers, Alexey<br><br><br>____________________<br> Racket Users list:<br> <a href="http://lists.racket-lang.org/users">http://lists.racket-lang.org/users</a><br></blockquote>------------------------------------------------------------------------------<br>[application/octet-stream "shared-flvector-example.rkt"] [~/Desktop & open]<span class="Apple-converted-space"> </span><br>[~/Temp & open]<br>____________________<br> Racket Users list:<br> <a href="http://lists.racket-lang.org/users">http://lists.racket-lang.org/users</a></blockquote></div></blockquote></div><br></div></body></html>