[英]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. 我编写了一个共享的C ++库,现在尝试使用
.Call
函数进行R扩展,以从该库中调用函数。 The function uses the Intel MKL function LAPACKE_dgesdd, which performs an SVD of a matrix. 该函数使用英特尔MKL函数LAPACKE_dgesdd,该函数执行矩阵的SVD。
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. 当我有一个大小为m = 5000且n = 8的矩阵时,R扩展和本机C ++版本的输出(U,S,V'矩阵)完全相同(小数点后15位)可能会期望。 However, when m=5000 and n=12, the R version gives inconsistent output, it is slightly different from the native C++ version.
但是,当m = 5000和n = 12时,R版本的输出不一致,它与本机C ++版本略有不同。 Furthermore, every time I run it, the R version gives me a slightly different output (unlike when n=8, where it is consistent).
此外,每次运行它时,R版本都会为我提供稍有不同的输出(与n = 8一致的情况不同)。
I really do not know how to explain this bizarre behavior. 我真的不知道如何解释这种奇怪的行为。 Does anyone have any thoughts?
有人有想法吗?
Code is below: 代码如下:
function.cpp: 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: mainR.cpp:
#include "function.cpp"
#include <Rcpp.h>
RcppExport SEXP testSvdR() {
testSvd();
}
And then the R code: 然后是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');
I solved this problem by statically linking the MKL when compiling function.cpp (I was dynamically linking before). 我通过在编译function.cpp时静态链接MKL解决了这个问题(之前我是动态链接的)。
I found this link also helpful: https://software.intel.com/en-us/articles/intel-mkl-custom-static-linkage 我发现此链接也有帮助: https : //software.intel.com/zh-cn/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.
我能想到的是,也许MKL的某些依赖项是从R自动加载的OpenBLAS或LAPACKE库中提取的。 I really do not know.
我真的不知道。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.