Rcpp中的英特尔MKL SVD:结果不一致

时间:2015-08-01 19:54:32

标签: r rcpp intel-mkl

我写了一个共享的C ++库,我现在正尝试使用Rcpp的.Call函数调用R扩展来调用此库中的函数。该函数使用英特尔MKL函数LAPACKE_dgesdd,它执行矩阵的SVD。

当我有一个大小为m = 5000且n = 8的矩阵时,R扩展和本机C ++版本的输出(U,S,V'矩阵)完全相同(到第15个小数点) ,正如人们所预料的那样。但是,当m = 5000且n = 12时,R版本提供不一致的输出,它与本机C ++版本略有不同。此外,每次我运行它时,R版本给我一个稍微不同的输出(不像n = 8时,它是一致的)。

我真的不知道如何解释这种奇怪的行为。有人有想法吗?

代码如下:

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();
}

然后是R代码:

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');

1 个答案:

答案 0 :(得分:1)

我在编译function.cpp时静态链接MKL解决了这个问题(之前我是动态链接的)。

我发现此链接也很有用:https://software.intel.com/en-us/articles/intel-mkl-custom-static-linkage

我不清楚为什么在进行动态链接时我有如此奇怪的结果。我可以想到的是,也许某些MKL的依赖项是从R自动加载的OpenBLAS或LAPACKE库中提取的。我真的不知道。