clojure pmap - 为什么我没有使用所有核心?

时间:2016-04-24 21:09:12

标签: clojure pmap

我尝试使用clojure pantomime库从大量tif文档(以及其他文档)中提取/ ocr文本。

我的计划是使用pmap在一系列输入数据(来自postgres数据库)上应用映射,然后使用tika / tesseract OCR输出更新同一个postgres数据库。这一直工作正常,但是我注意到htop中很多核心有时都处于空闲状态。

无论如何都要调和这个,我可以采取哪些步骤来确定为什么这可能会阻塞某个地方?所有处理都在单个tif文件上进行,每个线程完全互斥。

其他信息:

  1. 一些tika / tesseract过程需要3秒钟,其他过程需要90秒。一般来说,tika严重受CPU限制。根据{{​​1}},我有足够的内存可用。
  2. postgres在会话管理中没有锁定问题,所以我不认为这会阻止我。
  3. 也许某处htop正在等待future?怎么分辨到哪里?
  4. 任何提示都表示赞赏,谢谢。代码在下面添加。

    deref

2 个答案:

答案 0 :(得分:3)

pmap在批量(+ 2个核心)上并行运行map函数,但保留了排序。这意味着如果您有8个核心,则将处理一批10个项目,但只有在所有10个项目完成后才会启动新批次。

您可以创建自己的代码,使用futuredelayderef的组合,这将是一个很好的学术练习。之后,您可以抛弃您的代码并开始使用claypoole库,该库具有一组涵盖future的大部分用法的抽象。

对于这种特定情况,请使用无序的pmappfor实施(upmapupfor),这与pmap完全相同没有订购;只要批次中的任何一个项目完成,就会选择新项目。

在IO是主要瓶颈的情况下,或处理时间因工作项目而异的情况,这是并行mapfor操作的最佳方式。

当然,您应该注意不要依赖任何类型的返回值排序。

  (require '[com.climate.claypoole :as cp])

  (cp/upmap (cp/ncpus)
    #(try
       (update-a-row %)
       (catch Exception e (t/error (.getNextException e)))
       )
    fetch-all-batch )

答案 1 :(得分:1)

前段时间我遇到过类似的问题。我想你和我一样做了相同的假设:

  • pmap并行调用f。但这并不意味着工作是平等分享的。如你所说,有些需要3秒,而其他需要90秒。在3秒内完成的线程不会要求其他人分享剩下要完成的工作。所以完成的线程只是等待直到最后一个完成。

  • 你没有准确描述你的数据是怎样的,但我会假设你正在使用某种延迟序列,这对并行处理是不利的。如果您的进程是CPU限制的,并且您可以将整个输入保存在内存中,那么更喜欢使用clojure.core.reducers('map','filter'和特别'fold')来使用惰性映射,过滤器和其他

在我的情况下,这些提示将处理时间从34秒减少到仅仅8秒。希望它有所帮助