Используйте Cython, если вы можете:
Синтаксис prange
очень похож на range
. Это позволяет вам легко проложить путь для создания цикла Python -> преобразовать его в Cython -> преобразовать его в параллельный цикл. Надеемся, что изменения, необходимые каждый раз, малы. Напротив, многопроцессорность требует, чтобы вы получили внутреннюю часть вашего цикла как функцию, а затем настроили ppols, поэтому он стал менее знакомым.
Профили OpenMP/Cython довольно низкие. Напротив, многопроцессорный модуль имеет относительно высокие служебные данные («процессы», как правило, медленнее, чем «потоки»).
Многопроцессорность довольно ограничена в Windows (все должно быть разборчиво). Это часто оказывается довольно хлопотным.
Там в нескольких конкретных обстоятельствах, когда вы должны использует многопроцессорный:
Вы находите, что Вы должны получить Gil много - многопроцессорный не разделяют GIL так не замедляется. Если вам нужно только время от времени получать GIL, хотя небольшие блоки with gil:
в Cython часто не замедляют вас слишком сильно, поэтому попробуйте это первым.
Вам нужно сделать кучу совершенно разных операций сразу (то есть что-то, что не поддается циклу prange
, потому что каждый поток действительно работает отдельным кодом). Если это так, синтаксис Cython prange
не подходит.
предостережений от глядя на ваш код, что вы должны избегать использования классов Cython, если вы можете. Если вы можете реорганизовать его на вызов функции cdef
, которая будет лучше (классы Cython по-прежнему будут нуждаться в GIL время от времени). Нечто похожее на следующее будет хорошо работать:
cdef int f(double[:] arr, double loop_specific_parameter, int constant_parameter) nogil:
# return your boolean to stop the iteration
# modify arr
return result
# then elsewhere
cdef int i
cdef double[:,:] output = np.zeros(shape)
for i in prange(len(parameters_to_try),nogil=True):
result = f(output[i,:],parameters_to_try[i],constant_parameter)
if result:
break
причина, почему я не рекомендую с помощью классов Cython является то, что 1) вы не можете создавать их или индекс списка из них без GIL (для подсчета ссылок причины) и 2) объекты Python, включая классы Cython, по-видимому, не могут быть потоковыми локальными. См. Cython parallel prange - thread locality? для примера проблем. (Первоначально я не знал об ограничении на то, чтобы быть местным местным)
Накладные расходы with_gil
не обязательно огромны, поэтому, если этот дизайн имеет наибольший смысл, попробуйте его. Глядя на использование вашего процессора, вы узнаете, насколько хорошо он распараллеливается.
Nb. Большинство плюсов/минусов в this set of answers по-прежнему применяется, хотя вы используете Cython, а не модуль потоковой передачи Python. Разница в том, что вы часто можете избежать GIL в Cython (поэтому некоторые из недостатков использования потоков менее значительны).
Следует отметить, что эта итерация называется довольно часто (1000x +). – macmallow