问题标题说明了一切,真的:在球拍中并行地在列表中映射函数的最佳方法是什么?感谢。
答案 0 :(得分:9)
如果您的意思是多个处理器核心,那么最常用的方法是使用Places。
Places可以开发利用具有多个处理器,内核或硬件线程的计算机的并行程序。
一个地方是一个并行任务,实际上是一个独立的Racket虚拟机实例。场所通过场所通道进行通信,场所通道是双向缓冲通信的端点。
你可能能够使用其他并行化技术Futures,但它的工作条件相对有限,例如浮点运算,如{{3}所述}。
编辑:回复评论:
是否存在使用某处的并行映射的实现?
首先,我应该备份。你可能不需要地方。您可以使用Racket线程获得并发。例如,这是一个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)
如果正在完成的工作涉及阻止,例如I / O请求,这将给你“并行性”,意思是不会卡在I / O上。但是,Racket线程是“绿色”线程,因此每次只能使用一个CPU。
如果您真的需要并行使用多个CPU核心,那么您将需要Futures或Places。
由于Places的实现方式 - 实际上是多个Racket实例 - 我不会立即看到如何编写通用map/place
。有关以“定制”方式使用地点的示例,请参阅:
答案 1 :(得分:2)
我在Racket中不知道,但我在SISC Scheme中实现了一个版本。
(define (map-parallel fn lst)
(call-with-values (lambda ()
(apply parallel
(map (lambda (e)
(delay (fn e)))
lst)))
list))
只有parallel
不是R5RS。
使用示例:
使用常规map
:
(time (map (lambda (a)
(begin
(sleep 1000)
(+ 1 a)))
'(1 2 3 4 5)))
=> ((2 3 4 5 6) (5000 ms))
使用map-parallel
:
(time (map-parallel (lambda (a)
(begin
(sleep 1000)
(+ 1 a)))
'(1 2 3 4 5)))
=> ((2 3 4 5 6) (1000 ms))