并行化:pthreads还是OpenMP?

科学计算中的大多数人在共享内存并行化方面使用OpenMP作为准标准。

有没有任何理由(除了可读性)通过pthreads使用OpenMP? 后者似乎更基本,我怀疑它可以更快,更容易优化。

它基本上归结为你想要的平行化控制水平。 如果您想要做的只是添加一些#pragma语句,并且能够快速获得并行版本的代码,则OpenMP非常棒。 如果你想用MIMD编码或者复杂排队做一些有趣的事情,你仍然可以用OpenMP来完成所有的工作,但是在这种情况下使用线程可能更直接。 OpenMP在可移植性方面也具有相似的优势,因为不同平台的许多编译器现在都支持它,就像pthread一样。

所以你是绝对正确的 – 如果你需要对你的并行化进行微调,使用pthreads。 如果要尽可能less地进行并行操作,请使用OpenMP。

无论你决定去哪里,祝你好运!

另一个原因是:OpenMP是基于任务的,Pthreads是基于线程的。 这意味着OpenMP将分配与内核数相同数量的线程。 所以你会得到可扩展的解决scheme。 使用原始线程并不是那么容易的任务。

第二种观点:OpenMP提供了简化function:当你需要在线程中计算部分结果并合并它们。 你可以使用单行代码来实现它。 但是使用原始线程你应该做更多的工作。

只是想想你的要求,并试图了解:OpenMP足够吗? 你会节省很多时间。

OpenMP需要一个支持它的编译器,并使用pragmas。 这样做的好处是,在没有OpenMP支持(例如PCC或Clang / LLVM)编译时,代码仍然可以编译。 另外,请看看Charles Leiserson写关于DIYmultithreading的内容 。

Pthreads是用于库的POSIX标准( IEEE POSIX 1003.1c ),而OpenMP规范将在编译器上实现; 也就是说,有许多pthread实现(例如OpenBSD的rthreads,NPTL)和一些支持OpenMP的编译器(例如带有-fopenmp标志的GCC,MSVC ++ 2008)。

只有当多个处理器可用时,并且只有当代码针对可用处理器的数量进行了优化时,Pthread才能有效地进行并行化。 因此OpenMP代码更容易扩展。 您也可以将使用OpenMP编译的代码与使用pthread的代码混合在一起。

你的问题类似于“我应该编程C还是程序集”,C是OpenMP,程序集是pthread。

用pthreads你可以做更好的并行化,更好的意义非常紧密地适应你的algorithm和硬件。 这将是很多工作,虽然。

使用pthreads,生成不良并行代码也更容易。

当您需要并行执行相同的任务 (即多个数据)时,OpenMP非常适用,这是一种SIMD机器(单指令多数据)。

当需要并行执行(完全不同的)任务时,需要Pthreads,例如,读取一个线程中的数据并在另一个线程中与用户交互。

看到这个页面:

http://berenger.eu/blog/c-cpp-openmp-vs-pthread-openmp-or-posix-thread/

除了可读性,是否有任何理由通过pthreads使用OpenMP?

麦克有点触动了这个:

OpenMP在可移植性方面也具有相似的优势,因为不同平台的许多编译器现在都支持它,就像pthread一样

Crypto ++是跨平台的,意味着在Windows,Linux,OS X和BSD上运行。 它使用OpenMP进行线程支持,这些线程支持的操作可能很昂贵,比如模幂运算和模乘(可以执行并发操作)。

Windows不支持pthread,但现代Windows编译器确实支持OpenMP。 所以如果你想要移植到非nix的话,OpenMP通常是一个不错的select。


正如迈克所指出的那样:

如果你想要做的只是添加一些#pragma语句,并且相当快速地获得一个并行版本的代码,那么OpenMP是非常棒的。

下面是Crypto ++在RSA签名和Rabin-Williams签名中预先计算Rabin-Williams签名中使用的一些值的示例,这些值使用了伯恩斯坦(Bernstein)描述的Tweaked Roots:

 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); } } 

它符合Mike的观察 – 细粒度控制和同步并不是真的需要。 并行化被用来加速执行,并且源代码中没有任何代价。

如果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);