并行使用多个OMP并行部分 - >绩效问题?

时间:2017-09-08 17:49:25

标签: c++ openmp

我试图了解使用OpenMP(在Windows上)的一个C ++应用程序的巨大性能问题。申请结构如下:

我有一个算法,它基本上由一些使用OpenMP并行化的for循环组成:

void algorithm()
{
  #pragma omp parallel for numThreads(12)
  for (int i=0; ...)
  {
     // do some heavy computation (pure memory and CPU work, no I/O, no waiting)
  }

  // ... some more for-loops of this kind
}

应用程序从n个不同的线程并行执行此算法n次:

std::thread t1(algorithm);
std::thread t2(algorithm);
//...
std::thread tn(algorithm);

t1.join();
t2.join();
//...
tn.join();
// end of application

现在,问题如下:

  • 当我在我的系统上使用n=1(只有一次调用algorithm())运行具有32个物理CPU内核(没有超线程)的应用程序时,需要大约5秒并将CPU加载到大约30%正如预期的那样(假设我告诉OpenMP只使用12个线程)。
  • 当我使用n=2运行时,CPU负载上升到大约60%,但应用程序需要大约10秒钟。 这意味着几乎不可能并行运行多个算法实例

当然,仅此一点可能有很多原因(包括缓存未命中,RAM带宽限制等),但有一件事让我感到震惊:

  • 如果我在两个并行进程中运行我的应用程序两次,每个进程都有n=1,两个进程在大约5秒后完成,意味着我能够并行运行两个算法,因为他们生活在不同的过程中

这似乎排除了此性能瓶颈的许多可能原因。事实上,即使在分析代码之后,我也无法理解其原因。我怀疑的是,不同并行部分之间的OpenMP可能存在一些过度同步。

有没有人见过这样的效果?或者任何人都可以给我建议如何处理这个问题?我真的已经达到了我所能想到的一切,但到目前为止没有任何成功。我很感激能得到的任何帮助!

非常感谢,

PS:

  • 我一直在使用MS Visual Studio 2015和Intel 2017的编译器 - 两者都显示出基本相同的效果。
  • 我有一个非常简单的复制器来显示这个问题,如果需要我可以提供。它实际上不仅仅是上述内容,只是在for-loops中添加了一些实际工作。

0 个答案:

没有答案