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
[email protected]

_________________________________________________
  For list-related administrative tasks:
  http://lists.racket-lang.org/listinfo/users

Reply via email to