Spark java.lang.OutOfMemoryError: Java ヒープスペース 質問する

Spark java.lang.OutOfMemoryError: Java ヒープスペース 質問する

私のクラスター: マスター 1 台、スレーブ 11 台、各ノードには 6 GB のメモリがあります。

私の設定:

spark.executor.memory=4g, Dspark.akka.frameSize=512

問題は次の通りです:

まず、HDFS から RDD にデータ (2.19 GB) を読み取ります。

val imageBundleRDD = sc.newAPIHadoopFile(...)

次に、この RDD に対して何かを実行します。

val res = imageBundleRDD.map(data => {
                               val desPoints = threeDReconstruction(data._2, bg)
                                 (data._1, desPoints)
                             })

最後に、HDFSに出力します。

res.saveAsNewAPIHadoopFile(...)

プログラムを実行すると次のように表示されます:

.....
14/01/15 21:42:27 INFO cluster.ClusterTaskSetManager: Starting task 1.0:24 as TID 33 on executor 9: Salve7.Hadoop (NODE_LOCAL)
14/01/15 21:42:27 INFO cluster.ClusterTaskSetManager: Serialized task 1.0:24 as 30618515 bytes in 210 ms
14/01/15 21:42:27 INFO cluster.ClusterTaskSetManager: Starting task 1.0:36 as TID 34 on executor 2: Salve11.Hadoop (NODE_LOCAL)
14/01/15 21:42:28 INFO cluster.ClusterTaskSetManager: Serialized task 1.0:36 as 30618515 bytes in 449 ms
14/01/15 21:42:28 INFO cluster.ClusterTaskSetManager: Starting task 1.0:32 as TID 35 on executor 7: Salve4.Hadoop (NODE_LOCAL)
Uncaught error from thread [spark-akka.actor.default-dispatcher-3] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled for ActorSystem[spark]
java.lang.OutOfMemoryError: Java heap space

タスクが多すぎますか?

PS : 入力データが約 225 MB の場合、すべて正常です。

この問題をどうすれば解決できますか?

ベストアンサー1

いくつか提案があります:

  • ノードが Spark 用に最大 6g に設定されている場合 (他のプロセス用に少し残している場合)、4g ではなく 6g を使用します。UI をチェックして、できるだけ多くのメモリを使用していることspark.executor.memory=6gを確認してください(使用しているメモリの量が表示されます)。
  • もっと多くのパーティションを使用してみてください。CPU ごとに 2 ~ 4 個のパーティションが必要です。私の経験では、パーティションの数を増やすことは、プログラムをより安定させる (そして多くの場合はより高速にする) 最も簡単な方法です。大量のデータの場合は、CPU ごとに 4 個よりはるかに多くのパーティションが必要になる場合があります。場合によっては、8000 個のパーティションを使用する必要がありました。
  • を使用して、キャッシュ用に予約されているメモリの割合を減らします。コードでまたは をspark.storage.memoryFraction使用しない場合、これは 0 と同じになります。デフォルトは 0.6 で、ヒープ用に 0.4 * 4g のメモリしか得られないことを意味します。私の経験では、メモリの割合を減らすと、OOM がなくなることがよくあります。更新: Spark 1.6 からは、どうやらこれらの値を操作する必要がなくなり、Spark が自動的に値を決定するようになります。cache()persist
  • 上記と似ていますが、シャッフル メモリの割合です。ジョブでシャッフル メモリをあまり必要としない場合は、低い値に設定します (これにより、シャッフルがディスクにあふれ、速度に壊滅的な影響を与える可能性があります)。OOM が発生するシャッフル操作の場合は、反対のこと、つまり 0.8 などの大きな値に設定するか、シャッフルがディスクにあふれていることを確認する必要があります (1.0.0 以降のデフォルトです)。
  • メモリ リークに注意してください。これは多くの場合、ラムダで必要のないオブジェクトを誤って閉じることによって発生します。診断方法は、ログで「XXX バイトとしてシリアル化されたタスク」を探すことです。XXX が数 k より大きいか 1 MB を超える場合は、メモリ リークが発生している可能性があります。https://stackoverflow.com/a/25270600/1586965
  • 上記に関連して、本当に大きなオブジェクトが必要な場合は、ブロードキャスト変数を使用します。
  • 大きなRDDをキャッシュしていて、アクセス時間を犠牲にできる場合は、RDDのシリアル化を検討してください。http://spark.apache.org/docs/latest/tuning.html#serialized-rdd-storageまたは、ディスクにキャッシュすることもできます (SSD を使用している場合は、それほど悪くない場合もあります)。
  • (上級) 上記に関連して、Stringネストされた構造 (Mapネストされたケース クラスなど) は避けてください。可能であれば、プリミティブ型のみを使用し、重複が多数発生すると予想される場合は特に、すべての非プリミティブ型にインデックスを付けるようにしてくださいWrappedArray。可能な限り、ネストされた構造よりも優先してください。または、独自のシリアル化を展開することもできます。データを効率的にバイトに戻す方法に関する最も多くの情報を持っているのはあなたです。それを使用してください
  • (少しハック) 再度キャッシュする場合、Datasetより効率的なシリアル化を使用するため、 を使用して構造をキャッシュすることを検討してください。これは、前の箇条書きと比較するとハックと見なされます。ドメイン知識をアルゴリズム/シリアル化に組み込むと、メモリ/キャッシュ領域を 100 倍または 1000 倍に最小化できますが、 ではDatasetメモリでは 2 倍から 5 倍、ディスクでは 10 倍圧縮 (parquet) されるだけでしょう。

詳細は、http://spark.apache.org/docs/1.2.1/configuration.html を参照してください。

編集: (グーグルで簡単に検索できるように) 次のこともこの問題を示しています:

java.lang.OutOfMemoryError : GC overhead limit exceeded

おすすめ記事