Spark YARNのジョブでメモリチューニングを行っていますが、設定が異なると結果が異なり、Sparkジョブ実行の結果に影響します。 、私は混乱しており、なぜそれが起こるのか完全には理解しておらず、誰かが私にいくつかのガイダンスと説明を提供できれば幸いです。
いくつかの背景情報を提供し、質問を投稿し、それらの後に経験した事例を以下に説明します。
私の環境設定は以下の通りでした:
私のコードは、RDDを再帰的にフィルター処理して小さくし(アルゴリズムの一部として例を削除し)、mapToPairと収集を行って結果を収集し、リストに保存します。
なぜ異なるエラーがスローされ、ジョブは最初のケースと2番目のケースの間でより長く実行され(2番目のケースの場合)、executorメモリのみが増加しますか2つのエラーは何らかの形でリンクしていますか?
3番目と4番目の両方のケースが成功し、それはメモリの問題を解決するより多くのメモリを提供しているためだと理解しています。ただし、3番目のケースでは、
spark.driver.memory + spark.yarn.driver.memoryOverhead = YARNがJVMを作成するメモリ
= 11g +(driverMemory * 0.07、最小384m)= 11g + 1.154g = 12.154g
したがって、式から、ジョブを正常に実行するにはMEMORY_TOTALが約12.154gを必要とすることがわかります。これは、ドライバーのメモリ設定に10g以上必要な理由を説明しています。
しかし、4番目の場合、
spark.driver.memory + spark.yarn.driver.memoryOverhead = YARNがJVMを作成するメモリ
= 2 +(driverMemory * 0.07、最小384m)= 2g + 0.524g = 2.524g
メモリオーバーヘッドをわずかに1024(1g)増やすだけで、ドライバメモリがわずか2gでジョブが正常に実行され、MEMORY_TOTALは2.524g!一方、オーバーヘッド構成がないと、11g未満のドライバーメモリは失敗しますが、式からは意味をなさないため、混乱しています。
メモリオーバーヘッドを(ドライバーとエグゼキューターの両方で)増やすと、ジョブがより低いMEMORY_TOTAL(12.154g vs 2.524g)で正常に完了するのはなぜですか?私が行方不明になっている他の内部の仕事がここにありますか?
/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 7g --executor-memory 1g --num-executors 3 --executor-cores 1 --jars <jar file>
11g未満のドライバーメモリでプログラムを実行すると、以下のエラーが表示されます。これは、SparkContextが停止されているか、同様のエラーが停止したSparkContextで呼び出されるメソッドです。私が集めたものから、これはメモリが十分ではないことに関連しています。
/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 7g --executor-memory 3g --num-executors 3 --executor-cores 1 --jars <jar file>
同じドライバーメモリでより高いエグゼキューターメモリでプログラムを実行すると、ジョブは最初のケースよりも長く(約3〜4分)実行され、その後、コンテナがより多くのメモリを要求/使用する以前とは異なるエラーが発生します許可され、そのために殺されています。エグゼキュータのメモリが増加し、最初のケースのエラーの代わりにこのエラーが発生するため、私は奇妙に感じますが。
/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 11g --executor-memory 1g --num-executors 3 --executor-cores 1 --jars <jar file>
10gを超えるドライバーメモリの設定は、ジョブを正常に実行できるようにします。
/bin/spark-submit --class <class name> --master yarn-cluster --driver-memory 2g --executor-memory 1g --conf spark.yarn.executor.memoryOverhead=1024 --conf spark.yarn.driver.memoryOverhead=1024 --num-executors 3 --executor-cores 1 --jars <jar file>
ジョブはこの設定で正常に実行されます(ドライバーメモリ2gおよびエグゼキューターメモリ1gが、ドライバーメモリオーバーヘッド(1g)およびエグゼキューターメモリオーバーヘッド(1g)を増加させます。
助けていただければ幸いであり、Sparkを理解する上で本当に役立ちます。前もって感謝します。
すべてのケースで使用
--executor-cores 1
1を超えることをお勧めします。5を超えないでください。私たちの経験とSpark開発者の推奨から。
例えば。 http://blog.cloudera.com/blog/2015/03/how-to-tune-your-Apache-spark-jobs-part-2/ :
A rough guess is that at most five tasks per executor
can achieve full write throughput, so it’s good to keep
the number of cores per executor below that number
エグゼキュータごとに1コアを超えることが推奨されている場所を参照することはできません。ただし、同じエグゼキュータで複数のタスクを実行すると、いくつかの共通メモリ領域を共有できるため、実際にメモリを節約できるという考え方です。
--executor-cores 2から開始し、ダブル--executor-memory(--executor-coresは、1つのexecutorが同時に実行するタスクの数も示すため)、それが何をするのかを確認します。環境は使用可能なメモリの点でコンパクトであるため、3または4にすると、メモリ使用率がさらに向上します。
Spark 1.5を使用し、GC問題を引き起こしていたため、かなり前に--executor-cores 1の使用を停止しました。また、Sparkバグのように見えます。これは、メモリを増やすだけでは、コンテナごとにタスクを増やすことに切り替えるほどの効果はなかったためです。同じエグゼキューター内のタスクは、異なる時間にメモリ消費をピークにする可能性があるため、メモリを無駄に使用したり、メモリを過剰にプロビジョニングしたりする必要はありません。
もう1つの利点は、Sparkのシェア変数(アキュムレーターとブロードキャスト変数)がタスクごとではなく、エグゼキューターごとに1つのコピーしか持たないことです。したがって、エグゼキューターごとに複数のタスクに切り替えると、直接メモリが節約されます。 Spark共有変数を明示的に使用しない場合でも、Sparkはとにかく内部でそれらを作成する可能性が高いです。たとえば、Spark SQLを介して2つのテーブルを結合する場合、SparkのCBOは、結合を高速化するために小さなテーブル(または小さなデータフレーム)をブロードキャストすることを決定する場合があります。
http://spark.Apache.org/docs/latest/programming-guide.html#shared-variables