したがって、一般的に、次の場合にcoalesce()
を使用する必要があることを理解しています。
filter
またはその他の操作により、パーティションの数が減少し、元のデータセット(RDD、DF)が減少する可能性があります。coalesce()
は、大きなデータセットをフィルタリングした後、操作をより効率的に実行するのに役立ちます。
また、必要な場合にのみデータを移動することでシャッフルを減らすため、repartition
よりも安価であることも理解しています。私の問題は、coalesce
が取るパラメーター(idealPartionionNo
)をどのように定義するかです。私は別のエンジニアから渡されたプロジェクトに取り組んでおり、彼は以下の計算を使用してそのパラメーターの値を計算していました。
// DEFINE OPTIMAL PARTITION NUMBER
implicit val NO_OF_EXECUTOR_INSTANCES = sc.getConf.getInt("spark.executor.instances", 5)
implicit val NO_OF_EXECUTOR_CORES = sc.getConf.getInt("spark.executor.cores", 2)
val idealPartionionNo = NO_OF_EXECUTOR_INSTANCES * NO_OF_EXECUTOR_CORES * REPARTITION_FACTOR
次に、これはpartitioner
オブジェクトで使用されます。
val partitioner = new HashPartitioner(idealPartionionNo)
と一緒に使用されます:
RDD.filter(x=>x._3<30).coalesce(idealPartionionNo)
これは正しいアプローチですか? idealPartionionNo
値の計算の背後にある主なアイデアは何ですか? REPARTITION_FACTOR
とは何ですか?それを定義するために一般的にどのように作業しますか?
また、YARNはオンザフライで利用可能なエグゼキュータを識別する責任があるので、その番号(AVAILABLE_EXECUTOR_INSTANCES
)をオンザフライで取得し、それをidealPartionionNo
の計算に使用する方法はありますか(つまり、NO_OF_EXECUTOR_INSTANCES
をAVAILABLE_EXECUTOR_INSTANCES
に置き換えます)?
理想的には、フォームのいくつかの実際の例:
n
executors with m
cores and partition factor equal tok
があるとします。その後:
また、これらを説明している素敵なブログを紹介していただければ幸いです。
実際には、最適なパーティション数は、使用可能なリソースよりも、使用するデータ、使用する変換、および全体的な構成に大きく依存します。
reduce
とは対照的にtreeReduce
など)を使用する場合、パーティションの数が多いと、ドライバーの負荷が高くなります。コアの数と比較してパーティションをオーバーサブスクライブすること(ファクター2または3が一般的であるようです)、またはパーティションを特定のサイズに保つことを提案するいくつかのルールを見つけることができますが、これは独自のコードを考慮していません:
私の考えでは:
エグゼキュータまたはコアの数に基づいて、固定数のパーティションを使用しようとしないでください。最初にデータとコードを理解し、次に理解を反映するように構成を調整します。
通常、クラスターが安定した動作を示すパーティションごとの生データの量を決定するのは比較的簡単です(私の経験では、データのロードに使用する形式、データ構造に応じて、数百メガバイトの範囲になります。および構成)。これはあなたが探している「マジックナンバー」です。
一般的に覚えておく必要のあるいくつかのこと:
*byKey
、join
、RDD.partitionBy
、Dataset.repartition
)データの分散が不均一になる可能性があります。重大なデータスキューの症状がないか、常にジョブを監視してください。union
、coGroup
、join
)を持つ操作は、パーティションの数に影響を与える可能性があります。あなたの質問は有効ですが、Sparkパーティショニングの最適化は実行中の計算に依存します完全に。再パーティショニング/合体する正当な理由が必要です。 RDDを数えているだけで(まばらに配置されたパーティションが大量にある場合でも)、再パーティション化/合体の手順を実行すると速度が低下します。
repartition(n)
(coalesce(n, shuffle = true)
とcoalesce(n, shuffle = false)
と同じ)の違いは、実行モデルと関係があります。シャッフルモデルは、元のRDDの各パーティションをランダムに取得します。データをすべてのエグゼキュータに送信し、新しい(少ないまたは多い)数のパーティションを持つRDDを生成します。シャッフルなしモデルは、複数のパーティションを1つのタスクとしてロードする新しいRDDを作成します。
この計算について考えてみましょう。
sc.textFile("massive_file.txt")
.filter(sparseFilterFunction) // leaves only 0.1% of the lines
.coalesce(numPartitions, shuffle = shuffle)
shuffle
がtrue
の場合、テキストファイル/フィルターの計算はtextFile
のデフォルトで指定されたいくつかのタスクで行われ、フィルター処理された小さな結果がシャッフルされます。 shuffle
がfalse
の場合、タスクの総数は最大でnumPartitions
になります。
numPartitions
が1の場合、違いは非常に大きくなります。シャッフルモデルは、データを並行して処理およびフィルタリングし、フィルタリングされた結果の0.1%をダウンストリームDAG操作のために1つのエグゼキュータに送信します。シャッフルなしモデルは、最初からすべて1つのコアでデータを処理およびフィルタリングします。
ダウンストリーム操作を検討してください。このデータセットを1回だけ使用している場合は、おそらく再パーティション化する必要はまったくありません。後で使用するために(たとえばディスクに)フィルタリングされたRDDを保存する場合は、上記のトレードオフを考慮してください。これらのモデルに慣れるには経験が必要であり、パフォーマンスが向上すると、両方を試して、パフォーマンスを確認してください。
他の人が答えたように、あなたが求めるものを計算する公式はありません。そうは言っても、最初の部分について知識に基づいて推測し、時間をかけて微調整することができます。
最初のステップは、十分なパーティションがあることを確認することです。 NO_OF_EXECUTOR_INSTANCESエグゼキューターとエグゼキューターごとのNO_OF_EXECUTOR_CORESコアがある場合は、NO_OF_EXECUTOR_INSTANCES * NO_OF_EXECUTOR_CORESパーティションを同時に処理できます(それぞれが特定のインスタンスの特定のコアに移動します)。つまり、これはすべてがコア間で均等に分割され、すべてが処理にまったく同じ時間を要することを前提としています。これはめったにありません。局所性(たとえば、データが別のノードから取得する必要がある)のため、または単にバランスが取れていないため(たとえば、データがルートドメインでパーティション化されている場合、グーグルはおそらくかなり大きいでしょう)。ここでREPARTITION_FACTORが役立ちます。アイデアは、各コアを「オーバーブッキング」することです。したがって、1つが非常に速く終了し、もう1つがゆっくり終了する場合、タスクをそれらの間で分割するオプションがあります。一般に、2〜3の因数は良い考えです。
次に、単一のパーティションのサイズを見てみましょう。データ全体のサイズがXMBで、N個のパーティションがあるとします。各パーティションは平均X/NMBになります。 NがXに比べて大きい場合、平均パーティションサイズが非常に小さい可能性があります(たとえば、数KB)。この場合、各パーティションの管理のオーバーヘッドが高くなりすぎるため、通常はNを低くすることをお勧めします。一方、サイズが非常に大きい場合(たとえば、数GB)、同時に大量のデータを保持する必要があり、ガベージコレクション、メモリ使用量の増加などの問題が発生します。
最適なサイズは良い質問ですが、一般的に人々は100〜1000 MBのパーティションを好むようですが、実際には数十MBもおそらく良いでしょう。
注意すべきもう1つの点は、パーティションがどのように変化するかを計算するときです。たとえば、それぞれ100MBの1000パーティションから始めて、各パーティションが1Kになるようにデータをフィルタリングすると、おそらく合体する必要があります。 groupbyを実行したり、参加したりすると、同様の問題が発生する可能性があります。このような場合、パーティションのサイズとパーティションの数の両方が変化し、望ましくないサイズに達する可能性があります。