openmp等待内部for

我有一段代码,我想要并行化,并且openmp程序比串行版本慢很多,所以我的实现有什么问题? 这是该程序的代码

#include <iostream>
#include <gsl/gsl_math.h>
#include "Chain.h"
using namespace std;

int main(){
  int const N=1000;
  int timeSteps=100;
  double delta=0.0001;
  double qq[N];
  Chain ch(N);
  ch.initCond();
  for (int t=0; t<timeSteps; t++){
    ch.changeQ(delta*t);
    ch.calMag_i();
    ch.calForce001();
  }
  ch.printSomething();
}

Chain.h是

class Chain{
  public:
    int N;
    double *q;
    double *mx;
    double *my;
    double *force;

    Chain(int const Np);
    void initCond();
    void changeQ(double delta);
    void calMag_i();
    void calForce001();
};

Chain.cpp是

Chain::Chain(int const Np){
  this->N     = Np;
  this->q     = new double[Np];
  this->mx    = new double[Np];
  this->my    = new double[Np];
  this->force = new double[Np];  
}

void Chain::initCond(){
  for (int i=0; i<N; i++){
    q[i]     = 0.0;
    force[i] = 0.0;
  }
}

void Chain::changeQ(double delta){
  int i=0;
  #pragma omp parallel
  {
    #pragma omp for
    for (int i=0; i<N; i++){
      q[i] = q[i] + delta*i + 1.0*i/N;
    }
  }
}

void Chain::calMag_i(){
  int i =0;
  #pragma omp parallel
  {
    #pragma omp for
    for (i=0; i<N; i++){
      mx[i] = cos(q[i]);
      my[i] = sin(q[i]);
    }
  }
}

void Chain::calForce001(){
  int i;
  int j;
  double fij =0.0;
  double start_time = omp_get_wtime();
  #pragma omp parallel
  {
    #pragma omp for private(j, fij)
    for (i=0; i<N; i++){
      force[i] = 0.0;
      for (j=0; j<i; j++){
        fij = my[i]*mx[j] - mx[i]*my[j];
        #pragma omp critical
        {
          force[i] +=  fij;
          force[j] += -fij;
        }
      }
    }
  }
  double time = omp_get_wtime() - start_time;
  cout <<"time = " << time <<endl;
}

所以方法changeQ()和calMag_i()实际上比串行代码更快,但我的问题是calForce001() 。 执行时间是:

  • 与openMP 3.939s
  • 没有openMP 0.217s
  • 现在,显然我做错了什么,或者代码无法并行化。 请有用的帮助。 提前致谢。 卡洛斯

    编辑:为了澄清问题我添加的功能omp_get_wtime()来计算所述函数calForce001(执行时间和次为一个执行是

  • 与omp:0.0376656
  • 不含omp:0.00196766
  • 所以用omp方法慢20倍

    否则,我还计算calMag_i()方法的时间

  • 与omp:3.3845e-05
  • 没有omp:9.9516e-05
  • 对于这种方法,omp 速度要快3倍

    我希望这可以确认延迟问题出现在calForce001()方法中。


    有三个原因让你不能从任何加速中受益。

  • 你的代码中有#pragma omp parallel 。 这个编译指南的作用是启动“线程团队”。 在该区块结束时,该团队解散。 这是非常昂贵的。 删除这些文件并使用#pragma omp parallel for代替#pragma omp for会在第一次遇到时启动团队,并在每个块后将其设置为休眠状态。 这使我的应用程序速度提高了4倍。
  • 你使用#pragma omp critical 。 在大多数平台上,这将强制使用互斥锁 - 这是一个非常激烈的争论,因为所有线程都想同时写入该变量。 所以,不要在这里使用关键部分。 你可以使用原子更新,但在这种情况下,这不会有太大的区别 - 参见第三项。 只是删除关键部分提高了另外3倍的速度。
  • 并行性只有在有实际工作负载时才有意义。 你的所有代码都太小而不能从并行中受益。 只需要太少的工作量就可以赢回开始/唤醒/销毁线程的时间。 如果你的工作量是十倍,那么一些parallel for陈述就会有意义。 但特别是Chain::calForce001()永远不值得它,如果你必须做原子更新。
  • 关于编程风格:你用C ++编程。 请尽可能使用局部范围变量 - 例如Chain::calForce001() ,在内部循环中使用本地double fij 。 这使您不必编写private子句。 编译器足够聪明来优化。 正确的作用域允许更好的优化。

    链接地址: http://www.djcxy.com/p/79239.html

    上一篇: openmp latency for inside for

    下一篇: c++