2015-05-13 71 views
1

我嘗試使用下面的代碼來解決線性系統:使用LAPACKE_zgetrs與LAPACK_ROW_MAJOR導致非法的內存訪問

#include <stdio.h> 
#include <lapacke.h> 

int main() { 
    lapack_complex_double mat[4]; 
    lapack_complex_double vec[2]; 
    lapack_int p[2]; 

    mat[0] = lapack_make_complex_double(1,0); 
    mat[1] = lapack_make_complex_double(1,0); 
    mat[2] = lapack_make_complex_double(1,0); 
    mat[3] = lapack_make_complex_double(-1,0); 

    vec[0] = lapack_make_complex_double(1,0); 
    vec[1] = lapack_make_complex_double(1,0); 

    LAPACKE_zgetrf(LAPACK_ROW_MAJOR, 2, 2, mat, 2, p); 
    LAPACKE_zgetrs(LAPACK_ROW_MAJOR, 'N', 2, 1, mat, 2, p, vec, 2); 

    printf("%g %g\n", lapack_complex_double_real(vec[0]), 
     lapack_complex_double_imag(vec[0])); 
    return 0; 
} 

由於種種原因,這導致LAPACKE_zgetrs非法的內存訪問(通過valgrind和檢測到我的大程序崩潰zgetrs因爲「glibc檢測到腐敗或雙免費」)。爲了簡潔起見,我沒有在我的SSCCE中包括這個,但所有LAPACKE例程返回,返回0.

LAPACK_COL_MAJOR相同的代碼運行和valgrinds完美無缺。

我的lapacke,lapack等是Ubuntu 12.04自建的。我用在LAPACK CMake的文件中的下列設置:

BUILD_COMPLEX  ON 
BUILD_COMPLEX16  ON 
BUILD_DOUBLE  ON 
BUILD_SHARED_LIBS ON 
BUILD_SINGLE  ON 
BUILD_STATIC_LIBS ON 
BUILD_TESTING  ON 
CMAKE_BUILD_TYPE Release 
LAPACKE    ON 
LAPACKE_WITH_TMG ON 

,其餘(優化的BLAS/LAPACK和xblas)關閉。在構建期間沒有錯誤,並且所有測試都成功了。

我在哪裏搞砸了?

編輯:我只是試着用Fedora21和打包的lapacke。它沒有而是重現錯誤。

編輯2:雖然它不會重現內存出現故障,它會產生一個錯誤的解決方案,即(1 + 0I, 1 + 0I)對於上面的輸入(應該是(1,0)

+0

我發現[這個線程](https://software.intel.com/en-us/forums/topic/499788),它表明在計算膽固醇分解時行LAPACKE中有一個錯誤。我不確定'zgetrf'是否執行了一個,如果它觸發了一個類似的錯誤,但似乎可能,因爲你想要進行LU分解。 – martin

+0

@martin cholesky分解是LL^T分解。 – ztik

+0

@ctheo是的,這仍然是在某些情況下LU分解的特例。但你是對的,矩陣不是肯定的。 – martin

回答

0

經過一些調查研究,並得太多的東西,我找到了元兇:

使用LAPACK_ROW_MAJOR切換ld*主角尺寸參數的含義。雖然正常Fortran陣列的前導維數是的數字,但切換到ROW_MAJOR會將其含義切換爲列的數量。所以,正確的呼叫(給予正確的結果)是:

LAPACKE_zgetrs(LAPACK_ROW_MAJOR, 'N', 2, 1, mat, 2, p, vec, 1); 

其中第二2mat數量(不是行!),最後一個參數必須等於右手邊數nrhs(不是變量的數量!)。我隔離了這個呼叫,因爲我的項目中的所有其他呼叫處理方矩陣,所以「錯誤」呼叫由於對稱性而沒有任何負面影響。與往常一樣,如果您在最後跳過列,則主要維度會相應地變大,就像他們在正常設置中跳過行一樣。

顯然,這在Fortran文檔中沒有提及。不幸的是,我在Lapacke文檔中沒有看到這樣的評論,這會爲我節省幾個小時的時間。 :)

相關問題