Подтвердить что ты не робот

OpenMP и Python

У меня есть опыт в кодировании OpenMP для компьютеров с общей памятью (как в C, так и в FORTRAN) для выполнения простых задач, таких как сложение матриц, умножение и т.д. (просто посмотреть, как он конкурирует с LAPACK). Я знаю, что OpenMP достаточно для выполнения простых задач без необходимости просмотра документации.

Недавно я перешел на Python для своих проектов, и у меня нет опыта работы с Python за пределами абсолютных основ.

Мой вопрос:

Каков самый простой способ использования OpenMP в Python? Проще всего, я имею в виду тот, который требует минимальных усилий на стороне программиста (даже если это происходит за счет дополнительного системного времени)?

Причина, по которой я использую OpenMP, заключается в том, что серийный код может быть преобразован в рабочий параллельный код с несколькими !$OMP, разбросанными вокруг. Время, необходимое для достижения грубой распараллеливания, увлекательно мало. Есть ли способ воспроизвести эту функцию в Python?

От просмотра в SO, я могу найти:

  • Расширения C
  • StackLess Python

Есть ли еще? Что лучше всего подходит для моего вопроса?

4b9b3361

Ответ 1

Из-за GIL нет смысла использовать потоки для задач с интенсивным процессором в CPython. Вам нужно либо многопроцессорное обслуживание (пример), либо использовать расширения C, которые выпускают GIL во время вычислений, например, некоторые функции numpy, пример.

Вы можете легко написать C-расширения, которые используют несколько потоков в Cython, пример.

Ответ 2

Насколько мне известно, для Python нет пакета OpenMP (и я не знаю, что бы он сделал, если бы он был). Если вам нужны потоки непосредственно под вашим контролем, вам придется использовать одну из библиотек потоков. Однако, как отмечают другие, GIL (Global Interpreter Lock) делает многопоточность в Python для производительности немного... ну, бессмысленно *. GIL означает, что только один поток может получить доступ к интерпретатору за раз.

Я бы предложил посмотреть на NumPy/SciPy. NumPy позволяет писать код Matlab-esque, в котором вы работаете с массивами и матрицами с одиночными операциями. Он также имеет некоторые возможности параллельной обработки, см. SciPy Wiki.

Другие места для поиска:

* Хорошо, это не бессмысленно, но если время не потребляется за пределами кода Python (например, внешним процессом, вызванным с помощью popen или некоторых таких), потоки не собираются покупать вам ничего, кроме удобство.

Ответ 3

Если вы хотите выпустить GIL и использовать OpenMP ypu, можете взглянуть на Cython. Он предлагает простой parallelism для некоторых общих задач. Вы можете прочитать больше в документации Cython .

Ответ 4

Возможно, ваш ответ находится в Cython:

"Cython поддерживает собственный parallelism через модуль cython.parallel. Чтобы использовать этот вид parallelism, должен быть выпущен GIL (см. раздел" Освобождение GIL "). В настоящее время он поддерживает OpenMP, но позже на большее количество бэкэндов может быть поддерживается". Документация Cython

Ответ 5

Cython

Cython поддерживает OpenMP: с Cython OpenMP можно добавить с помощью оператора prange (parallel range) и добавления директивы компилятора -fopenmp в setup.py.

При работе в строге prange выполнение выполняется параллельно, потому что мы отключили блокировку глобального интерпретатора (GIL), используя with nogil:, чтобы указать блок, в котором отключен GIL.

Чтобы скомпилировать _cython_np.pyx_, мы должны изменить setup.py script, как показано ниже. Мы сообщим ему сообщить компилятору C использовать -fopenmp в качестве аргумента во время компиляции - включить OpenMP и связать его с библиотеками OpenMP. setup.py

С Cythons prange, мы можем выбирать разные подходы к планированию. Со статичным рабочим объемом распределяется равномерно по доступным ЦП. Однако, поскольку некоторые из ваших расчетных регионов являются дорогостоящими во времени, в то время как другие дешевы - если мы попросим Cython планировать рабочие куски одинаково с использованием статических по всем процессорам, то результаты для некоторых регионов будут выполняться быстрее других, и тогда эти потоки будут сидеть без дела. Как динамические, так и управляемые параметры расписания пытаются смягчить эту проблему, распределяя работу в небольших кусках динамически во время выполнения, так что ЦП распределяются более равномерно, когда время вычисления рабочей нагрузки является переменной. Таким образом, для вашего кода правильный выбор будет зависеть от характера вашей рабочей нагрузки.

Numba

Премиум-версия Numbas, NumbaPro, имеет экспериментальную поддержку оператора рассылки prange для работы с OpenMP.

Pythran

Pythran (компилятор Python-to-С++ для подмножества Python) может использовать возможности векторизации и возможности параллелизации OpenMP, хотя он работает только с использованием Python 2.7. Вы указываете параллельные разделы, используя директивы pragma omp (очень похоже на поддержку Cythons OpenMP, описанную выше), например:

pragma omp

PyPy

Компилятор JIT Python PyPy поддерживает модуль многопроцессорности (см. ниже) и имеет проект PyPy-STM " специальную версию PyPy для разработки, которая может запускать несколько независимых головок, зависящих от процессора, в одном и том же процессе параллельно.

Боковое примечание: многопроцессорная обработка

OpenMP - это низкоуровневый интерфейс для нескольких ядер. Вы можете захотеть взглянуть на multiprocessing. Модуль multiprocessing работает на более высоком уровне, разделяя структуры данных Python, в то время как OpenMP работает с примитивными объектами C (например, целыми числами и поплавками), как только вы скомпилировали C. Это имеет смысл только для используйте OpenMP, если вы компилируете свой код; если вы не компилируете (например, если вы используете эффективный код numpy и хотите работать на многих ядрах), то придерживаться с помощью multiprocessing, вероятно, правильный подход.

Ответ 6

http://archive.euroscipy.org/talk/6857" представляет возможности Cython OpenMP, фокусирующиеся на параллельных циклах над массивами NumPy. Примеры исходного кода демонстрируют, как использовать OpenMP из Python. для параллельных алгоритмов с OpenMP показывают, какие ускорения могут быть достигнуты для разных размеров данных по сравнению с другими стратегиями распараллеливания.

import numpy
import cython
from cython cimport parallel

@cython.boundscheck(False)
@cython.wraparound(False)
def func(object[double, ndim=2] buf1 not None,
        object[double, ndim=2] buf2 not None,
        object[double, ndim=2] output=None,
        int num_threads=2):
    cdef unsigned int x, y, inner, outer
    if buf1.shape != buf2.shape:
        raise TypeError('Arrays have different shapes: %s, %s' % (buf1.shape,
            buf2.shape))
    if output is None:
        output = numpy.empty_like(buf1)
    outer = buf1.shape[0]
    inner = buf1.shape[1]
    with nogil, cython.boundscheck(False), cython.wraparound(False):
        for x in parallel.prange(outer, schedule='static',
                num_threads=num_threads):
            for y in xrange(inner):
                output[x, y] = ((buf1[x, y] + buf2[x, y]) * 2 +
                    buf1[x, y] * buf2[x, y])
return output