重写用于并行执行的常见lisp顺序代码的最佳惯用方法是什么?
有一些好的库,比如lparallel,可以帮助处理简单的案例。例如,如果我们在长列表中有一些mapcar,我们可以用lparallel:mapcar替换它,并且它在大多数情况下都可以完成工作。现在我进行了一些循环调用,获取了一些远程JSON API的结果并将其纳入列表:
(loop :for offset :from 0 :by 100
:for result = (get-remote-data offset)
:until (null result) :nconc result)
如何替换它,并行调用get-remote-data
而无需更改get-remote-data
本身?有没有标准和惯用的方法?任何关于这个主题的好读也会有所帮助。感谢。
答案 0 :(得分:4)
我已将chanl
用于此类用例来设置消息队列。一世
启动 n 工作线程,进行远程调用并将其发送给
队列。聚合器从队列中获取结果
连接它们。
如果订单很重要,这可能不对。你也许也许 预定义在定义的单独填充的结果数组 工人的抵消。
编辑:为了获得未知数量的页面,您可以使用 原子偏移计数器和原子标志。工人线程(来自 固定池)然后检查标志,从计数器获得下一个偏移量, 进行远程调用,最后将结果发送到队列,或者, 如果结果为空,请关闭标志。如果标志被翻转掉 检查它的任何工作线程都会自行关闭。当工人 线程池是空的,你已经完成了。
答案 1 :(得分:2)
我使用lparallel创建了以下内容:
(defun get-datum (n)
(sleep (random 2))
(if (> n 1000)
()
(list n)))
(defun get-data ()
(let ((channel (lparallel:make-channel))
results)
(flet ((collect (item)
(setq results (append item results))))
;; Ask lparallel to schedule the first 8 requests
(loop for i from 0 to 70 by 10
do (lparallel:submit-task channel #'get-datum i))
;; Schedule an additional request each time one returns
;; until we get a null result
(loop for i from 80 by 10
for result = (lparallel:receive-result channel)
while result
do (lparallel:submit-task channel #'get-datum i)
(collect result))
;; wait for all outstanding requests
(loop repeat 7
do (collect (lparallel:receive-result channel)))
results)))