【问题标题】:clojure reduce function uses all cores even though it seems to be single threadedclojure reduce 函数使用所有内核,即使它似乎是单线程的
【发布时间】:2020-11-27 16:20:30
【问题描述】:
(defn sum [numbers]
  (reduce + numbers))

(def numbers (into [] (range 0 100000000)))

(time (sum numbers))

上面是运行的代码。

只需将很多数字相加即可。

这行在repl中被执行了多次:
(time (sum numbers)) 每次它几乎都会让所有核心完全运行。

查看jvisualvm,创建的线程并不多。

但这段代码使用了我的 6 核笔记本电脑上可用的所有 12 个超线程。

幕后发生了什么使这成为可能?

【问题讨论】:

  • 无关注释 - (reduce + (range 0 100000000)) 明显更快,因为 range 返回一个知道如何在不创建中间序列的情况下减少自身的对象。 (into [] ..) 强制将整个范围实现为 1 个大序列。
  • 你的 reduce 是单线程的。 Java 虚拟机可能正在处理垃圾收集或其他任务。 VisualVM 屏幕截图表明许多线程与 RMI 相关。
  • 正如前面评论中提到的,有多种垃圾收集算法可供大多数 JVM 配置使用。其中一些将利用多个并行线程来执行垃圾收集工作。至少这似乎是您系统上正在发生的事情。当您启动不这样做的 JVM 时,您可以尝试手动选择 GC 算法,并查看它是否会改变使用的核心数。
  • 这可能是因为使用 JMX 而死?甚至对于jvisualvm?见plumbr.io/handbook/gc-tuning-in-practice/other-examples/rmi-gc

标签: multithreading clojure jvm visualvm jvisualvm


【解决方案1】:

感谢 cmets。

这与范围的大小有关。

在我的笔记本电脑上,当它有大约 7000 万个数字时,一切都很好。

当它达到 8000 万左右时,堆大小会增长很多,花费的时间会显着增长,并且所有内核都开始工作。并且视觉 vm 显示更多的 GC 活动正在发生。

所以上面的cmets可能是对的,它与GC有关。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-08
    • 2017-03-22
    • 1970-01-01
    相关资源
    最近更新 更多