2013-09-28 29 views
1

我想在Racket中實現一個並行映射功能。地方似乎是正確的事情,但他們對我來說是一個未知的領域。我在想代碼看起來應該如下所示。如何使用Places編寫並行圖?

#lang racket 

; return xs split into n sublists 
(define (chunk-into n xs) 
    (define N (length xs)) 
    (cond [(= 1 n) (list xs)] 
     [(> n N) 
     (cons empty 
       (chunk-into (sub1 n) xs))] 
     [else 
     (define m (ceiling (/ N n))) 
     (cons (take xs m) 
       (chunk-into (sub1 n) (drop xs m)))])) 

(module+ test 
    (check-equal? (length (chunk-into 4 (range 5))) 4) 
    (check-equal? (length (chunk-into 2 (range 5))) 2)) 

(define (parallel-map f xs) 
    (define n-cores (processor-count)) 
    (define xs* (chunk-into n-cores xs)) 
    (define ps 
    (for/list ([i n-cores]) 
     (place ch 
      (place-channel-put 
       ch 
       (map f 
       (place-channel-get ch)))))) 
    (apply append (map place-channel-put ps xs*))) 

這給了錯誤:

f: identifier used out of context in: f

所有我見過的顯示提供了一個主要功能不帶參數這在某種程度上得到的的設計模式的例子用來實例另外的地方,但是這使用起來非常麻煩,所以我正在積極努力避免它。這可能嗎?

注:我也嘗試使用期貨製作並行圖。不幸的是,對於我所有的測試來說,它實際上比map更慢(我嘗試使用fib的遞歸過程版本進行測試),但在這種情況下,如果您有任何提高速度的建議。

(define (parallel-map f xs) 
    (define xs** (chunk-into (processor-count) xs)) 
    (define fs (map (λ (xs*) (future (thunk (map f xs*)))) xs**)) 
    (apply append (map touch fs))) 
+0

我確實在unstable中看到open-place,它將錯誤更改爲unbound。 – wdkrnls

回答

1

我曾經使用過地點,但從未將函數作爲參數傳遞給某個地方。我能想出以下,而這些混沌的代碼,它使用eval:

#!/usr/bin/env racket 
#lang racket 

(define (worker pch) 
    (define my-id (place-channel-get pch)) ; get worker id 
    (define wch-w (place-channel-get pch)) ; get work channel (shared between controller and all workers) - worker side 
    (define f  (place-channel-get pch)) ; get function 
    (define ns (make-base-namespace)) ; for eval 
    (let loop() 
    (define n (place-channel-get wch-w)) ; get work order 
    (let ((res (eval `(,f ,n) ns)))  ; need to use eval here !! 
     (eprintf "~a says ~a\n" my-id res) 
     (place-channel-put wch-w res)  ; put response 
     (loop))))       ; loop forever 

(define (parallel-map f xs) 
    (define l (length xs)) 
    (define-values (wch-c wch-w) (place-channel)) ; create channel (2 endpoints) for work dispatch (a.k.a. shared queue) 
    (for ((i (in-range (processor-count)))) 
    (define p (place pch (worker pch)))   ; create place 
    (place-channel-put p (format "worker_~a" i)) ; give worker id 
    (place-channel-put p wch-w)     ; give response channel 
    (place-channel-put p f))      ; give function 
    (for ((n xs)) 
    (place-channel-put wch-c n))     ; create work orders 
    (let loop ((i 0) (res '()))      ; response loop 
    (if (= i l) 
     (reverse res) 
     (let ((response (sync/timeout 10 wch-c))) ; get answer with timeout (place-channel-get blocks!) 
      (loop 
      (+ i 1) 
      (if response (cons response res) res)))))) 

(module+ main 
    (displayln (parallel-map 'add1 (range 10)))) 

運行在一個控制檯提供,例如:

worker_1 says 1 
worker_1 says 3 
worker_1 says 4 
worker_1 says 5 
worker_1 says 6 
worker_1 says 7 
worker_1 says 8 
worker_1 says 9 
worker_1 says 10 
worker_0 says 2 
(1 3 4 5 6 7 8 9 10 2) 

正如我所說的,這些混沌。歡迎所有建議!

+0

這看起來像一個很有幫助的例子。我注意到的第一件事是2是最後一個。這是爲什麼?另外,我看到你傳遞了一個符號作爲參數,而不是一個函數。我把它作爲函數本身不能作爲消息傳遞? (當然,我試圖做的第一件事是在repl中定義fib,然後嘗試對其調用parallel-map,導致錯誤,說明fib未定義)。 – wdkrnls

+0

事實上,地方似乎無法接收到消息的功能,而球拍照常給出了一個奇妙的錯誤。 – wdkrnls

+0

由於計算並行發生,結果的順序是不可預測的。如果您運行該程序幾次,您可能會得到不同的結果。如果您想按照特定順序獲得結果,您必須對工單進行編號並將結果與​​訂單信息一起提交(並相應地組合它們)。 – uselpa

相關問題