为了加快一些物理模拟代码的速度,我将Pardiso与Eigen结合使用。与诸如Eigen的SparseLU之类的替代求解器相比,Pardiso使我的分解步骤显着提高,随着我增加线程数而增加。
但是,在我的仿真代码中,此求解的RHS不是单个向量,而是矩阵。从并行的角度来看,我可以想象这很好,因为每个反向求解都是独立的,但是在增加线程数时,我注意到在求解步骤中没有加速。
因此,我尝试使用OpenMP并行进行反向求解。虽然明显更快,但始终会返回错误的结果。我已经建立了一个大致像这样的测试...
SparseMatrix<double> A = ...;
SparseMatrix<double> B = ...;
mkl_set_num_threads(t);
// Factorize
pardiso.factorize(A);
// Solve1
SparseMatrix<double> X1 = pardiso.solve(B);
// Solve2
SparseMatrix<double> X2(A.rows(), B.cols());
#pragma omp parallel num_threads(t)
{
#pragma omp for
{
for (int n = 0; n < B.cols(); ++n)
{
X2.col(n) = pardiso.solve(B.col(n));
}
}
}
X2.isApprox(X1); // I know X1 is giving me the correct matrix, but this return false
我很好奇,如果有人知道无论num_threads为何Solve1都具有相同的速度,或者是否有人知道Solve2为何返回错误的矩阵。
我在Windows上使用VS2019,并使用Intel C ++编译器进行编译,将Use MKL设置为parallel,并打开了OpenMP。我已经测试过OpenMP可以正常工作,当omp使用单线程时Solve2是正确的,而使用OpenMP和Eigen的SparseLU则Solve2是正确的。我也仔细研究了所有这些先前的问题。
Eigen::PardisoLU (MKL) in parallel scenario
Calling multithreaded MKL in from openmp parallel region
Number of threads of Intel MKL functions inside OMP parallel regions
我仍然最终得到不正确的输出。在所有内容之前都设置mkl_set_dynamic(1)
和omp_set_nested(1)
不会改变任何内容。