Pierwszy podejście działa, ponieważ Spark jest za pomocą specjalnych strategii serializacji przetwarzać zamknięcia wymaganych dla przekształceń, które jest znacznie wolniejsze, ale bardziej wydajne niż średnia pickle
(inaczej nie mogliśmy skorzystać .map(lambda x: ...)
).
Ostatnie podejście działa, ponieważ nie ma potrzeby serializowania kodu funkcji w ogóle. Odwołuje się do modułu sqrt
od numpy
tak długo, jak NumPy jest dostępny dla każdego pracownika, nie ma problemu.
Drugie podejście nie działa, ponieważ marynowanie nie powoduje serializacji kodu.
import pickle
pickle.dumps(my_sqrt)
## b'\x80\x03c__main__\nmy_sqrt\nq\x00.'
Wszystko robi stwierdza proszę mi dać obiekt przypisany do my_sqrt
(my_sqrt.__name__
) ze skryptu środowiska najwyższego poziomu (a.k.a. __main__
). Gdy jest wykonywany na robotach, nie korzysta z tego samego środowiska i nie ma już takiego obiektu w zakresie, stąd wyjątek. Dla jasności nie jest to ani błąd, ani coś konkretnego dla Sparka. można łatwo odtworzyć samo zachowanie lokalnie następująco:
In [1]: import pickle
In [2]: def foo(): ...
In [3]: foo_ = pickle.dumps(foo)
In [4]: pickle.loads(foo_)
Out[4]: <function __main__.foo>
In [5]: del foo
In [6]: pickle.loads(foo_)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
...
AttributeError: Can't get attribute 'foo' on <module '__main__'>
Ponieważ nie zajmuje się rzeczywistej wartości można nawet przypisać tak:
In [7]: foo = "foo"
In [8]: pickle.loads(foo_)
Out[8]: 'foo'
Zabierz wiadomość tutaj jest jeśli chcesz użyć funkcji w ten sposób, umieść ją w osobnym module i rozprowadź wśród pracowników tak samo, jak w przypadku innych zależności, w tym definicji klas niestandardowych.
Czy możesz umieścić link do jakiegoś materiału, który rozszerza się na "specjalną strategię serializacji", której używa iskra zamiast marynowania? – x89a10
@ x89a10 Spark używa [zmodyfikowanej wersji] (https://github.com/apache/spark/blob/33ae7a35daa86c34f1f9f72f997e0c2d4cd8abec/python/pyspark/cloudpickle.py) z ['cloudpickle'] (https://github.com/cloudpipe/cloudpickle). Istnieje kilka innych elementów rozproszonych, ale to powinno dać ci wystarczająco dużo, aby zrozumieć różnicę. – zero323