[racket] parallelism

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Thu May 12 22:19:46 EDT 2011

Thanks for the bug reports.

Meanwhile, did you read the section that explains why futures can go
slower than sequential versions and how to deal with that?

Robby

On Thu, May 12, 2011 at 8:44 PM, Stephen Bloch <sbloch at adelphi.edu> wrote:
>
> On May 11, 2011, at 3:23 PM, Robby Findler wrote:
>
>> You might try futures. Do read the guide first, of course.
>
> I've tried some simple experiments.
>
> The function in question iterates over every pixel of an image being constructed:
>        (for* ((y (in-range 0 height))
>                  (x (in-range 0 width)))
>             ; set the (x,y) pixel in the bitmap to be the result of a function call on x and y
>             )
>
> I wrote another version that parallelizes the rows:
>        (touch-all (for/list ((y (in-range 0 height)))
>                                  (future (lambda () (for ((x (in-range 0 width)))
>                                                                        ; set the (x,y) pixel as above
>                                                ))))
>        (define (touch-all futures)
>                (for ((f futures)) (touch f)))
> This version occasionally crashes DrRacket, but usually runs in about twice the time of the non-futures version.
>
> I wrote another version that parallelizes the columns:
>        (for ((y (in-range 0 height)))
>                (touch-all (for/list ((x (in-range 0 width)))
>                                        (future (lambda ()
>                                                        ; set the (x,y) pixel as above
>                                                        ))))))
> I don't think I've ever gotten this version to run without crashing DrRacket, so I have no timing data.
>
> I wrote another version that parallelizes both rows and columns:
>        (touch-all (for*/list ((y (in-range 0 height))
>                                             (x (in-range 0 width)))
>                                (future (lambda ()
>                                                ; set the (x,y) pixel as above
>                                        ))))
> This ran once without crashing, but it produced a wrong answer, and I didn't get the timing data.  Every other time I've tried it, DrRacket has crashed.
>
> The likelihood of crashing seems to be lower if width and height are smaller.
>
>
>
>
> I then tried some simpler, smaller, non-image examples:
>
> (define nums (build-list 1000 (lambda (x) x))
>
> (time (touch-all (map (lambda (x) (future (lambda () (sqrt x)))) nums)))
> vs.
> (time (map sqrt nums))
>
> I can't tell how much slower the former is than the latter, because I've never gotten the latter to exceed 0 ms :-)
> But at least the futures version has CPU time > real time, which suggests there's some parallelization going on.
>
>
>
>
>
> So I figured "maybe you're not supposed to use more futures than you have processors."
> I'm running on a machine with 4 parallel processors, according to (processor-count).
> So I tried something with only 3 futures:
> (time (touch-all (map (lambda (x) (future (lambda () (map (lambda (y) (* x y)) nums)))) '(1 2 3)))
> as compared with a non-futures version
> (time (map (lambda (x) (map (lambda (y) (* x y)) nums)) '(1 2 3)))
> The futures version takes about twice as long as the non-futures version.  But again, CPU time > real time, which suggests some parallelization.
>
>
> I suspect that futures would be more useful if each of the tasks were bigger; I should try some more experiments with more complex tasks.
>
> Stephen Bloch
> sbloch at adelphi.edu
>



Posted on the users mailing list.