Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to map a function over a list in parallel in racket?

The question title says it all, really: What is the best way map a function over a list in parallel in racket? Thanks.

like image 987
Chris Avatar asked Mar 26 '13 22:03

Chris


2 Answers

If you mean over multiple processor cores, then the most general approach is to use Places.

Places enable the development of parallel programs that take advantage of machines with multiple processors, cores, or hardware threads.

A place is a parallel task that is effectively a separate instance of the Racket virtual machine. Places communicate through place channels, which are endpoints for a two-way buffered communication.

You might be able to use the other parallelization technique, Futures, but the conditions for it to work are relatively limited, for example floating point operations, as described here.


EDIT: In response to the comment:

Is there an implementation of parallel-map using places somewhere?

First, I should back up. You might not need Places. You can get concurrency using Racket threads. For example, here's a map/thread:

#lang racket

(define (map/thread f xs)
  ;; Make one channel for each element of xs.
  (define cs (for/list ([x xs])
               (make-channel)))
  ;; Make one thread for each elemnet of xs.
  ;; Each thread calls (f x) and puts the result to its channel.
  (for ([x xs]
        [c cs])
    (thread (thunk (channel-put c (f x)))))
  ;; Get the result from each channel.
  ;; Note: This will block on each channel if not yet ready.
  (for/list ([c cs])
    (channel-get c)))

;; Use:
(define xs '(1 2 3 4 5))
(map add1 xs)
(map/thread add1 xs)

If the work being done involves blocking, e.g. I/O requests, this will give you "parallelism" in the sense of not being stuck on I/O. However Racket threads are "green" threads so only one at a time will be using the CPU.

If you truly need parallel use of multiple CPU cores, then you would need Futures or Places.

Due to the way Places are implemented --- effectively as multiple instances of Racket --- I don't immediately see how to write a generic map/place. For examples of using places in a "bespoke" way, see:

  • Places in the Guide
  • Places in the Reference
like image 103
Greg Hendershott Avatar answered Oct 08 '22 02:10

Greg Hendershott


I don't know in Racket, but I implemented a version in SISC Scheme.

(define (map-parallel fn lst)
  (call-with-values (lambda ()
                      (apply parallel 
                             (map (lambda (e)
                                    (delay (fn e)))
                                  lst)))
    list))

Only parallel is not R5RS.

Example of use:

Using a regular map:

(time (map (lambda (a)
        (begin
          (sleep 1000)
          (+ 1 a)))
     '(1 2 3 4 5)))
=> ((2 3 4 5 6) (5000 ms))

Using the map-parallel:

(time (map-parallel (lambda (a)
        (begin
          (sleep 1000)
          (+ 1 a)))
     '(1 2 3 4 5)))
=> ((2 3 4 5 6) (1000 ms))
like image 36
Felipe Avatar answered Oct 08 '22 00:10

Felipe