我正在尝试将openMP并行化添加到相当大的项目中,并且我发现openMP在并行块之外执行了太多同步 。
这个同步是针对所有变量完成的,甚至是并行块中没有使用的变量,并且不仅在进入块之前连续完成。
我做了一个证明这一点的例子:
#include <cmath>
int main()
{
double dummy1 = 1.234;
int const size = 1000000;
int const size1 = 2500;
int const size2 = 500;
for(unsigned int i=0; i<size; ++i){
//for (unsigned int j=0; j<size1; j++){
// dummy1 = pow(dummy1/2 + 1, 1.5);
//}
#pragma omp parallel for
for (unsigned int j=0; j<size2; j++){
double dummy2 = 2.345;
dummy2 = pow(dummy2/2 + 1, 1.5);
}
}
}
如果我运行此代码(使用for循环注释),运行时为6.75秒,并行化,30.6秒没有。大。
但是如果我取消注释for循环并再次运行它,过度同步就会启动,我得到67.9s的并行化结果和73s没有。如果我增加size1,我甚至可以通过并行化获得比没有它更慢的结果。
有没有办法禁用此同步并仅在第二个循环之前强制它?或者其他任何方式如何提高速度?
请注意,外部并非第一个for循环都在实例中可并行化。外部实际上是一个ODE求解器,第一个内部更新内部值的载荷。
我正在使用gcc(SUSE Linux)4.8.5
感谢您的回答。
答案 0 :(得分:0)
最后,我的问题的解决方案是指定线程数=处理器核心数。似乎超线程导致了这些问题。所以使用(我的处理器有4个真核)
#pragma omp parallel for num_threads(4)
我得到的时间是8.7秒而没有第一个for循环和51.9s。仍然有大约1.2s的开销,但这是可以接受的。使用默认(8个线程)
#pragma omp parallel for
时间分别为6.65s和68s。这里的开销大约是19s。
因此,如果不存在其他代码,则超线程会有所帮助,但是当它出现时,使用它可能并不总是一个好主意。