数日前、何人かの友人から、spark ジョブのリソース割り当てについて尋ねられました。つまり、ジョブを送信するときに、割り当てるべきリソースの数がわかりません。私の答えは、経験に頼ることです. よくよく考えてみれば、経験に頼ることは言わないことと同じです. いくつかの方法論やアイデアがあるはずです. この記事がありますが、書いたときは本当に書き方がわからなかったので、インターネットで検索して、大物がどのように答えたかを調べました。偶然にも、誰かが 3 年前にこの質問をしたことを本当に知りました。
コメントを読んで自分は理解できた気がしますが、友達が理解できるかどうかわからないので、詳しく説明したほうがいいと思います
まず最初に、spark の公式 Web サイトでハードウェア レベルの提案がいくつか提供されています。最初のリンクは https://spark.apache.org/docs/latest/hardware-provisioning.html です。
ただし、この記事では、アプリケーション レベルで非常に細かい方法でリソースを割り当てる方法については紹介しません。ただし、メモリや CPUなど、関連するいくつかの指示を参照できます。
まず、次のように、spark のこれら 2 つの部分に関連するパラメーターを確認しましょう。
--num-executors/ (SparkSQL の Spark.executor.instances パラメーター) |
このパラメーターは、ジョブによって使用されるエグゼキューターの総数を表します |
--driver-memory/ (SparkSQL は spark.driver.memory パラメーターで構成されます) |
このパラメータは、Driver 側で消費されるメモリを表します. 通常、Driver 側はあまり多くのリソースを消費しないため、多くのリソースを与える必要はありません. |
--executor-memory (SparkSQL は spark.executor.memory パラメーターで構成されます) |
このパラメータは、各エグゼキュータが占有するメモリを表します |
--executor-cores/ (SparkSQL は spark.executor.cores パラメーターで構成されます) |
このパラメーターは、エグゼキューターで並列に実行できるタスクの数を表します (並列と同時の違いに注意してください!) |
通常、Spark ジョブによって消費される合計メモリ >=(spark.executor.instances)*(spark.exetor.memory);
占有されている CPU の数 >= (spark.executor.instances) * (spark.exector.cores)。
ここで「大なり」が使用されている理由は、AppMaster もリソースを占有するためです。AppMaster に関しては、Yarn 部分の 2 つのパラメーターを確認する必要があります。
yarn.nodemanager.resource.memory-mb |
このパラメーターは、nm が Yarn に使用可能な最大メモリーを使用できることを示します。 |
yarn.nodemanager.resource.cpu-vcores |
このパラメーターは、nm が糸に使用できる仮想 CPU の最大数を示します。 |
一般に、実際の本番環境では、yarn が割り当てることができるリソースの合計が割り当てられている必要があります。個別のスパーク ジョブ キューもあります (ここでも、フェア、FIFO、またはキャパシティのいずれであるかは、糸のスケジューリング モードによって異なります)。
ここで例を挙げて説明しましょう: 合計 6 ノードのベア クラスタがあり、各ノードが 16c 64g で構成されているとします (実際には、各ノードの構成は不均一である可能性があります)。
しかし、すべてのリソースをヤーンに割り当てることは不可能であり、システム運用のために一部を確保する必要があるため、各ノードは 1C と 1G を確保し、極端な方法を取る必要があります。最後に、糸によって割り当てられる各ノードで使用可能なリソースは次のとおりです。
yarn.nodemanager.resource.memory-mb=63g
yarn.nodemanager.resource.cpu-vcores=15
この場合、リソースの合計は all_memory=63*6=378g; all_cpu=6*15=90c です。
各 Executor の並列処理が 5 であると仮定すると、90/5=18 の Executor が必要になりますが、AppMaster 用に 1 つ予約する必要があるため、–num-exectors=17; 合計 18 の Executor が必要であると計算しただけです。合計 6 ノード, 平均して, 各ノードは 3 つのエグゼキュータを開始します, そして 1 つのノードは 63g であるため, 各エグゼキュータは 21g のメモリを占有できます. 注意: 各エグゼキュータはジョブのために 21g をすべて使用するわけではありません, スタック用のリソースも予約します. storage , バッファーのオーバーヘッドは安定性を確保するために使用されます, これはしばしばオフヒープメモリーと呼ばれます. このブロックのオーバーヘッドは spark.executor.memoryOverhead パラメーターによって設定されます, その値 = max(384mb, 0.1*executorMemory) )。したがって、オフヒープ メモリのこの部分 = max(384mb, 0.1*21)~=2g です。次に、ヒープメモリ = 21-2 = 19g です。
要約する表は次のとおりです。
つまり、ジョブを送信するとき、そのパラメーター構成値は次の値を超えることはできません (この例では、すべてのリソースが使用のためにタスクに与えられていると仮定しています!):
--executor-cores / spark.executor.cores = 5--executor-memory / spark.executor.memory = 19--num-executors / spark.executor.instances = 17
ノード数 |
メモリ/ノード |
CPU/ノード |
糸は最大量のメモリを割り当てることができます |
糸は最大のCPUを割り当てることができます |
各エグゼキューターの並列度を想定する |
エグゼキュータの総数 |
実際に働いているエグゼキュータの数 |
各ノードが開始できるエグゼキューターの数 |
各エグゼキュータが占有するメモリ |
オフヒープ メモリ |
実際の作業に使用されるメモリ |
6 |
64g |
16C |
63g×6=378g |
15C*6=90C |
5 |
90℃/5=18 |
18-1=17 |
18/6=3 |
63g/3=21g |
最大(384MB,0.1*21g)=2g |
21g-2g=19g |
9 |
90c/9=10 |
10-1=9 |
10/6~=2 |
63g/~=2~=37g |
最大(384MB,0.1*37g)=3g |
37g-3=34g |
一部の友人は、なぜ各エグゼキューターの並列処理が 5 に設定されているのか、当然、それを増やすこともできるので、混乱するかもしれません。If you increase the parallelism of each executor, it is equal to Improvement the parallelism capability, which reduce the number of polling tasks. たとえば、100 個のタスクがあり、各エグゼキューターが 20 個のタスクを実行する場合、5 回ポーリングする必要があります。各エグゼキュータが 50 のタスクを設定すると、ポーリングが 2 回必要になります; これにより、各エグゼキュータが保持するメモリが増加します。
実際、前回のフォーラムで言及された評価方法の 1 つは、タスクの数に応じて逆方向に推論することであり、公式には、CPU コアが 2 ~ 3 のタスクを処理するというものです。
次にタスクが100個あると仮定して最大で50c必要か、上記の例で言えば、現時点では各ノードを均等に共有する方法をとるか、少数のノードに処理を集中させるかで決まります。もちろん、採用する方法は、実際に処理するデータの量と計算の複雑なロジックと組み合わせる必要があります (ネットワークの消費や局所的な計算、各ノードの負荷などもここで考慮する必要があるため)。 、共有の方法が通常採用されている場合、各ノードはおそらく8cを使用します。では、各ノードはいくつのエグゼキューターを開始するのでしょうか? 1 つのエグゼキューターを開始するのか、それとも 2 つのエグゼキューターを開始するのか、各エグゼキューターはどのくらいのメモリを占有するのか? 現時点では、コード ロジックがより多く計算するか、より多くキャッシュするかによって異なります。これは、メモリ モデルが関与する場所です. メモリ モデルを知らない人のために, 私の元の記事を参照してください:タングステン オン スパーク メモリ モデルの設計
上記のリソース割り当ては評価されていますが、その後の最適化が必要ないという意味ではありません. そうでなければ、なぜインターネット上にこれほど多くの最適化記事があるのでしょうか? 同時に、チームワーク リソースにも注意を払う必要があります.すべてのリソースをあなたのために使用することはできません。
そのため、評価するリソースの一部を減らす必要があるため、常に調整を行う必要がある場合があります. これが、多くの人がリソースの割り当て方法を尋ねるとき、経験に頼っていると言う理由です!
編集者は、このことに適用する公式は実際にはないと考えています。
リソースを割り当てるためのより良い方法論がある場合、または何かが間違っている場合は、私に連絡して他の友人と共有してください.
他に困ったことがあれば、私に嫌がらせを歓迎します~
参考:
-
スパーク公式サイト
-
https://bbs.csdn.net/topics/392153088