Распараллеливание:pthreads или OpenMP?
-
06-09-2019 - |
Вопрос
Большинство специалистов в области научных вычислений используют OpenMP как квазистандарт, когда дело доходит до распараллеливания общей памяти.
Есть ли какая-либо причина (кроме удобства чтения) использовать OpenMP поверх pthreads?Последнее кажется более простым, и я подозреваю, что его можно было бы оптимизировать быстрее и проще.
Решение
В основном это сводится к тому, какой уровень контроля вы хотите получить над своей распараллеливанием.OpenMP отлично подходит, если все, что вы хотите сделать, это добавить несколько операторов #pragma и довольно быстро создать параллельную версию вашего кода.Если вы хотите делать действительно интересные вещи с помощью MIMD-кодирования или сложной организации очередей, вы все равно можете делать все это с помощью OpenMP, но, вероятно, в этом случае намного проще использовать потоковую обработку.OpenMP также обладает аналогичными преимуществами в переносимости, поскольку сейчас его поддерживают многие компиляторы для разных платформ, как и в случае с pthreads.
Так что вы абсолютно правы - если вам нужен точно настроенный контроль над вашим распараллеливанием, используйте pthreads .Если вы хотите распараллелить процесс с минимальными затратами, используйте OpenMP.
Каким бы путем вы ни решили пойти, удачи!
Другие советы
Еще одна причина:OpenMP основан на задачах, Pthreads - на потоках.Это означает, что OpenMP выделит такое же количество потоков, как и количество ядер.Таким образом, вы получите масштабируемый решение.Сделать это с помощью необработанных потоков не так-то просто.
Второе мнение:OpenMP предоставляет функции сокращения:когда вам нужно вычислить частичные результаты в потоках и объединить их.Вы можете реализовать это просто с помощью одной строки кода.Но используя необработанные потоки, вы должны выполнить больше работы.
Просто подумайте о своих требованиях и попытайтесь понять:достаточно ли для вас OpenMP?Вы сэкономите уйму времени.
OpenMP требует компилятора, который поддерживает его и работает с прагмами.Преимущество этого заключается в том, что при компиляции без поддержки OpenMP (например,PCC или Clang / LLVM на данный момент), код все равно будет компилироваться.Кроме того, взгляните на что писал Чарльз Лейзерсон о многопоточности своими руками.
Pthreads - это стандарт POSIX (IEEE POSIX 1003.1c) для библиотек, в то время как Спецификации OpenMP должны быть реализованы на компиляторах;при этом существует множество реализаций pthread (напримерOpenBSD rthreads, NPTL) и ряд компиляторов, поддерживающих OpenMP (напримерGCC с флагом -fopenmp, MSVC++ 2008).
Pthreads эффективны для распараллеливания только при наличии нескольких процессоров и только тогда, когда код оптимизирован под количество доступных процессоров.В результате код для OpenMP становится более легко масштабируемым.Вы также можете смешивать код, который компилируется с помощью OpenMP, с кодом, использующим pthreads.
Ваш вопрос похож на вопрос "Должен ли я программировать C или assembly", где C - это OpenMP, а assembly - pthreads.
С помощью pthreads вы можете добиться гораздо лучшего распараллеливания, что означает более точную настройку под ваш алгоритм и аппаратное обеспечение.Однако это будет большая работа.
С помощью pthreads также намного проще создавать плохо распараллеленный код.
Есть ли какая-либо причина (кроме удобства чтения) использовать OpenMP поверх pthreads?
Майк вроде как коснулся этого:
OpenMP также обладает аналогичными преимуществами в переносимости, поскольку многие компиляторы для разных платформ поддерживают его сейчас, как и в случае с pthreads
Криптография++ является кроссплатформенным, то есть работает на Windows, Linux, OS X и BSD.Он использует OpenMP для поддержки потоков в местах, где операция может быть дорогостоящей, таких как модульное возведение в степень и модульное умножение (и где могут выполняться параллельные операции).
Windows не поддерживает pthreads, но современные компиляторы Windows поддерживают OpenMP.Так что, если вы хотите переносимости на устройства, отличные от * nix, то OpenMP часто является хорошим выбором.
И , как также отметил Майк:
OpenMP отлично подходит, если все, что вы хотите сделать, это добавить несколько операторов #pragma и довольно быстро создать параллельную версию вашего кода.
Ниже приведен пример предварительного вычисления Crypto ++ некоторых значений, используемых в сигнатурах Рабина-Уильямса, с использованием измененных корней, как описано Бернштейном в Подписи RSA и подписи Рабина-Уильямса...:
void InvertibleRWFunction::Precompute(unsigned int /*unused*/)
{
ModularArithmetic modp(m_p), modq(m_q);
#pragma omp parallel sections
{
#pragma omp section
m_pre_2_9p = modp.Exponentiate(2, (9 * m_p - 11)/8);
#pragma omp section
m_pre_2_3q = modq.Exponentiate(2, (3 * m_q - 5)/8);
#pragma omp section
m_pre_q_p = modp.Exponentiate(m_q, m_p - 2);
}
}
Это согласуется с наблюдением Майка - точный контроль зернистости и синхронизация на самом деле не были нужны.Распараллеливание использовалось для ускорения выполнения, а синхронизация в исходном коде осуществлялась бесплатно.
И если OpenMP является нет доступный, код сводится к:
m_pre_2_9p = modp.Exponentiate(2, (9 * m_p - 11)/8);
m_pre_2_3q = modq.Exponentiate(2, (3 * m_q - 5)/8);
m_pre_q_p = modp.Exponentiate(m_q, m_p - 2);
OpenMP идеально подходит, когда вам нужно выполнить та же задача параллельно (то есть на нескольких данных) работает своего рода SIMD-машина (single-instruction multiple-data).
Pthreads необходим, когда вы хотите выполнять (совершенно разные) задачи параллельно, такие как, например, чтение данных в одном потоке и взаимодействие с пользователем в другом потоке.
Смотрите эту страницу:
http://berenger.eu/blog/c-cpp-openmp-vs-pthread-openmp-or-posix-thread/