5

これには約1秒かかります

(1 to 1000000).map(_+3)

これはjava.lang.OutOfMemoryError: Java heap spaceを与えますが

(1 to 1000000).par.map(_+3)

編集:

標準のscala 2.9.2構成があります。これをscalaプロンプトで入力しています。そして、bash で [ -n "$JAVA_OPTS" ] || を見ることができます。JAVA_OPTS="-Xmx256M -Xms32M"

そして、環境にJAVA_OPTSが設定されていません。

100 万個の整数 = 8MB、リストを 2 回作成 = 16MB

4

4 に答える 4

9

これは、JVM メモリ オプション、Parralel コレクションのストックに必要なメモリに間違いなく関連しているようです。例えば:

scala> (1 to 1000000).par.map(_+3)

OutOfMemoryError評価しようとしたのは3回目ですが、

scala> (1 to 1000000).par.map(_+3).seq

失敗したことはありません。問題は、Parallel コレクションのストレージの計算ではありません。

于 2012-06-01T09:56:21.490 に答える
3

失敗のいくつかの理由:

  1. 並列コレクションは特殊化されていないため、オブジェクトはボックス化されます。これは、メモリ使用量を取得するために要素数に 8 を掛けることができないことを意味します。
  2. 使用mapするとは、範囲がベクトルに変換されることを意味します。並列ベクトルの場合、効率的な連結はまだ実装されていないため、異なるプロセッサによって生成された中間ベクトルをマージするとコピーが行われ、より多くのメモリが必要になります。これは、将来のリリースで対処される予定です。
  3. REPL は以前の結果を保存します。各行で評価されたオブジェクトはメモリに残ります。
于 2012-06-01T12:01:20.357 に答える
2

ここには 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) を返します。これは、通常のベクターよりも多くのスペースを占有します。これは、メモリが不足する前に 4 回実行できますが、これは実行できます。

(1 to 100000).map(_+3)

メモリがなくなる前に11回。したがって、並列コレクションを保持すると、より多くのスペースが必要になります。

回避策として、返す前に のような単純なコレクションに変換できListます。

並列コレクションがなぜこれほど多くのスペースを占有するのか、なぜ多くのものへの参照を保持するのかについては、私にはわかりませんがviews[*]、それが問題だと思われる場合は問題を提起してください。

[*] 確たる証拠なし。

于 2012-06-01T12:13:18.927 に答える
0

私は同じことをしましたが、 ThreadPool を使用すると問題が解決するようです:

  val threadPool = Executors.newFixedThreadPool(4)
  val quadsMinPar = quadsMin.par
  quadsMinPar.tasksupport = new ThreadPoolTaskSupport(threadPool.asInstanceOf[ThreadPoolExecutor])

大規模なコレクションの ForkJoin が作成するスレッドが多すぎる可能性があります。

于 2015-01-12T14:29:36.303 に答える