大约需要1秒
(1 to 1000000).map(_+3)
虽然这给出了 java.lang.OutOfMemoryError:Java堆空间
(1 to 1000000).par.map(_+3)
修改
我有标准的scala 2.9.2配置。我在scala提示符下键入此内容。在bash中我可以看到[-n“$ JAVA_OPTS”] || JAVA_OPTS =“ - Xmx256M -Xms32M”
我没有在我的环境中设置JAVA_OPTS。
100万个整数= 8MB, 创建列表两次= 16MB
答案 0 :(得分:9)
似乎肯定与存储Parralel集合所需的内存的JVM内存选项和有关。例如:
scala> (1 to 1000000).par.map(_+3)
第三次尝试评估时,最终得到OutOfMemoryError
,而
scala> (1 to 1000000).par.map(_+3).seq
从未失败过。问题不在于计算它是Parrallel集合的存储。
答案 1 :(得分:3)
失败的几个原因:
map
表示将范围转换为矢量。对于并行向量,尚未实现有效的级联,因此合并由不同处理器产生的中间向量通过复制来进行 - 需要更多的存储器。这将在以后的版本中解决。答案 2 :(得分:2)
这里有两个问题,即存储并行集合所需的内存量以及“通过”并行集合所需的内存量。
这两条线之间可以看出差异:
(1 to 1000000).map(_+3).toList
(1 to 1000000).par.map(_+3).toList
REPL存储已评估的表达式,请记住。在我的REPL上,我可以在内存不足之前执行这7次。通过并行执行传递暂时使用额外的内存,但是一旦执行了toList,额外的使用就会被垃圾收集。
(1 to 100000).par.map(_+3)
返回ParSeq [Int](在本例中为ParVector),它占用比普通Vector更多的空间。这个我可以在内存耗尽之前执行4次,而我可以执行此操作:
(1 to 100000).map(_+3)
在我内存不足之前已经11次了。所以并行收藏,如果你保留它们会占用更多空间。
作为一种变通方法,您可以在返回之前将它们转换为更简单的集合,例如List
。
至于为什么并行集合会占用太多空间以及为什么它会引用很多东西,我不知道,但我怀疑views
[*],如果你认为这是一个问题,raise an issue for it。
[*]没有任何真实证据。
答案 3 :(得分:0)
我也一样,但是使用ThreadPool似乎为我解决了这个问题:
val threadPool = Executors.newFixedThreadPool(4)
val quadsMinPar = quadsMin.par
quadsMinPar.tasksupport = new ThreadPoolTaskSupport(threadPool.asInstanceOf[ThreadPoolExecutor])
大型集合的ForkJoin可能会创建太多线程。