c++ - 使用 Armadillo 进行基准测试时,SuperLu 和 LaPack 的比较失败

标签 c++ lapack armadillo

我想在使用 spsolve() 时比较 SuperLu 的稀疏求解器和使用 LaPack 的密集版本的速度在 Armadillo 。因此我写了这个程序:

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <armadillo\armadillo>

#define SIZE 2500
#define ROUNDS 2500

int main()
{
    //Time measurement stuff
    LARGE_INTEGER frequency;
    LARGE_INTEGER t1, t2, t3, t4;
    QueryPerformanceFrequency(&frequency);
    //Other stuff
    arma::cx_colvec b = arma::randu<arma::cx_colvec>(SIZE);
    arma::cx_colvec b1 = b, b2 = b;
    arma::sp_cx_mat A = arma::sp_cx_mat(SIZE, SIZE);
    A.diag(-2).fill(-1);
    A.diag(-1).fill(16);
    A.diag(0).fill(-30);
    A.diag(1).fill(16);
    A.diag(2).fill(-1);


    arma::cx_colvec c = arma::zeros<arma::cx_colvec>(SIZE), d = arma::zeros<arma::cx_colvec>(SIZE); 
    QueryPerformanceCounter(&t1);
    for (size_t i = 0; i < ROUNDS; i++)
    {
        if(arma::spsolve(c, A, b1, "superlu") == false)
        {
            std::cout << "Error in round 1\n";
            break;
        }
        b1 = c;
    }
    QueryPerformanceCounter(&t2);
    QueryPerformanceCounter(&t3);
    for (size_t i = 0; i < ROUNDS; i++)
    {
        if(arma::spsolve(d, A, b2, "lapack") == false)
        {
            std::cout << "Error in round 2\n";
            break;
        }
        b2 = d;
    }
    QueryPerformanceCounter(&t4);
    std::cout << "Superlu took " << (t2.QuadPart - t1.QuadPart)*1000.0 / frequency.QuadPart << '\n';
    std::cout << "Lapack took " << (t4.QuadPart - t3.QuadPart)*1000.0 / frequency.QuadPart << '\n';
    std::cout << "Both results are equal: " << arma::approx_equal(b1, b2, "abstol", 1e-5) << '\n';
    return 0;
}

现在 SIZE 的小值和 ROUND函数approx_equal返回 true,但对于较大的值,结果 b1b2根据 approx_equal 不再相等.为什么?会不会是我的superlu-library没有正常工作?

最佳答案

我不会责怪 SuperLU 库。这里的“问题”似乎是矩阵 A 的最小特征值随着 SIZE 的值越来越大而变得越来越小。现在,for 循环将 inv(A) 重复应用于给定 vector 。由于您开始使用的 vector 是随机的,因此 A 的特征向量将具有一些非零“混合”,对应于最小特征值。如果反演重复多次,该分量会显着放大,因此 vector 的各个分量 b1/b2 会变大。

例如,对于 SIZE=2000ROUNDS=2,我得到解的最大分量(绝对值)约为 10^ 9。然后,您的测试似乎规定了 10^-5绝对容差。然而,对于如此大的数字,这意味着 14 位有效数字必须完全匹配,这几乎是 double 的极限。 在我看来,鉴于这里比较的数字的性质,测试更有意义,例如,使用 approx_equal(b1, b2, "reldiff", 1E-8) 的相对误差.

此外,还应该检查解决方案实际上是否有意义 - 对于大量的 ROUNDS,它迟早会溢出。例如,在 SIZE=2000ROUNDS=80 的情况下,我在 b1/b2 vector 中得到无穷大...

关于c++ - 使用 Armadillo 进行基准测试时,SuperLu 和 LaPack 的比较失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44209297/

相关文章:

c++ - 如何根据行总数的条件删除 Armadillo 中 SpMat<unsigned int> 的行?

c++ - opencv-3.0.0 ubuntu 14.04 "nonfree/nonfree.hpp"构建错误

ubuntu - 使用 BLAS (LAPACK) 模块编译 Fortran 代码

c++ - 用C/C++在Linux中读取内核信息

c++ - LAPACK dgetrs 与 dgesv

Linux 使用 lapack 库

r - 在 Rcpp 中使用属性并使用 RcppArmadillo 代码时出现错误

c++ - 我可以在 Armadillo 中实例化矩阵,然后在后面的代码行中将其设置为使用辅助内存吗?

c++ - 如何将名称发送给不同的功能

c++ - OS X 10.8.5 下的 Boost 编译错误