[racket] Concurrent execution

From: jukka.tuominen at finndesign.fi (jukka.tuominen at finndesign.fi)
Date: Mon Oct 3 11:41:49 EDT 2011

Wow, that's great Sam!

I tried to create a simple test around it (below), but it's hard to find a
pattern in the results. A few notes, though:

- The results vary a great deal from run to run
- 'Plain map' seems to do things in parallel itself!?
  (by looking at the System Monitor during the test run)
  This may paralyze secondary parallelizing :)
- Plain map does usually better with short lists. No wonder.
- The amount of distribution should be related to the available number of
  HW processors; not the more the merrier, obviously.

---
#lang racket

(require racket/future)

(define (my-factorial x)
  (cond
    [(= x 0) 1]
    [else (* x (my-factorial (- x 1)))]
    ))

(define (par-map f l)
  (define fs (for/list ([elem (in-list l)]) (future (lambda () (f elem)))))
  (map touch fs))

(define lst1 '(12345 12345))
(define lst2 '(12345 12345 12345 12345 12345 12345))
(define lst3 '(12345 12345 12345 12345 12345 12345 12345 12345 12345 12345
12345 12345 12345 12345 12345 12345 12345 12345))
(define lst4 '(12345 12345 12345 12345 12345 12345 12345 12345 12345 12345
12345 12345 12345 12345 12345 12345 12345 12345
                     12345 12345 12345 12345 12345 12345 12345 12345 12345
12345 12345 12345 12345 12345 12345 12345 12345
12345))


(define (test)
  (define start-time 0)
  (begin (display "First round - par-map first")(newline)(newline)
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst1)(display "par-map1:  ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst1)(display "map1    :  ")(display (- (current-seconds)
start-time))(newline)(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst2)(display "par-map2:  ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst2)(display "map2:      ")(display (- (current-seconds)
start-time))(newline)(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst3)(display "par-map3:  ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst3)(display "map3:      ")(display (- (current-seconds)
start-time))(newline)(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst4)(display "par-map4:  ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst4)(display "map4:      ")(display (- (current-seconds)
start-time))(newline)(newline)(newline))
         (display "Second round - map first")(newline)(newline)
         (begin (set! start-time (current-seconds))(map my-factorial
lst1)(display "map1:      ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst1)(display "par-map1:  ")(display (- (current-seconds)
start-time))(newline)(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst2)(display "map2:      ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst2)(display "par-map2:  ")(display (- (current-seconds)
start-time))(newline)(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst3)(display "map3:      ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst3)(display "par-map3:  ")(display (- (current-seconds)
start-time))(newline)(newline))
         (begin (set! start-time (current-seconds))(map my-factorial
lst4)(display "map4:      ")(display (- (current-seconds)
start-time))(newline))
         (begin (set! start-time (current-seconds))(par-map my-factorial
lst4)(display "par-map4:  ")(display (- (current-seconds)
start-time))(newline))
         ))

(test)
---

> On Mon, Oct 3, 2011 at 2:25 AM, Jukka Tuominen
> <jukka.tuominen at finndesign.fi> wrote:
>>
>> Sorry for thinking aload again, but I'm learning these issues myself in
>> the background, and I wonder if something like the following might work?
>>
>> Concurrent List Processing -idea
>>
>> Two phase process
>>
>> 1) Distribution phase
>> Create a recursive procedure combining cons and threads so that each
>> item in the original list will be replaced by a named thread. Sending
>> out new threads won't wait for individual threads to return in this
>> phase. The result of this phase is a list of named threads.
>>
>> 2) Collection phase
>> This phase is again a recursive cons process, but this time sequential.
>> It starts from the beginning of the named-thread list, and as soon as
>> the first thread returns its value, it moves on. The process goes on
>> until the end of the list is reached. The resulting list is the return
>> value.
>
> Here's your idea, implemented with futures.  I'm assuming that you
> want to apply a particular procedure to each element of the list, as
> in `map':

You're assuming right

>
> (define (par-map f l)
>   (define fs (for/list ([elem (in-list l)]) (future (lambda () (f elem))))
>   (map touch fs))
>
>> - If the original list to be processed is very long, then the
>> construction of the second phase list shouldn't wait for bottle neck
>> items to cons the list elsewhere where possible. The speed gain wouldn't
>> be substantial though, since it is just building a list, and you cannot
>> finish it until the last item is available, anyway.
>
> You'd want to basically make the result list into a queue in which
> elements are inserted.

Right. The list would just need to be veeery long to make any difference,
I would think.

br, jukka

> --
> sam th
> samth at ccs.neu.edu
>




Posted on the users mailing list.