web-dev-qa-db-fra.com

obtenir le nombre de nœuds visibles dans PySpark

J'exécute quelques opérations dans PySpark et j'ai récemment augmenté le nombre de nœuds dans ma configuration (qui est sur Amazon EMR). Cependant, même si j'ai triplé le nombre de nœuds (de 4 à 12), les performances ne semblent pas avoir changé. En tant que tel, j'aimerais voir si les nouveaux nœuds sont visibles pour Spark.

J'appelle la fonction suivante:

sc.defaultParallelism
>>>> 2

Mais je pense que cela me dit le nombre total de tâches réparties sur chaque nœud, pas le nombre total de codes visibles par Spark.

Comment consulter la quantité de nœuds que PySpark utilise dans mon cluster? 

19
Bryan

sc.defaultParallelism est juste un indice. Selon la configuration, il peut ne pas avoir de relation avec le nombre de nœuds. Il s'agit du nombre de partitions si vous utilisez une opération qui utilise un argument de nombre de partitions mais que vous ne fournissez pas. Par exemple, sc.parallelize créera un nouveau RDD à partir d’une liste. Vous pouvez lui indiquer le nombre de partitions à créer dans le RDD avec le deuxième argument. Mais la valeur par défaut pour cet argument est sc.defaultParallelism.

Vous pouvez obtenir le nombre d'exécuteurs avec sc.getExecutorMemoryStatus dans l'API Scala, mais cela n'est pas exposé dans l'API Python.

En général, il est recommandé d’avoir environ 4 fois plus de partitions dans un RDD que d’exécuteurs. C'est un bon conseil, car s'il y a un écart dans le temps que prennent les tâches, cela va tout régler. Certains exécutants traiteront 5 tâches plus rapides tandis que d'autres traiteront 3 tâches plus lentes, par exemple.

Vous n'avez pas besoin d'être très précis avec cela. Si vous avez une idée approximative, vous pouvez aller avec une estimation. Comme si vous savez que vous avez moins de 200 processeurs, vous pouvez dire que 500 partitions iront bien.

Essayez donc de créer des RDD avec ce nombre de partitions:

rdd = sc.parallelize(data, 500)     # If distributing local data.
rdd = sc.textFile('file.csv', 500)  # If loading data from a file.

Ou repartitionnez le RDD avant le calcul si vous ne contrôlez pas la création du RDD:

rdd = rdd.repartition(500)

Vous pouvez vérifier le nombre de partitions dans un RDD avec rdd.getNumPartitions().

14
Daniel Darabos

Sur pyspark, vous pouvez toujours appeler l'API scala getExecutorMemoryStatus à l'aide du pont py4j de pyspark:

sc._jsc.sc().getExecutorMemoryStatus().size()
21
Nic

J'ai trouvé parfois que mes sessions étaient tuées par la télécommande, ce qui donnait une erreur Java

Py4JJavaError: An error occurred while calling o349.defaultMinPartitions.
: Java.lang.IllegalStateException: Cannot call methods on a stopped SparkContext.

J'ai évité cela par ce qui suit

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')
1

Il devrait être possible d’obtenir le nombre de nœuds du cluster en utilisant ceci (similaire à la méthode de @ Dan ci-dessus, mais plus courte et qui fonctionne mieux!).

sc._jsc.sc().getExecutorMemoryStatus().keySet().size()
1
Charles Newey

Les autres réponses permettent d’obtenir le nombre d’exécuteurs. Voici un moyen d'obtenir le nombre de nœuds. Cela inclut les nœuds de tête et de travail. 

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)  
0