PySparkでいくつかの操作を実行していて、最近(Amazon EMRにある)構成でノードの数を増やしました。ただし、ノード数を3倍(4から12)にしても、パフォーマンスは変化していないようです。そのため、新しいノードがSparkに表示されるかどうかを確認します。
次の関数を呼び出しています:
sc.defaultParallelism
>>>> 2
しかし、これは、Sparkが認識できるコードの総数ではなく、各ノードに分散されたタスクの総数を示していると思います。
PySparkがクラスターで使用しているノードの数を確認するにはどうすればよいですか?
_sc.defaultParallelism
_は単なるヒントです。構成によっては、ノードの数とは関係がない場合があります。これは、パーティションカウント引数を取る操作を使用するが、提供しない場合のパーティション数です。たとえば、_sc.parallelize
_はリストから新しいRDDを作成します。 2番目の引数を使用して、RDDに作成するパーティションの数を指定できます。ただし、この引数のデフォルト値は_sc.defaultParallelism
_です。
Scala APIでは_sc.getExecutorMemoryStatus
_を使用してエグゼキューターの数を取得できますが、これはPython APIでは公開されていません。
一般に、推奨事項は、エグゼキューターの約4倍のパーティションをRDDに含めることです。これは良いヒントです。タスクにかかる時間にばらつきがある場合は、それが解消されるからです。たとえば、一部のエグゼキューターは5つの高速タスクを処理し、他のエグゼクターは3つの低速タスクを処理します。
これで非常に正確である必要はありません。大まかなアイデアがある場合は、見積もりで行くことができます。 CPUの数が200未満であることがわかっている場合と同様に、500パーティションで問題ないと言えます。
したがって、次の数のパーティションでRDDを作成してみてください。
_rdd = sc.parallelize(data, 500) # If distributing local data.
rdd = sc.textFile('file.csv', 500) # If loading data from a file.
_
または、RDDの作成を制御しない場合は、計算の前にRDDを再分割します。
_rdd = rdd.repartition(500)
_
rdd.getNumPartitions()
を使用して、RDDのパーティション数を確認できます。
Pysparkでは、pysparkのpy4jブリッジを使用してscala getExecutorMemoryStatus
APIを呼び出すことができます。
sc._jsc.sc().getExecutorMemoryStatus().size()
これを使用して、クラスター内のノード数を取得できるはずです(上記の@Danの方法に似ていますが、短くて機能します)。
sc._jsc.sc().getExecutorMemoryStatus().keySet().size()
リモートによってセッションが強制終了されて、奇妙なJavaエラーが発生することがありました。
Py4JJavaError: An error occurred while calling o349.defaultMinPartitions.
: Java.lang.IllegalStateException: Cannot call methods on a stopped SparkContext.
私はこれを次のようにして避けました
def check_alive(spark_conn):
"""Check if connection is alive. ``True`` if alive, ``False`` if not"""
try:
get_Java_obj = spark_conn._jsc.sc().getExecutorMemoryStatus()
return True
except Exception:
return False
def get_number_of_executors(spark_conn):
if not check_alive(spark_conn):
raise Exception('Unexpected Error: Spark Session has been killed')
try:
return spark_conn._jsc.sc().getExecutorMemoryStatus().size()
except:
raise Exception('Unknown error')
他の回答は、実行者の数を取得する方法を提供します。ノードの数を取得する方法は次のとおりです。これには、ヘッドノードとワーカーノードが含まれます。
s = sc._jsc.sc().getExecutorMemoryStatus().keys()
l = str(s).replace("Set(","").replace(")","").split(", ")
d = set()
for i in l:
d.add(i.split(":")[0])
len(d)