在科学计算中,大多数人在共享内存并行化方面使用OpenMP作为准标准。
除了可读性之外,是否有任何理由选择OpenMP而不是pthreads?后者似乎更基础,我怀疑它可能更快且更容易优化。
在科学计算中,大多数人在共享内存并行化方面使用OpenMP作为准标准。
除了可读性之外,是否有任何理由选择OpenMP而不是pthreads?后者似乎更基础,我怀疑它可能更快且更容易优化。
这基本上取决于你想要多大程度地控制你的并行化。如果你只想添加一些#pragma语句并很快地得到代码的并行版本,那么OpenMP就非常适合。如果你想用MIMD编码或复杂的队列做一些真正有趣的事情,你仍然可以使用OpenMP来完成所有这些,但在这种情况下使用线程可能更加简单。就像pthread一样,现在许多不同平台的编译器都支持OpenMP,并具有类似的可移植性优势。
所以你是完全正确的——如果你需要对并行化进行精细调整,使用pthread。如果你希望尽可能少地工作并实现并行化,那么使用OpenMP。
无论你选择哪种方式,祝你好运!
另一个原因是:OpenMP 是基于任务的,而 Pthreads 是基于线程的。这意味着 OpenMP 将分配与核心数量相同的线程数。因此,您将获得可扩展的解决方案。如果使用原始线程,则很难完成这项任务。
第二个观点:OpenMP 提供了归约功能:当您需要在线程中计算部分结果并将它们组合起来时,您只需要使用一行代码即可实现。但是,如果使用原始线程,则需要做更多的工作。
考虑一下您的需求并尝试理解:OpenMP 是否足够适合您?您将节省大量时间。
OpenMP需要支持它的编译器,并使用pragma。这样做的优点是,即使没有OpenMP支持(例如PCC或Clang/LLVM),代码仍将编译。此外,请参阅Charles Leiserson关于DIY多线程的文章。
Pthreads是POSIX标准(IEEE POSIX 1003.1c)库,而OpenMP规范则需要在编译器上实现;也就是说,有各种pthread实现(例如OpenBSD rthreads、NPTL),以及许多支持OpenMP的编译器(例如带有-fopenmp标志的GCC、MSVC++2008)。
只有在有多个处理器可用且代码已经针对可用处理器数量进行了优化时,Pthreads才能有效地进行并行化。因此,使用OpenMP编写的代码更易于扩展。您还可以将与使用pthread的代码混合编译。
pthread_create()
和pragma omp parallel {}
所需的内容? - Jeff Hammond正如Mike所指出的:
如果你只想添加一些#pragma语句并很快地创建代码的并行版本,那么OpenMP非常好。
以下是Crypto++使用Bernstein在RSA signatures and Rabin-Williams signatures...中描述的Tweaked Roots预计算用于Rabin-Williams签名的一些值的示例:
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);
当您需要并行执行相同任务(即在多个数据上),一种SIMD机器(单指令多数据)时,OpenMP是理想的选择。
当您想要并行执行非常不同的任务时,例如在一个线程中读取数据,在另一个线程中与用户交互时,需要使用Pthreads。
请参阅此页面:
http://berenger.eu/blog/c-cpp-openmp-vs-pthread-openmp-or-posix-thread/