C++并行化库:OpenMP与Thread Building Blocks比较

53

我要改装我的自定义图形引擎,以利用多核CPU。更准确地说,我正在寻找一个可以将循环并行化的库。

在我看来,OpenMP和Intel的Thread Building Blocks都非常适合这项工作。而且,这两个库都受到Visual Studio的C++编译器和大多数其他流行编译器的支持。同时,这两个库似乎都非常容易使用。

那么,我应该选择哪一个呢?是否有人尝试过这两个库,并且可以给我一些使用任一库的优缺点?最后,您选择了哪个库来使用?

谢谢,

Adrian


类似问题:https://dev59.com/nHRC5IYBdhLWcg3wVvnL(我在我的问题中添加了对这个问题的引用。) - strager
7个回答

60

我没有广泛使用TBB,但我的印象是它们相互补充而不是竞争。TBB提供线程安全的容器和一些并行算法,而OpenMP更多地用于并行化现有代码的方式。

就个人经验而言,我发现将OpenMP轻松应用于现有代码中非常容易,只要你拥有可以并行运行的循环或一系列部分即可。然而,当你需要修改某些共享数据时,它对你帮助不大 - 此时TBB的并发容器可能正好是你想要的。

如果您只想并行化独立迭代(或可以相当容易地实现),那么我会选择OpenMP。如果您需要更多线程之间的交互,我认为TBB在这方面可能会提供更多。


2
现有代码的好处是很容易在这里和那里插入一些#pragma。但如果要插入TBB,则可能会更加困难(很大程度上取决于现有的代码风格)。 - Anonymous

27

来自英特尔软件博客的文章:比较Windows*线程、OpenMP*、Intel® Threading Building Blocks在并行编程中的应用

这也涉及到风格问题 - 对我来说,TBB非常类似于C++,而我不太喜欢OpenMP pragma(有点像C,如果必须使用C写,则会使用它)。

我还会考虑团队现有的知识和经验。学习新的库(特别是涉及到线程/并发性的时候)需要一些时间。我认为目前,OpenMP比TBB更广为人知和部署(但这只是我的观点)。

还有一个因素 - 但考虑到最常见的平台,可能不是一个问题 - 可移植性。但许可证可能是一个问题。

  • TBB包含了一些来自学术研究的好的研究成果,例如递归数据并行化方法
  • 还有一些关于缓存友好性的工作,例如这个例子
  • 英特尔博客上的讲座似乎非常有趣。

谢谢提供链接,但由于它托管在英特尔的网站上,我不会真正相信它能提供完全公正的意见。显然,他们撰写了这篇文章来推广使用自己的库。 - Adrian Grigore
2
是的,在第一行的某个地方忘记了表情符号 ;) - Anonymous

20

一般来说,我发现使用TBB需要对代码进行更耗时的修改,但有很高的回报;而OpenMP则可以快速获得中等回报。如果你正在从头开始创建一个新模块并考虑长期发展,请选择TBB。如果您希望获得小而即时的收益,请选择OpenMP。

此外,TBB和OpenMP不是彼此排斥的。


9
我曾经都使用过,我的总体印象是,如果你的算法相对容易并行化(例如循环大小相等,数据间没有太多依赖关系),OpenMP更容易使用,且非常好用。实际上,如果你发现可以使用OpenMP,那么它可能是更好的选择,只要你知道你的平台支持它。我没有使用过OpenMP的新任务结构,这些结构比原始的循环和区块选项更加通用。
TBB提供了更多的数据结构,但需要更多的前期工作。另外,它也许更擅长让你意识到竞态条件错误。我的意思是,在OpenMP中,通过未共享(或其他)应该共享的内容,可能很容易导致竞态条件。你只有在得到错误结果时才会看到这一点。我认为在TBB中出现这种情况的可能性稍微小一些。
总的来说,我个人更喜欢OpenMP,尤其是考虑到它的任务表达能力增强了。

3

是的,TBB更加友好于C++,而OpenMP更适合FORTRAN风格的C代码。OpenMP中的新任务功能非常有趣,同时C++0x中的Lambda和函数对象可能会使TBB更易于使用。


3
据我所知,TBB(有一个开源版本可用于GPLv2)更多地涉及C ++而不是C领域。现在很难找到关于C ++和通用OOP并行化的具体信息。大多数信息都是针对函数式编程,比如C(CUDA或OpenCL上也一样)。如果您需要C ++支持并行化,请选择TBB!

1
TBB现在采用Apache许可证... - Jeff Hammond

2
在Visual Studio 2008中,您可以添加以下行来并行化任何“for”循环。它甚至可以与多个嵌套的for循环一起使用。这里是一个例子:
#pragma omp parallel for private(i,j)
for (i=0; i<num_particles; i++)
{
  p[i].fitness = fitnessFunction(p[i].present);
  if (p[i].fitness > p[i].pbestFitness)
  { 
     p[i].pbestFitness = p[i].fitness;
     for (j=0; j<p[i].numVars; j++) p[i].pbest[j] = p[i].present[j];
  }
}  
gbest = pso_get_best(num_particles, p);

在我们添加了#pragma omp parallel之后,我的Core 2 Duo的两个核心都被充分利用,因此总CPU使用率从50%提高到了100%。


1
只是一条说明:嵌套循环只在编译器支持时才能正常工作。 - Nav
3
另外一点需要注意的是:你可以使用 omp parallel for 来并行化任何可并行化的 for 循环。例如,如果循环体包含类似于 p[j] = p[j] - p[j-1] 的代码,则不能使用 omp parallel for - chus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接