科学计算领域的大多数人在共享内存并行化方面都使用 OpenMP 作为准标准。
是否有任何理由(除了可读性之外)在 pthreads 上使用 OpenMP?后者似乎更基本,我怀疑它可以更快、更容易优化。
它基本上可以归结为您想要对并行化进行何种程度的控制。如果您只想添加一些 #pragma 语句并很快获得代码的并行版本,那么 OpenMP 非常有用。如果您想使用 MIMD 编码或复杂的队列做真正有趣的事情,您仍然可以使用 OpenMP 完成所有这些工作,但在这种情况下使用线程可能更简单。 OpenMP 在可移植性方面也具有类似的优势,因为许多不同平台的编译器现在都支持它,就像 pthreads 一样。
所以你是绝对正确的 - 如果你需要对并行化进行微调控制,请使用 pthreads。如果您想以尽可能少的工作量进行并行化,请使用 OpenMP。
无论你决定走哪条路,祝你好运!
另一个原因:OpenMP 是基于任务的,Pthreads 是基于线程的。这意味着 OpenMP 将分配与内核数量相同数量的线程。所以您将获得可扩展解决方案。使用原始线程来完成这件事并不是一件容易的事。
第二种意见:OpenMP 提供了缩减功能:当您需要在线程中计算部分结果并将它们组合起来时。您只需使用一行代码即可实现它。但使用原始线程你应该做更多的工作。
想想您的需求并尝试了解:OpenMP 足以满足您的需求吗?您将节省大量时间。
OpenMP 需要一个支持它的编译器,并且可以使用编译指示。这样做的优点是,在没有 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 代码更易于扩展。您也可以将使用 OpenMP 编译的代码与使用 pthread 的代码混合在一起。
你的问题类似于“我应该编程C还是汇编”的问题,C是OpenMP,汇编是pthreads。
使用 pthreads,您可以实现更好的并行化,更好的意思是非常紧密地适应您的算法和硬件。但这将是一个很大的工作量。
使用 pthreads 也更容易生成并行性较差的代码。
是否有任何理由(除了可读性之外)在 pthreads 上使用 OpenMP?
迈克谈到了这一点:
OpenMP 在可移植性方面也具有类似的优势,因为现在许多不同平台的编译器都支持它,就像 pthreads
Crypto++ 是跨平台的,意味着可以在 Windows、Linux、OS X 和 BSD 上运行。它在操作成本较高的地方使用 OpenMP 提供线程支持,例如模幂和模乘(以及可以执行并发操作的地方)。
Windows 不支持 pthread,但现代 Windows 编译器支持 OpenMP。因此,如果您想要非 *nix 的可移植性,那么 OpenMP 通常是一个不错的选择。
正如迈克也指出的那样:
如果您只想添加一些 #pragma 语句并很快获得代码的并行版本,那么 OpenMP 非常有用。
下面是 Crypto++ 的示例,使用伯恩斯坦在 RSA 签名和 Rabin-Williams 签名中描述的调整根来预先计算 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);
}
}
这与迈克的观察相符——细粒度控制和同步并不是真正需要的。并行化用于加速执行,并且同步在源代码中是免费的。
如果 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 机器(单指令多数据)。
当您想要并行执行(完全不同的)任务时,例如在一个线程中读取数据并在另一个线程中与用户交互,则需要 Pthreads。
请参阅此页:
http://berenger.eu/blog/c-cpp-openmp-vs-pthread-openmp-or-posix-thread/