简体   繁体   中英

Intel MKL SVD in Rcpp: inconsistent results

I wrote a shared C++ library, and I am now trying to make an R extension using the .Call function of Rcpp to call a function from this library. The function uses the Intel MKL function LAPACKE_dgesdd, which performs an SVD of a matrix.

When I have a matrix of the size m=5000 and n=8, the output (U, S, V' matrices) from the R extension and the native C++ version are exactly the same (to the 15th decimal point), as one might expect. However, when m=5000 and n=12, the R version gives inconsistent output, it is slightly different from the native C++ version. Furthermore, every time I run it, the R version gives me a slightly different output (unlike when n=8, where it is consistent).

I really do not know how to explain this bizarre behavior. Does anyone have any thoughts?

Code is below:

function.cpp:

#include <iostream>
#include "mkl_lapacke.h"
#include "mkl.h"
#include <chrono>


  int testSvd(){
    int m=5000;
    int l=12;
    //Allocate matrices
    double * s2 = (double *)mkl_malloc( l*sizeof( double ), 64 );
    double * Rt2 = (double *)mkl_malloc( l*l*sizeof( double ), 64 );
    double * U_l2 = (double *)mkl_malloc( m*l*sizeof( double ), 64 );
    double * AQ2 = (double *)mkl_malloc( m*l*sizeof( double ), 64 );

    populate_matrix_random (m,l,AQ2); //Note that this populates AQ2 with the same matrix every time it is run

    //Perform the svd
    LAPACKE_dgesdd( LAPACK_ROW_MAJOR, 'S', m, l, AQ2, l, s2, U_l2, l, Rt2, l );

    for (int i=0; i<50; i++ ){
          printf( " %6.12f", U_l2[i] );
    }
    printf("\n\s:");
    for (int i=0; i<50; i++ ){
                    printf( " %6.12f", s2[i] );
    }
    printf("\n\Rt\n:");
     for (int i=0; i<50; i++ ){
                    printf( " %6.12f", Rt2[i] );
    }
 }

mainR.cpp:

#include "function.cpp"
#include <Rcpp.h>
RcppExport SEXP testSvdR() {
    testSvd();
}

And then the R code:

library(Rcpp);
rm(list = ls())
dyn.load("/opt/intel/composer_xe_2015/mkl/lib/intel64/libmkl_rt.so",     local=FALSE);
dyn.load("mainR.so", local=FALSE);
result = .Call('testSvdR');

I solved this problem by statically linking the MKL when compiling function.cpp (I was dynamically linking before).

I found this link also helpful: https://software.intel.com/en-us/articles/intel-mkl-custom-static-linkage

It is not clear to me why I had such strange results when I was doing the dynamic linkage. All I can think is that perhaps some of the MKL's dependencies were being pulled from OpenBLAS or LAPACKE libraries that R automatically loads. I really do not know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM