2016-06-21 19 views
1

Hier ist eine Beschreibung eines seltsamen Fehlers, den ich bei der Verwendung der LAPACKE-Funktion LAPACKE_zheevx() festgestellt habe. Ein einfacher Testcode, der drei von vier Eigenwerten/Vektoren berechnet (das Beispiel von der Intel-Website), funktioniert gut und liefert eine korrekte Ausgabe. Wenn ich jedoch eine Deklaration einer beliebigen Zeichenfolge in den Quellcode einfüge (z. B. std :: string OutputFIlename;), wird die Kompilierung gut ausgeführt, aber bei der Ausführung erhalte ich den Segmentierungsfehler SIGSEGV !!!LAPACKE/GNU C++: Sonderbarer Fehler in der LAPACKE_zheevx() -Funktion

Zuerst werde ich die Code-Liste, die funktioniert:

//=========================== 
#include <iostream> 
#include <string> 
#include <fstream> 
#include <cassert> 

#include <stdlib.h> 
#include <stdio.h> 
#include <complex> 
#include <math.h> 

#include "Headers_LAPACKE\lapacke.h" 
#include "Headers_LAPACKE\lapacke_config.h" 
#include "Headers_LAPACKE\lapacke_mangling.h" 
#include "Headers_LAPACKE\lapacke_utils.h" 

void print_matrix(char* desc, lapack_int m, lapack_int n, lapack_complex_double* a, lapack_int lda); 

int main() 
{ 
    std::cout << "Start..." << std::endl; 
    //std::string fn_VALS; 

    // --------------- LAPACKE --- define variables ---------------------------------------------------------------- 
    // 

    // Define arguments for LAPACKE_zheevx() routine: 
    int matrix_layout; // = LAPACK_ROW_MAJOR or LAPACK_COL_MAJOR 

    char jobz;   // It is ="V" to calculate EigenVECTORS and 
         // ="N" if you don't do it. 

    char range;   // ="A" for ALL values (don't want this), 
         // ="V" for values in in the half-open interval (vl,vu], 
         // ="I" for EigenVALUES indexed from il through iu (this is what you want). 

    char uplo;   // ="U" for Upper Triangle of the matrix, or 
         // ="L" for the Lower triangle of the matrix. 

    lapack_int n;  // the order of matrix "a" to be diagonalized. 

    lapack_complex_double* a; // complex array of dimension (lda,n). 
           // On entry it is Hermitian matrix "a". 
           // uplo="U" means the leading n-by-n upper triangular part of "a" contain the upper triangular part of the Hermitial matrix to be diagonalized. 
           // uplo="L" means equivalent for the lower triangular part. 
           // On exit, this content is destroyed. 

    lapack_int lda;  // leading dimension of "a": lda >= max(1,n). 

    double vl;   // taken into account only if range="V": vl<vu. Not referenced if range="I" or range="A". 
    double vu;   // taken into account only if range="V": vl<vu. Not referenced if range="I" or range="A". 

    lapack_int il;  // taken into account only if range="I": il<iu. Indices in ascending order of SMALLEST EigenVALUE to be returned. Not referenced if range="v" or range="A". 
    lapack_int iu;  // taken into account only if range="I": il<iu. Indices in ascending order of LARGEST EigenVALUE to be returned. Not referenced if range="v" or range="A". 

    double abstol;  // The absolute error tolerance for EigenVALUES. If abstop =<0, then EPS*|T| is used. If you get info>0 (some eigenvalues did not converge) then try abstol=2*DLAMCH('S'). 
    lapack_int* m;  // total number of EigenVALUES found: 0 =< m =< n, If range="A" then m=n, if range="I" then m = iu-il+1. 
    double* w;   // double precision array of dimension n. On normal exit, the first m elements contain the selected EigenVALUES in ASCENDING ORDER. 
    lapack_complex_double* z; // double precision array of dimension (ldz, max(1,m)). If jobz="V" and info=0, the first m-columns of z contain normalized EigenVECTORS of a, corresponding to the selected EigenVALUES, with i-th column of z contains the Eigenvectro corresponding to w(i) eigenvalue. 
    lapack_int ldz;  // leading dimension of array z. ldz>=1 and if jobz="V" then ldz >= max(1,n). 

     // following are used only with LAPACKE_zheevx_work() routine:. 
     //lapack_complex_double* work; // array of dimension max(1,lwork). 
     //lapack_int lwork;    // lwork=-1 means workspace query. Othewise it has to be length of the array work: lwork=2*n for n>1, and lwork >=1 for N=<1. 
     //double* rwork;     // array dimension is 7*n; 
     //lapack_int* iwork;    // array dimension is 5*n; 

    lapack_int* ifail; // jobz="V" and info=0: first m elemens of ifail are zero. jobz="V" and info>0: ifail contain indices of the eigenvectors that failed to converge. 
    lapack_int info; //info=0 means successful exit. info>0 means eigenvectors failed to converge, their indices are in ifail. info<0, info=-i means i-th argument had an illegal value. 
    // 
    // ------------------------------------------------------------------------------------------------------------ 

    matrix_layout = LAPACK_ROW_MAJOR; 
    jobz = 'V'; vl = 0.0; vu =100.0; 
    il = 1; iu=4; // are ignored now. 
    range = 'V'; 
    uplo ='U'; 
    n = 4; 
    lda = n; 
    ldz = n; 

    z = new lapack_complex_double [ldz*n]; 
    w = new double [n]; 
    a = new lapack_complex_double [lda*n]; 
    a[0] =lapack_complex_double{6.51,0.0}; a[1] =lapack_make_complex_double(-5.92, 9.53); a[2]=lapack_complex_double{-2.46,2.91}; a[3]=lapack_complex_double{8.84,3.21}; 
    a[4] =lapack_complex_double{0.0,0.0}; a[5] =lapack_make_complex_double(-1.73,0.0); a[6]=lapack_complex_double{6.5,2.09}; a[7]=lapack_complex_double{1.32, 8.81}; 
    a[8] =lapack_complex_double{0.0,0.0}; a[9] =lapack_make_complex_double(0.0,0.0);  a[10]=lapack_complex_double{6.90,0.0}; a[11]=lapack_complex_double{-0.59,2.47}; 
    a[12]=lapack_complex_double{0.0,0.0}; a[13]=lapack_make_complex_double(0.0,0.0);  a[14]=lapack_complex_double{0.0,0.0}; a[15]=lapack_complex_double{-2.85,0.0}; 

    ifail = new lapack_int [n]; 
    abstol = -1; // set default tolerance for calcuation of EigVals in the assigned interval. 

    print_matrix("Entry Matrix A:", n, n, a, lda); 
    std::cout << std::endl; 

    info = LAPACKE_zheevx(matrix_layout, jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, ifail); 

    if (info>0) 
    { 
     std::cout << "Error: ZHEEVX failed to compute eigenvalues/vectors."; 
     exit(1); 
    } 
    std::cout << "info = " << info << std::endl; 

    std::cout << "Number of eigvals found: " << *m << std::endl; 
    for (int i_e =0; i_e<*m; i_e++) 
    { 
     std::cout << "Eigval. " << i_e << " is " << w[i_e] << std::endl; 
    } 

    print_matrix("Selected EigVECTORS (column-wise):", n, n, z, ldz); 
    std::cout << std::endl; 


    std::cout << "Done :-) !!!" <<std::endl; 

    return 0; 
} 


////////////////////////////////////////////////////////* Auxiliary routine: printing a matrix */ 
void print_matrix(char* desc, lapack_int m, lapack_int n, lapack_complex_double* a, lapack_int lda) 
{ 
     lapack_int i, j; 
     printf("\n %s\n", desc); 
     for(i = 0; i < m; i++) 
     { 
      for(j = 0; j < n; j++) 
      { 
       printf(" (%6.2f,%6.2f)", lapack_complex_double_real(a[i*lda+j]), lapack_complex_double_imag(a[i*lda+j])); 
      } 
      printf("\n"); 
     } 
} 
//======================================= 

Nun, wenn in main() entfernt man das Kommentarsymbol (//) on line 2: // std :: string fn_VALS; Dies wird zu std :: string fn_VALS; Damit kompiliert sich die Quelle, schlägt aber zur Laufzeit mit dem Segmentierungsfehler SIGSEGV fehl.

Weitere Informationen:

Ich benutze Windows 7 Pro und Code :: Blocks, die LAPACKE Kopf- und DLL wurden auf 2016.06.15 heruntergeladen. der Konsole: Prozess zurück -1073741819 (0xC0000005) Vom Call-Stack-Fenster in Code :: Blocks

.......... main() ruft LAPACKE_zheevx() [lapacke.dll]

.......... LAPACKE_zheevx() ruft LAPACKE_zheevx_work() [lapacke.dll]

.......... LAPACKE_zheevx_work() ruft zheevx_() [lapack.dll ]

Bitte helfen.

Antwort

1

Ich habe versucht, das Programm, das Sie durch Eingabe prodived zu kompilieren:

g++ main.cpp -o main -llapacke -llapack -lblas -lm -Wall 

Die Flagge -Wall alle Warnungen ermöglicht. Eine der Warnungen ist interessant:

Warnung: ‚m‘ in dieser Funktion nicht initialisierten verwendet wird [-Wuninitialized]

Der Zeiger lapack_int* m; wird nicht als LAPACKE_zheevx(..., m, ...); initialisiert wird aufgerufen. Daher kann es auf eine beliebige Stelle im Speicher zeigen. Es wird erwartet, dass der Zeiger m einen Ausgabeparameter der Funktion hostet, und es ist wahrscheinlich, dass LAPACKE_zheevx() oder eine nachfolgende Funktion den Zeiger m dereferenziert. Dies führt zu undefiniertem Verhalten: Je nachdem, wo m zeigt, kann es unbemerkt bleiben oder einen Segmentierungsfehler auslösen.

Können Sie versuchen lapack_int* m[1]; anstelle von lapack_int* m;?

This example from intel nicht das gleiche Problem verfügen wie m als MKL_INT und vorbei Argument an die Funktion (&m) decleared wird. Ist es der, von dem du angefangen hast?

+0

Vielen Dank. Das hat geholfen. Hier ist, was ich im Code geändert habe: nur vorgestellte Zeile mit m = new lapack_int [1]; Die Variablen im Aufruf von LAPACKE_zheevx wurden unverändert beibehalten. – Boki

+0

Alle Variablen, die als Ergebnis/Ausgabe von LAPACKE_zheevxI() zurückgegeben wurden, wurden als Zeigerarrays behandelt. Nur der einzelne Wert von "m" war nicht, und jetzt, wenn "m" ein Zeiger-Array mit einem Element m [0] wurde, funktionierte es. – Boki

+0

Ich frage mich, ob es eine nette Webseite mit Beispielen für LAPACKE High/Mid Level Routinen gibt? Ich konnte keinen bereuten. Diese Intel-Website (ja, ich benutzte dieses Beispiel) nutzt ihre eigene MKL – Boki