2017-05-26 70 views
0

我想比較在犰狳中使用spsolve()時SuperLu的稀疏求解器的速度和使用LaPack的密度版本的速度。因此,我寫了這個程序:使用armadillo進行基準測試時SuperLu和LaPack的比較失敗

#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; 
} 

現在爲SIZEROUNDapprox_equal返回true,則函數值較小,但對於較大值的結果b1b2不等於再根據approx_equal。爲什麼?問題是我的超級圖書館工作不正常?

回答

1

我不會責怪SuperLU圖書館。這裏的「問題」似乎是A矩陣的最小特徵值對於逐漸增大和變大的SIZE值變得越來越小。現在,for循環重複將inv(A)應用於給定的向量。由於您從頭開始的矢量是隨機的,因此它將具有與最小特徵值相對應的特徵向量的非零「混合」A。如果反演重複多次,則該分量變得明顯放大,因此矢量b1/b2的各個分量變大。

例如,對於SIZE=2000ROUNDS=2,我得到解決方案的最大分量(絕對值)大約是10^9。您的測試似乎規定了10^-5絕對公差。然而,對於如此大的數字,這意味着14位有效數字必須完全匹配,幾乎在雙精度的極限處。 在我看來,考慮到這裏比較的數字的性質,測試會更有意義,例如與approx_equal(b1, b2, "reldiff", 1E-8)的相對誤差。

此外,應該檢查解決方案是否有意義 - 對於大量的ROUNDS,它遲早會溢出。例如已有SIZE=2000ROUNDS=80,我得到b1/b2載體中的無窮大...

相關問題