【问题标题】:How to map a function over a list in parallel in racket?如何在球拍中并行地将函数映射到列表上?
【发布时间】:2013-03-16 22:16:01
【问题描述】:

问题的标题说明了一切,真的:在球拍中将函数映射到并行列表的最佳方法是什么?谢谢。

【问题讨论】:

    标签: parallel-processing scheme racket


    【解决方案1】:

    如果您指的是多个处理器内核,那么最通用的方法是使用Places

    场所支持开发利用具有多个处理器、内核或硬件线程的机器的并行程序。

    一个地方是一个并行任务,它实际上是一个单独的 Racket 虚拟机实例。场所通过场所通道进行通信,场所通道是双向缓冲通信的端点。

    也许可以使用其他并行化技术Futures,但其工作条件相对有限,例如浮点运算,如here 所述。 p>


    编辑:回应评论:

    是否有使用某处地点的并行地图实现?

    首先,我应该备份。您可能不需要 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。有关以“定制”方式使用地点的示例,请参阅:

    【讨论】:

    • 谢谢格雷格。我确实尝试快速尝试使用期货将阶乘函数映射到大整数列表上,但计算似乎绑定到一个核心。然而,我显然在使用 bignums——我没有意识到期货仅限于浮动。
    • 顺便说一句,我的描述有点随意。它不是那么多的“浮点数”。定点和浮点都可以;关键是它们是fixnum 还是flonum 并且不需要装箱/分配。这有点棘手。这就是为什么我建议将 Places 作为更一般的尝试。只有当你在做数字的事情并且愿意仔细检查代码时,你才会发现 Futures 很有帮助(据我了解;其他了解更多的人可能会加入并纠正我)。
    • 感谢您的澄清,格雷格。
    • 是否有使用地点的并行地图实现?我希望能够调用由可用内核数量参数化的 (parallel-map f xs ys zs) 并完成它。
    • @wdkrnls 似乎让它以通用方式工作并不容易,因为地方被提升到模块顶层(起初有点混乱,但多次阅读文档中的段落有帮助)。我尝试将多个位置放在一个列表中,但后来无法在我的程序中使用它们。这种提升有一些奇怪的效果。总的来说,地点的概念似乎很棒,就像 Racket 中的几乎所有概念一样。
    【解决方案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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-15
      • 1970-01-01
      • 2021-09-30
      • 1970-01-01
      • 2012-09-27
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多