Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 并行共轭梯度失败:线程越多,成本越高_Multithreading_Gcc_Openmp_Eigen_Linear Equation - Fatal编程技术网

Multithreading 并行共轭梯度失败:线程越多,成本越高

Multithreading 并行共轭梯度失败:线程越多,成本越高,multithreading,gcc,openmp,eigen,linear-equation,Multithreading,Gcc,Openmp,Eigen,Linear Equation,我想在Egen 3.3.7()中使用并行共轭梯度来求解Ax=b,但它表明线程越多,计算成本越高。 我在此测试代码,并将矩阵维数从90000更改为9000000。下面是代码(我将文件命名为test cg parallel.cpp): 谁能给我一些建议吗?非常感谢。你测量时间的方法不正确时钟似乎测量的是并行时间,而不是墙上的时钟时间。更喜欢使用OpenMP OMPGETGETWWTIME方法,或者甚至C++ STD::实际的挂钟时间随着线程数的增加而略微减少。然而,请注意,在这种情况下,本征尺度很

我想在Egen 3.3.7()中使用并行共轭梯度来求解Ax=b,但它表明线程越多,计算成本越高。 我在此测试代码,并将矩阵维数从90000更改为9000000。下面是代码(我将文件命名为test cg parallel.cpp):


谁能给我一些建议吗?非常感谢。

你测量时间的方法不正确<代码>时钟似乎测量的是并行时间,而不是墙上的时钟时间。更喜欢使用OpenMP OMPGETGETWWTIME方法,或者甚至C++ <代码> STD::实际的挂钟时间随着线程数的增加而略微减少。然而,请注意,在这种情况下,本征尺度很糟糕。你可以用它。这是专门为(尽可能)扩展一台多核机器而设计的LAPACK的替代品。@Jérôme Richard感谢您的回复。我按照你的建议做了,发现效率随着线程数的增加而略有提高(从1个线程增加到6个线程)。我想知道是否有方法可以提高Eigen的多线程效率。我想用迭代法用稀疏矩阵解线性方程组,PLASMA对我适用吗?显然,PLASMA不支持这一点。您可以查看支持此功能的库的列表。我听说它能做到,但我从来没用过。另外,据我所知,PETSc在内部使用MPI,因此可能更难使用(尽管可能更快)。您可以从了解PETSc是否完全实现了您想要的功能开始。
    // Use RowMajor to make use of multi-threading
typedef SparseMatrix<double, RowMajor> SpMat;
typedef Triplet<double> T;

// Assemble sparse matrix from
// https://eigen.tuxfamily.org/dox/TutorialSparse_example_details.html
void insertCoefficient(int id, int i, int j, double w, vector<T>& coeffs,
                       VectorXd& b, const VectorXd& boundary)
{
  int n = int(boundary.size());
  int id1 = i+j*n;
  if(i==-1 || i==n) b(id) -= w * boundary(j); // constrained coefficient
  else  if(j==-1 || j==n) b(id) -= w * boundary(i); // constrained coefficient
  else  coeffs.push_back(T(id,id1,w));              // unknown coefficient
}

void buildProblem(vector<T>& coefficients, VectorXd& b, int n)
{
  b.setZero();
  ArrayXd boundary = ArrayXd::LinSpaced(n, 0,M_PI).sin().pow(2);
  for(int j=0; j<n; ++j)
    {
      for(int i=0; i<n; ++i)
        {
          int id = i+j*n;
          insertCoefficient(id, i-1,j, -1, coefficients, b, boundary);
          insertCoefficient(id, i+1,j, -1, coefficients, b, boundary);
          insertCoefficient(id, i,j-1, -1, coefficients, b, boundary);
          insertCoefficient(id, i,j+1, -1, coefficients, b, boundary);
          insertCoefficient(id, i,j,    4, coefficients, b, boundary);
        }
    }
}

int main()
{
  int n = 3000;  // size of the image
  int m = n*n;  // number of unknowns (=number of pixels)
  // Assembly:
  vector<T> coefficients;          // list of non-zeros coefficients
  VectorXd b(m);                   // the right hand side-vector resulting from the constraints
  buildProblem(coefficients, b, n);
  SpMat A(m,m);
  A.setFromTriplets(coefficients.begin(), coefficients.end());
  // Solving:
  // Use ConjugateGradient with Lower|Upper as the UpLo template parameter to make use of multi-threading
  clock_t time_start, time_end;
  time_start=clock();
  ConjugateGradient<SpMat, Lower|Upper> solver(A);
  VectorXd x = solver.solve(b);         // use the factorization to solve for the given right hand side

  time_end=clock();
   cout<<"time use:"<<1000*(time_end-time_start)/(double)CLOCKS_PER_SEC<<"ms"<<endl;
   return 0;
}
liu@liu-Precision-3630-Tower:~/test$ g++ test-cg-parallel.cpp -O3 -fopenmp -o cg
liu@liu-Precision-3630-Tower:~/test$ OMP_NUM_THREADS=1 ./cg

time use:747563ms

liu@liu-Precision-3630-Tower:~/test$ OMP_NUM_THREADS=4 ./cg

time use: 1.49821e+06ms

liu@liu-Precision-3630-Tower:~/test$ OMP_NUM_THREADS=8 ./cg

time use: 2.60207e+06ms