Parallelism в Python
Каковы варианты достижения parallelism в Python? Я хочу выполнить кучу вычислений, связанных с процессором, на некоторых очень больших растровках и хотел бы их распараллелить. Исходя из фона C, я знаком с тремя подходами к parallelism:
- Процессы передачи сообщений, возможно, распределенные по кластеру, например. MPI.
- Явная разделяемая память parallelism, либо с использованием pthreads или fork(), pipe(), et. аль
- Неявная разделяемая память parallelism с использованием OpenMP.
Решение о подходе к использованию - это упражнение в компромиссах.
В Python, какие подходы доступны и каковы их характеристики? Есть ли кластерный клон MPI? Каковы предпочтительные способы обеспечения общей памяти parallelism? Я слышал ссылку на проблемы с GIL, а также ссылки на тасклеты.
Короче говоря, что мне нужно знать о разных стратегиях параллелизации в Python, прежде чем выбирать между ними?
Ответы
Ответ 1
Как правило, вы описываете вычисление привязки CPU. Это не Python forte. Ни исторически, ни многопроцессорно.
Threading в основном интерпретаторе Python управляется страшной глобальной блокировкой. Новый API multiprocessing работает вокруг этого и дает абстракцию рабочего пула с помощью труб и очередей и т.д.
Вы можете написать критический код производительности в C или Cython и использовать Python для клея.
Ответ 2
Новый модуль (2.6) multiprocessing - это путь. Он использует подпроцессы, которые затрагивают проблему GIL. Он также абстрагирует некоторые локальные/удаленные проблемы, поэтому выбор запуска вашего кода локально или распространение по кластеру можно сделать позже. Документация, которую я связал выше, - это честный бит, чтобы пережевывать, но должен обеспечить хорошую основу для начала работы.
Ответ 3
Вам может быть интересно Stackless Python.
Ответ 4
Существует много пакетов, наиболее подходящих, поскольку другие говорят, что это многопроцессорность, особенно с классом "Пул".
Аналогичный результат можно получить параллельный питон, который, кроме того, предназначен для работы с кластерами.
В любом случае, я бы сказал, многопроцессорный.
Ответ 5
В зависимости от того, сколько данных вам нужно обрабатывать и сколько процессоров/машин вы собираетесь использовать, в некоторых случаях лучше записать часть его в C (или Java/С#, если вы хотите использовать jython/IronPython )
Ускорение, которое вы можете получить от этого, может сделать больше для вашей производительности, чем параллельное выполнение на 8 процессорах.
Ответ 6
Ray - это элегантная (и быстрая) библиотека для этого.
Самая основная стратегия распараллеливания функций Python - это объявление функции с @ray.remote
декоратора @ray.remote
. Затем он может быть вызван асинхронно.
import ray
import time
# Start the Ray processes (e.g., a scheduler and shared-memory object store).
ray.init(num_cpus=8)
@ray.remote
def f():
time.sleep(1)
# This should take one second assuming you have at least 4 cores.
ray.get([f.remote() for _ in range(4)])
Вы также можете распараллелить вычисление с сохранением состояния с помощью акторов, опять же с помощью декоратора @ray.remote
.
# This assumes you already ran 'import ray' and 'ray.init()'.
import time
@ray.remote
class Counter(object):
def __init__(self):
self.x = 0
def inc(self):
self.x += 1
def get_counter(self):
return self.x
# Create two actors which will operate in parallel.
counter1 = Counter.remote()
counter2 = Counter.remote()
@ray.remote
def update_counters(counter1, counter2):
for _ in range(1000):
time.sleep(0.25)
counter1.inc.remote()
counter2.inc.remote()
# Start three tasks that update the counters in the background also in parallel.
update_counters.remote(counter1, counter2)
update_counters.remote(counter1, counter2)
update_counters.remote(counter1, counter2)
# Check the counter values.
for _ in range(5):
counter1_val = ray.get(counter1.get_counter.remote())
counter2_val = ray.get(counter2.get_counter.remote())
print("Counter1: {}, Counter2: {}".format(counter1_val, counter2_val))
time.sleep(1)
Он имеет ряд преимуществ перед многопроцессорным модулем:
- Один и тот же код работает как на одной многоядерной машине, так и на большом кластере.
- Данные эффективно распределяются между процессами на одном компьютере с использованием общей памяти и эффективной сериализации.
- Вы можете распараллелить функции Python (используя задачи) и классы Python (используя актеры).
- Сообщения об ошибках распространяются хорошо.
Рэй - это основа, которую я помогал развивать.