2016-01-13 16 views
13

jestem po prostu coraz zawiesić Spark, i mam funkcji, które muszą być odwzorowane na rdd, ale używa globalnego słownika:Broadcast słownikiem do RDD w PySpark

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 

Powyższe daje oczekiwany wynik; jednak nie jestem pewien co do korzystania z globalnej zmiennej my_dict. Wygląda na to, że kopia słownika jest tworzona przy każdej partycji. I po prostu nie czuje się dobrze ..

Wyglądało na to, że szukam broadcast. Jednak, gdy próbuję go użyć:

my_dict_bc = sc.broadcast(my_dict) 

def my_func(letter): 
    return my_dict_bc[letter] 

pojawia się następujący błąd:

TypeError: 'Broadcast' object has no attribute '__getitem__ 

To zdaje się sugerować, że nie można nadawać słownika.

Moje pytanie: Jeśli mam funkcję korzystającą ze słownika globalnego, która musi zostać przypisana do rdd, jaki jest właściwy sposób jej wykonania?

Mój przykład jest bardzo prosty, ale w rzeczywistości my_dict i my_list są znacznie większe, a my_func jest bardziej skomplikowany.

Odpowiedz

15

Zapomniałeś czegoś ważnego o obiektach Broadcast, mają one właściwość o nazwie value, w której przechowywane są dane.

Dlatego trzeba zmodyfikować my_func do czegoś takiego:

my_dict_bc = sc.broadcast(my_dict) 

def my_func(letter): 
    return my_dict_bc.value[letter] 
+0

widzę !, Więc kiedy dodać 'my_dict_bc.value' działa poprawnie. A "nadawanie" to standardowe podejście do pracy z obiektami, które są udostępniane, prawda? – Akavall

+0

Tak, jest to dobra praktyka, jednak jeśli słownik nie jest zbyt duży, można użyć obiektu globalnego bez żadnego problemu. –

+0

To ma sens. Dziękuję Ci. – Akavall