Search code examples
c++valgrindlapackintel-mkl

Valgrind detects memory leaks in MKL/LAPACK STEVR function for eigenvalue problems with matrix sizes above a threshold


I am working on software that uses the Intel MKL implementation of LAPACK functions for eigenvalue problems. When I ran Valgrind to check the code for memory leaks it reported errors only when using the function 'STEVR', or more precisely the C-funtion LAPACKE_dstevr. In order to find out if my interface is the problem or the called function, I wrote an isolated test application. The code looks like this:

#include <mkl/mkl.h>
#include <random>

int main() {

    // Tolerance
    double absTol = 1e-12;

    // Problem size
    lapack_int n = 64;

    // Generate random tridiagonal symmetric matrix
    std::mt19937 randomGen;
    std::normal_distribution<double> normal(1., 1.);
    double *mainDiagonal = new double[n];
    double *subDiagonal = new double[n-1];
    for (int i=0; i<n-1; i++) {
        mainDiagonal[i] = normal(randomGen);
        subDiagonal[i] = normal(randomGen);
    }
    mainDiagonal[n-1] = normal(randomGen);

    // Allocate memory for results 
    double *eigenValues = new double[n];
    double *eigenVectors = new double[n*n];

    // Resulting integer array and integer for leading dimension 
    // allocated/initialized according to MKL/LAPACK documentation
    lapack_int *isuppz = new lapack_int[2*n]();
    lapack_int ldz = n;

    // Eigenvectors shall be computed
    char job = 'V';

    // All pairs of eigenvalues and -vectors shall be computed
    char range = 'A';

    // These values can remain uninitialized (irrelevant it range=='A')
    lapack_int lowerIndex, upperIndex, upperBound, lowerBound;

    // Number of eigenvalues found (output parameter)
    lapack_int m;

    // Solve problem using MKL/LAPACK function
    LAPACKE_dstevr(LAPACK_ROW_MAJOR, job, range, n, mainDiagonal, subDiagonal,
            lowerBound, upperBound, lowerIndex, upperIndex, absTol, &m, 
            eigenValues, eigenVectors, ldz, isuppz);

    // Free memory
    delete[] mainDiagonal;
    delete[] subDiagonal;
    delete[] eigenValues;
    delete[] eigenVectors;
    delete[] isuppz;
    
    return 0;
}

Compiling it with

g++ -fopenmp -ggdb3 -Wall -Wextra test_dstevr.cpp -lmkl_intel_lp64 -lmkl_core -lmkl_gnu_thread -lpthread -lm -ldl -lmkl_rt -o test_dstevr

and running valgrind with the command

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.out ./test_dstevr

gives me 0 errors. If I change the size of the matrix to n = 65 or any number greater than 64, however, Valgrind reports

ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

and

==48382== 960 bytes in 3 blocks are possibly lost in loss record 10 of 12
==48382==    at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==48382==    by 0x40149DA: allocate_dtv (dl-tls.c:286)
==48382==    by 0x40149DA: _dl_allocate_tls (dl-tls.c:532)
==48382==    by 0xB549322: allocate_stack (allocatestack.c:622)
==48382==    by 0xB549322: pthread_create@@GLIBC_2.2.5 (pthread_create.c:660)
==48382==    by 0xB320DEA: ??? (in /usr/lib/x86_64-linux-gnu/libgomp.so.1.0.0)
==48382==    by 0xA08AA10: mkl_trans_mkl_domatcopy2_par (in /usr/lib/x86_64-linux-gnu/libmkl_gnu_thread.so)
==48382==    by 0xCF5D5F4: mkl_trans_avx2_mkl_domatcopy (in /usr/lib/x86_64-linux-gnu/libmkl_avx2.so)
==48382==    by 0x4D76FBC: LAPACKE_dge_trans (in /usr/lib/x86_64-linux-gnu/libmkl_intel_lp64.so)
==48382==    by 0x4DB57DB: LAPACKE_dstevr_work (in /usr/lib/x86_64-linux-gnu/libmkl_intel_lp64.so)
==48382==    by 0x4DB5430: LAPACKE_dstevr (in /usr/lib/x86_64-linux-gnu/libmkl_intel_lp64.so)
==48382==    by 0x10951C: main (test_dstevr.cpp:45)

Of course, being a power of two, the number 64 does not seem random to me, but I have absolutely no idea what the problem might be. Does anybody here? I am using Ubuntu 20.04 LTS and GCC 9.4.0.


Solution

  • Here is the solution for anyone else with a similar issue. Try using the latest oneMKL version 2022.2.0 which is now available for download and here is the command with Intel oneAPI compilers

    icpx -ggdb3 -I"${MKLROOT}/include" test_dstevr.cpp -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -ldl -o test_dstevr
    

    After compiling, try running Valgrind with the below command and we see no issues now

    valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --verbose --log-file=valgrind.out ./test_dstevr