假设我有以下代码:
(defn multiple-writes []
(doseq [[x y] (map list [1 2] [3 4])] ;; let's imagine those are paths to files
(when-not (exists? x y) ;; could be left off, I feel it is faster to check before overwriting
(write-to-disk! (do-something x y)))))
我这样称呼(省略参数):
(go (multiple-writes))
我使用go
在后台执行某些代码,但我不知道我是否在使用正确的工具。有关这些功能的更多信息:
multiple-writes
可被视为缓存填充函数。do-something
需要100到500毫秒,具体取决于输入do-something
消耗一些内存(使用图像缓冲区,一些图像可以是2000px * 2000px)multiple-writes
时,都要处理10到40个元素/图像。write-to-disk
都会创建一个新文件(如果有的话会覆盖它,但不应该发生)write-to-disk
始终写在同一目录中所以我想通过并行执行(write-to-disk! (do-something x y))
来加快速度,尽可能快。 但是我根本不想让系统过载,因为不是一项高优先级的任务。
我应该怎么做?
注意:尽管有标题,但这不是this question的重复,因为我不想限制为3个帖子(不是说答案不一样,但我觉得这个问题不同)。
答案 0 :(得分:1)
我会做一个IO组件。然后,每个处理节点都可以将结果发送到那里保存。这很容易用流模型化。使用fork / join,可以通过不在层次结构中返回结果但将其发送到例如来实现。代理人。
如果内存消耗是一个问题,也许你可以分工更多。像100x100补丁一样。
答案 1 :(得分:1)
看看claypoole library,它提供了一些好的和简单的抽象填充pmap
和fork / join reducers
之间的空白,否则需要手动编码future
和promise
s。
使用pmap
并行批处理的所有结果都需要在执行下一批处理之前返回,因为保留了返回顺序。这可能是处理时间变化很大的问题(无论是计算,http请求还是不同“大小”的工作项)。这通常会使pmap
减慢到单线程map
+不需要的开销性能。
使用claypoole的无序pmap并且(upmap
和upfor
)无序,一个线程(核心)中较慢的函数调用可以被另一个线程上的较快函数调用所取代,因为排序不需要是保留,只要并非所有核心都被慢速呼叫堵塞。
如果IO到一个磁盘是唯一的瓶颈,这可能没有多大帮助,但由于claypoole具有可配置的线程池大小和功能来检测可用内核的数量,因此它将有助于限制内核数量。
fork / join reducers可以通过工作窃取来优化CPU使用率,这可能会大大增加内存使用量,因为没有选项可以在不改变reducer库的情况下限制并行进程的数量。