2016-05-17 44 views
0

我想学习OpenMP并行化我的代码的一部分,我试图找出为什么它不是更快时,使用2个线程而不是1.这里是的代码的最小工作示例:没有得到预期的加速使用OpenMP的非平凡的计算

#include <iostream> 
#include <omp.h> 

using namespace std; 

class My_class 
{ 
    public : 

     // Constructor 
     My_class(int nuIterations) 
      : prVar_(0), 
       nuIters_(nuIterations) 
     {} // Empty 

     // Do something expensive involving the class' private vars 
     void do_calculations() 
     { 
      for (int i=0;i<nuIters_;++i){ 
       prVar_=prVar_+i+2*i+3*i+4*i-5*i-4*i; 
      } 
     } 

     // Retrieve result 
     double getResult() 
     { 
      return prVar_; 
     } 

    private: 

     double prVar_; 
     int nuIters_; 

}; 

int main() 
{ 
    // Initialize one object for every thread 
    My_class *test_object1, *test_object2; 
    test_object1 = new My_class(1000000000); 
    test_object2 = new My_class(500000000); 

    // Set number of threads (use one line at a time) 
    omp_set_num_threads(1); // One thread executes in 11.5 real seconds 
    //omp_set_num_threads(2); // Two threads execute in 13.2 real seconds 
    double start = omp_get_wtime(); // Start timer 
#pragma omp parallel sections // Do calculations in parallel 
    { 
#pragma omp section 
     { 
      test_object1->do_calculations(); 
     } 
#pragma omp section 
     { 
      test_object2->do_calculations(); 
     } 
    }// End of parallel sections 
    // Print results 
    double end = omp_get_wtime(); 
    cout<<"Res 1 : "<<test_object1->getResult()<<endl; 
    cout<<"Res 2 : "<<test_object2->getResult()<<endl; 
    cout<<"Time : "<<end-start<<endl; 

    return 0; 
} 

编译和运行这个使用g++ myomp.cpp -O0 -std=c++11 -fopenmp给出了1个2个线程以下执行时间:

  1. 1螺纹:11.5秒
  2. 2线程:13.2秒

有什么方法可以加速2线程? 我在4核英特尔i7-4600U和Ubuntu上运行此操作系统。

编辑:改变了大多数帖子,使其遵循指导。

+2

您必须以[mcve]加上您的硬件规格的形式给我们提供更多信息,否则答案只是猜测。猜测包括:写入共享缓存行,进行内存绑定,隐式同步,使用您不知道的共享资源或其组合。 – Zulan

+0

感谢您的评论,我会尝试制定一个合适的示例并编辑帖子! – nikaza

+0

完成,希望它现在有意义! – nikaza

回答

2

有两只方面的影响在这里:

  1. 缓存行争:您必须在动态内存分配了两个非常小的物体。如果它们结束于同一个缓存行(通常是64字节),那么想要更新的线程将同时竞争1级缓存,因为它们需要独占(写入)访问权限。您应该已经随机观察到了这种情况:有时,根据内存位置,它显着更快/更慢。尝试打印指针地址并将它们除以64.要解决此问题,您需要pad/align the memory

  2. 您有巨大的负载不平衡。一项任务仅仅是计算两倍的工作量,因此即使在理想条件下,也只能达到1.5的加速。

+0

我向私有变量添加了一个1000元素的双精度数组(试图将两个对象分隔得比一个高速缓存线更远),它根本没有任何区别... –

+0

“没有区别”是什么意思?如果您已经获得了1.5倍加速,那么您可能不会受到1)的影响。 – Zulan

+0

同意。我试图说,似乎没有任何缓存线争用,但我说得很糟糕。我也试着让这两种工作负载大小相同,加速比例确实是2倍。所以,至少在我的机器上,它似乎几乎完全是你的第二个效果。有我的投票:-) –