上記のパラメータの調整はどこから始めますか。エグゼキュータメモリから始めてエグゼキュータの数を取得しますか、それともコアから始めてエグゼキュータ番号を取得しますか。リンクをたどった。しかし、高レベルのアイデアを得ましたが、どのように、どこから始めて最終的な結論に到達するかはまだわかりません。
回答:
次の回答は、タイトルに記載されている3つの主要な側面、つまりエグゼキュータの数、エグゼキュータのメモリ、およびコアの数をカバーしています。ドライバーメモリなど、この回答の時点では取り上げていないパラメーターが他にもある可能性がありますが、近い将来追加したいと思います。
ケース1ハードウェア-6ノード、および各ノード16コア、64 GB RAM
各エグゼキュータはJVMインスタンスです。したがって、1つのノードに複数のエグゼキュータを含めることができます
OSとHadoopデーモンには最初の1コアと1GBが必要なので、15コア、各ノードに63GBのRAMが利用可能です。
コアの数を選択する方法から始めます:
Number of cores = Concurrent tasks as executor can run
So we might think, more concurrent tasks for each executor will give better performance. But research shows that
any application with more than 5 concurrent tasks, would lead to bad show. So stick this to 5.
This number came from the ability of executor and not from how many cores a system has. So the number 5 stays same
even if you have double(32) cores in the CPU.
遺言執行者の数:
Coming back to next step, with 5 as cores per executor, and 15 as total available cores in one Node(CPU) - we come to
3 executors per node.
So with 6 nodes, and 3 executors per node - we get 18 executors. Out of 18 we need 1 executor (java process) for AM in YARN we get 17 executors
This 17 is the number we give to spark using --num-executors while running from spark-submit shell command
各エグゼキュータのメモリ:
From above step, we have 3 executors per node. And available RAM is 63 GB
So memory for each executor is 63/3 = 21GB.
However small overhead memory is also needed to determine the full memory request to YARN for each executor.
Formula for that over head is max(384, .07 * spark.executor.memory)
Calculating that overhead - .07 * 21 (Here 21 is calculated as above 63/3)
= 1.47
Since 1.47 GB > 384 MB, the over head is 1.47.
Take the above from each 21 above => 21 - 1.47 ~ 19 GB
So executor memory - 19 GB
最終番号-エグゼキュータ-17、コア5、エグゼキュータメモリ-19 GB
ケース2ハードウェア:同じ6ノード、32コア、64 GB
5は、良好な並行性についても同じです
各ノードのエグゼキュータの数= 32 / 5〜6
したがって、エグゼキュータの総数= 6 * 6ノード= 36です。AM= 35の場合、最終的な数は36-1になります。
エグゼキュータメモリは、ノードごとに6つのエグゼキュータです。63 / 6〜10。オーバーヘッドは.07 * 10 = 700MBです。したがって、オーバーヘッドとして1GBに丸めると、10-1 = 9GBになります。
最終的な数値-エグゼキュータ-35、コア5、エグゼキュータメモリ-9 GB
ケース3
上記のシナリオは、コアの数を固定として受け入れ、エグゼキュータとメモリの数に移動することから始まります。
最初のケースでは、19 GBは必要ないと考え、10 GBで十分である場合、次の数値が表示されます。
コア5各ノードのエグゼキュータの数= 3
この段階では、これは21になり、最初の計算では19になります。ただし、10で問題ないと考えたため(オーバーヘッドが少ないと想定)、ノードあたりのエグゼキュータの数を6に切り替えることはできません(63/10など)。ノードあたり6つのエグゼキュータと5つのコアがある場合、16コアしかない場合、ノードあたり30コアになります。したがって、各エグゼキュータのコア数も変更する必要があります。
もう一度計算すると、
マジックナンバー5は3になります(5以下の任意の数)。したがって、3つのコアと15の使用可能なコアを使用すると、ノードごとに5つのエグゼキューターが得られます。したがって、(5 * 6 -1)= 29エグゼキュータ
したがって、メモリは63 / 5〜12です。オーバーヘッドは12 * .07 = .84です。したがって、エグゼキュータメモリは12-1 GB = 11GBです。
最終的な数は29エグゼキュータ、3コア、エグゼキュータメモリは11GBです
動的割り当て:
注:動的割り振りが有効になっている場合のエグゼキューターの数の上限。つまり、sparkアプリケーションは必要に応じてすべてのリソースを使い果たす可能性があるということです。したがって、他のアプリケーションが実行されていて、タスクを実行するためにコアも必要なクラスターでは、クラスターレベルで実行するようにしてください。つまり、ユーザーアクセスに基づいて、YARNに特定の数のコアを割り当てることができます。したがって、spark_userを作成して、そのユーザーにコア(最小/最大)を与えることができます。これらの制限は、SparkとYARNで実行される他のアプリケーション間で共有するためのものです。
spark.dynamicAllocation.enabled-これがtrueに設定されている場合-エグゼキュータについて言及する必要はありません。理由は以下のとおりです。
spark-submitで指定する静的パラメーター番号は、ジョブ期間全体のものです。ただし、動的割り当てが明らかになると、次のようなさまざまな段階があります。
何から始めるか:
開始するエグゼキュータの初期数(spark.dynamicAllocation.initialExecutors)
幾つ :
次に、負荷(保留中のタスク)に基づいて、要求する数。これは、最終的には静的な方法でspark-submitで与える数値になります。したがって、初期エグゼキュータ番号が設定されたら、最小(spark.dynamicAllocation.minExecutors)および最大(spark.dynamicAllocation.maxExecutors)番号に移動します。
いつ尋ねるか与えるか:
新しいエグゼキュータをいつリクエストしますか(spark.dynamicAllocation.schedulerBacklogTimeout)-これだけの期間、保留中のタスクがあります。だからリクエストしてください。各ラウンドで要求されるエグゼキュータの数は、前のラウンドから指数関数的に増加します。たとえば、アプリケーションは最初のラウンドで1つのエグゼキュータを追加し、次のラウンドで2、4、8などのエグゼキュータを追加します。特定の時点で、上記の最大値が明らかになります
いつエグゼキューターを提供しますか(spark.dynamicAllocation.executorIdleTimeout)-
私が何かを逃したならば、私を訂正してください。上記は、私が問題で共有したブログといくつかのオンラインリソースに基づく私の理解です。ありがとうございました。
参照:
spark.executor.cores
ので、デフォルトで利用可能なすべてを使用する可能性があります。
また、ユースケースによって異なりますが、重要な構成パラメーターは次のとおりです。
spark.memory.fraction
(実行とストレージに使用される(ヒープスペース-300MB)の割合)http://spark.apache.org/docs/latest/configuration.html#memory-managementから。
キャッシュ/永続化を使用しない場合は、0.1に設定して、プログラムのすべてのメモリを確保します。
キャッシュ/永続化を使用する場合は、次のメモリを確認できます。
sc.getExecutorMemoryStatus.map(a => (a._2._1 - a._2._2)/(1024.0*1024*1024)).sum
HDFSまたはHTTPからデータを読み取りますか?
繰り返しますが、チューニングはユースケースによって異なります。
spark.memory.storageFraction=0.1
か?AFAIKspark.memory.fraction
は、実行とストレージのSpark
両方に使用されるメモリの量を決定し(すでに説明しました)、メモリの量(ストレージと実行に使用可能)のみがキャッシュの削除の影響を受けないためです。このリンクを参照してくださいspark.memory.storageFraction