Есть ли какая-либо причина (кроме читабельности) использовать OpenMP поверх pthreads?
Майк вроде бы коснулся этого:
OpenMP также имеет аналогичные преимущества в переносимости, поскольку многие компиляторы для разных платформ поддерживают его сейчас, как и в случае с pthreads
Crypto ++ является кроссплатформенным, то есть работает в Windows, Linux, OS X и BSD. Он использует OpenMP для поддержки потоков в тех местах, где операция может быть дорогой, например, модульное возведение в степень и модульное умножение (и где может выполняться параллельная операция).
Windows не поддерживает pthreads, но современные компиляторы Windows поддерживают OpenMP. Так что, если вы хотите переносимости с номерами, отличными от * nix, то OpenMP часто является хорошим выбором.
И как Майк также отметил:
OpenMP отлично подходит, если все, что вы хотите сделать, это добавить несколько операторов #pragma и довольно быстро получить параллельную версию вашего кода.
Ниже приведен пример предварительного вычисления Crypto ++ некоторых значений, используемых в сигнатурах Рабина-Вильямса, с использованием Tweaked Roots, как описано Бернштейном в сигнатурах 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);