44

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

是否有任何理由(除了可读性)在 pthreads 上使用 OpenMP?后者似乎更基本,我怀疑它可能更快更容易优化。

4

6 回答 6

42

它基本上归结为您希望对并行化进行何种级别的控制。如果您想要做的只是添加一些#pragma 语句并很快拥有代码的并行版本,那么 OpenMP 非常棒。如果你想用 MIMD 编码或复杂的队列来做真正有趣的事情,你仍然可以用 OpenMP 来做这一切,但在这种情况下使用线程可能要简单得多。OpenMP 在可移植性方面也有类似的优势,因为许多不同平台的编译器现在都支持它,就像 pthreads 一样。

所以你是绝对正确的——如果你需要对并行化进行微调控制,请使用 pthreads。如果您想以尽可能少的工作进行并行化,请使用 OpenMP。

不管你决定走哪条路,祝你好运!

于 2009-06-01T16:10:52.567 回答
23

另一个原因:OpenMP 是基于任务的,Pthreads 是基于线程的。这意味着 OpenMP 将分配与内核数相同的线程数。因此,您将获得可扩展的解决方案。使用原始线程来做到这一点并不是一件容易的事。

第二种意见:OpenMP 提供缩减功能:当您需要在线程中计算部分结果并将它们组合时。您可以仅使用单行代码来实现它。但是使用原始线程你应该做更多的工作。

想想您的需求并尝试理解:OpenMP 是否足以满足您的需求?您将节省大量时间。

于 2009-06-20T14:24:46.607 回答
8

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 的代码。

于 2009-12-29T20:41:15.093 回答
3

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

使用 pthreads,您可以进行更好的并行化,更好地适应您的算法和硬件。不过,这将是很多工作。

使用 pthreads 也更容易生成并行性较差的代码。

于 2012-07-22T11:56:26.197 回答
1

是否有任何理由(除了可读性)在 pthreads 上使用 OpenMP?

迈克有点提到这一点:

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

Crypto++是跨平台的,意味着可以在 Windows、Linux、OS X 和 BSD 上运行。它使用 OpenMP 在操作可能很昂贵的地方提供线程支持,例如模幂和模乘(以及可以执行并发操作的地方)。

Windows 不支持 pthread,但现代 Windows 编译器确实支持 OpenMP。因此,如果您想要移植到非 *nix 的,那么 OpenMP 通常是一个不错的选择。


正如迈克还指出的那样:

如果您想要做的只是添加一些#pragma 语句并很快拥有代码的并行版本,那么 OpenMP 非常棒。

下面是 Crypto++ 使用 Tweaked Roots 预计算 Rabin-Williams 签名中使用的一些值的示例,如 Bernstein 在RSA 签名和 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);
于 2015-06-13T22:32:24.507 回答
0

当您需要并行执行相同的任务(即在多个数据上)时,OpenMP 是理想的选择,它是一种 SIMD 机器(单指令多数据)。

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

请参阅此页面:

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

于 2013-08-02T10:37:58.710 回答