web-dev-qa-db-fra.com

Diffuser un dictionnaire au format RDD dans PySpark

Je commence tout juste à maîtriser Spark, et ma fonction doit être mappée sur une variable rdd, mais utilise un dictionnaire global:

from pyspark import SparkContext

sc = SparkContext('local[*]', 'pyspark')

my_dict = {"a": 1, "b": 2, "c": 3, "d": 4} # at no point will be modified
my_list = ["a", "d", "c", "b"]

def my_func(letter):
    return my_dict[letter]

my_list_rdd = sc.parallelize(my_list)

result = my_list_rdd.map(lambda x: my_func(x)).collect()

print result

Ce qui précède donne le résultat attendu. Cependant, je ne suis vraiment pas sûr de mon utilisation de la variable globale my_dict. Il semble qu'une copie du dictionnaire est faite avec chaque partition. Et ça ne se sent pas bien ..

Il ressemblait à broadcast est ce que je recherche. Cependant, quand j'essaye de l'utiliser:

my_dict_bc = sc.broadcast(my_dict)

def my_func(letter):
    return my_dict_bc[letter] 

Je reçois l'erreur suivante:

TypeError: 'Broadcast' object has no attribute '__getitem__

Cela semble impliquer que je ne peux pas diffuser un dictionnaire.

Ma question: Si j’ai une fonction qui utilise un dictionnaire global, elle doit être mappée sur rdd, quelle est la bonne façon de le faire?

Mon exemple est très simple, mais en réalité, my_dict et my_list sont beaucoup plus volumineux et my_func est plus compliqué.

18
Akavall

Vous avez oublié quelque chose d'important à propos des objets Broadcast: ils ont une propriété appelée value où les données sont stockées.

Par conséquent, vous devez modifier my_func en quelque chose comme ceci:

my_dict_bc = sc.broadcast(my_dict)

def my_func(letter):
    return my_dict_bc.value[letter] 
24
Alberto Bonsanto

La manière appropriée de le faire dépend de la manière dont les variables partagées en lecture seule (le dictionnaire dans votre cas) seront accessibles dans le reste du programme. Dans le cas que vous avez décrit, vous n'avez pas besoin d'utiliser une variable de diffusion. De la section du guide de programmation Spark sur les variables de diffusion :

Spark diffuse automatiquement les données communes nécessaires aux tâches de chaque étape. Les données ainsi diffusées sont mises en cache sous forme sérialisée et désérialisées avant l'exécution de chaque tâche. Cela signifie que la création explicite de variables de diffusion n'est utile que lorsque les tâches de plusieurs étapes nécessitent les mêmes données ou lorsque la mise en cache des données sous forme désérialisée est importante.

Dans votre cas, si les données ne sont nécessaires que dans la phase de carte unique, il n'est pas nécessaire de diffuser explicitement la variable (ce n'est pas "utile"). Cependant, si le même dictionnaire devait être utilisé plus tard dans une autre étape, vous pouvez utiliser broadcast pour éviter la sérialisation et la désérialisation du dictionnaire avant chaque étape.

1
shaneb