2017-08-07 82 views
0

我有一個問題,通過eig_sym犰狳中的本徵分解。當我試圖計算出多組特徵向量的並行,不時的特徵向量是犰狳的eig_sym中的線程安全問題

  • 不是正交
  • 不歸
  • 甚至不會有問題的矩陣的特徵向量。

如果每次只運行一次計算(所以這似乎是一些線程安全問題),此問題消失。一旦兩個計算並行運行,問題就會再次出現。奇怪的是,特徵值在任何情況下都是正確的。

//compile with: g++ -std=c++11 -pthread -larmadillo -o evecs armadillo_evecs.cpp 
#include <iostream> 
#include <armadillo> 
#include <assert.h> 
#include <future> 
#include <vector> 
using namespace std; 

void testcalc() { 
    // set up random symmetric matrix 
    arma::mat r = arma::randu<arma::mat> (100, 100); 
    r = r.t() * r; 

    arma::vec eval; 
    arma::mat evec; 
    // calculate eigenvalues and -vectors 
    assert(arma::eig_sym(eval, evec, r)); 
    arma::mat test = evec.t() * evec; 

    // Check whether eigenvectors are orthogonal, (i. e. matrix 'test' is diagonal) 
    assert(arma::norm(test - arma::diagmat(test)) < 1.0e-10); 
} 


int main() { 
    // start 100 eigenvalue (+vector) calculations 
    vector<future<void>> fus; 
    for (size_t i = 0; i < 100; i++) { 
     // try parallel evaluation ... fails sometimes 
     fus.push_back(async(launch::async, &testcalc)); 

     // try sequential evaluation ... works fine 
     // future<void> f = async(launch::async, &testcalc); 
     // f.get(); // Wait until calculation has finished, before starting new one 
    } 

    // wait until calculations have finished 
    for(auto it = fus.begin(); it != fus.end(); it++) { 
     it->get(); 
    } 

    return 0; 
} 

所以在斷言

assert(arma::norm(test - arma::diagmat(test)) < 1.0e-10); 

上述代碼有時會失敗。可能這是底層庫的問題(我讀過lapack有一些線程安全問題)?我真的不知道,從哪裏開始尋找。

回答

1

而不是「滾動自己的並行化」,使用底層庫已經提供的並行化更簡單,更安全。

因此,不要使用參考BLAS和LAPACK,而應使用多線程版本,如OpenBLASIntel MKL。有關更多詳細信息,請參閱Armadillo FAQ

+0

另外,您應該記住像LAPACK這樣的庫並不是在考慮並行計算的情況下開發的。一些例程從上次調用它們的狀態時開始跟蹤它們的狀態,當由不同的線程訪問時導致問題。 – Hannebambel

+0

感謝您的建議。我現在正在使用OpenBLAS。它確實更安全,也更快。 – okruz