46

我将改造我的自定义图形引擎,以便它能够利用多核 CPU。更确切地说,我正在寻找一个库来并行化循环。

在我看来,OpenMP 和英特尔的线程构建块都非常适合这项工作。此外,Visual Studio 的 C++ 编译器和大多数其他流行的编译器都支持两者。这两个库似乎都非常易于使用。

那么,我应该选择哪一个呢?有没有人尝试过这两个库,并且可以给我一些使用这两个库的利弊?另外,你最终选择了与什么合作?

谢谢,

阿德里安

4

7 回答 7

56

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

就我个人而言,我发现 OpenMP 很容易放入现有代码中,您可以在其中有一个可并行化的循环或一堆可以并行运行的部分。但是,对于需要修改一些共享数据的情况,它对您没有帮助——TBB 的并发容器可能正是您想要的。

如果您想要的只是并行化迭代独立的循环(或者可以很容易地做到这一点),我会选择 OpenMP。如果您需要线程之间的更多交互,我认为 TBB 在这方面可能会提供更多。

于 2009-03-05T20:46:52.870 回答
26

来自英特尔的软件博客:比较 Windows* 线程、OpenMP*、英特尔® 线程构建块以进行并行编程

这也是风格的问题——对我来说,TBB 非常像 C++,而我不太喜欢 OpenMP 编译指示(有点 C 的味道,如果我必须用 C 编写,我会使用它)。

我也会考虑团队现有的知识和经验。学习一个新库(尤其是在线程/并发方面)确实需要一些时间。我认为目前,OpenMP 比 TBB 更广为人知和部署(但这只是我的观点)。

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

  • TBB 融合了一些源自学术研究的优秀研究,例如递归数据并行方法
  • 有一些关于缓存友好性的工作,例如.
  • 英特尔博客的讲座似乎很有趣。
于 2009-03-05T15:41:12.340 回答
19

总的来说,我发现使用 TBB 需要对代码库进行更耗时的更改并获得高回报,而 OpenMP 提供快速但适中的回报。如果您正在从头开始关注新模块并考虑长期考虑,请选择 TBB。如果您想要小而直接的收益,请选择 OpenMP。

此外,TBB 和 OpenMP 并不相互排斥。

于 2009-03-06T10:51:20.810 回答
8

我实际上都使用过这两种方法,我的总体印象是,如果您的算法相当容易实现并行(例如,大小均匀的循环,没有太多的数据相互依赖性),OpenMP 更容易,而且很好用。事实上,如果您发现自己可以使用 OpenMP,如果您知道您的平台会支持它,这可能是更好的选择。我没有使用过 OpenMP 的新任务结构,它比原来的循环和部分选项更通用。

TBB 预先为您提供了更多的数据结构,但肯定需要更多的预先准备。另外,它可能会更好地让您了解竞争条件错误。我的意思是,在 OpenMP 中通过不共享(或其他)应该共享的东西来启用竞争条件是相当容易的。只有当你得到不好的结果时,你才会看到这一点。我认为 TBB 不太可能发生这种情况。

总的来说,我个人偏爱 OpenMP,尤其是考虑到它在任务方面的表现力更强。

于 2009-04-28T11:54:25.210 回答
2

据我所知,TBB(有一个可用的 GPLv2 下的开源版本)更关注 C++,然后是 C 领域。这些时候很难找到 C++ 和一般的 OOP 并行化特定信息。大多数地址功能性的东西,如 c(在 CUDA 或 OpenCL 上相同)。如果您需要 C++ 支持并行化,请选择 TBB!

于 2012-01-10T07:14:45.103 回答
2

是的,TBB 对 C++ 更友好,而鉴于其设计,OpenMP 更适合 FORTRAN 风格的 C 代码。OpenMP 中的新任务功能看起来很有趣,同时 C++0x 中的 Lambda 和函数对象可能会使 TBB 更易于使用。

于 2013-01-24T06:51:44.780 回答
1

在 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%。

于 2010-06-28T17:43:23.547 回答