问题标题确实说明了一切:在球拍中将函数映射到并行列表的最佳方法是什么?谢谢。
2 回答
如果您的意思是多个处理器内核,那么最通用的方法是使用Places。
Places 支持开发利用具有多个处理器、内核或硬件线程的机器的并行程序。
地点是一个并行任务,它实际上是 Racket 虚拟机的一个单独实例。场所通过场所通道进行通信,场所通道是双向缓冲通信的端点。
您也许可以使用另一种并行化技术Futures,但它的工作条件相对有限,例如浮点运算,如此处所述。
编辑:回应评论:
是否有在某处使用地点的并行地图实现?
首先,我应该备份。您可能不需要 Places。您可以使用 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
. 有关以“定制”方式使用地点的示例,请参阅:
我不知道在 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))