0

I use Rcpp::sourceCpp("test.cpp") and it output the following error information. Note that check1() works and check2 fails. The difference is "arma::vec" and "arma::fvec". The error happens when I tried it on a Windows. When I tried it on linux, it works.

(EDIT: I have added my R environment on Linux. PS: Results on Linux shows that float is faster than double, which is why I prefer using float)

C:/RBuildTools/3.5/mingw_64/bin/g++  -std=gnu++11 -I"C:/PROGRA~1/R/R-36~1.1/include" -DNDEBUG -I../inst/include -fopenmp  -I"C:/Users/wenji/OneDrive/Documents/R/win-library/3.6/Rcpp/include" -I"C:/Users/wenji/OneDrive/Documents/R/win-library/3.6/RcppArmadillo/include" -I"Y:/"        -O2 -Wall  -mtune=generic -c check.cpp -o check.o
C:/RBuildTools/3.5/mingw_64/bin/g++ -shared -s -static-libgcc -o sourceCpp_3.dll tmp.def check.o -fopenmp -LC:/PROGRA~1/R/R-36~1.1/bin/x64 -lRlapack -LC:/PROGRA~1/R/R-36~1.1/bin/x64 -lRblas -lgfortran -lm -lquadmath -LC:/PROGRA~1/R/R-36~1.1/bin/x64 -lR
check.o:check.cpp:(.text+0xa18): undefined reference to `sdot_'
collect2.exe: error: ld returned 1 exit status

The below is the R environment on Windows

R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18362)

Matrix products: default

Random number generation:
 RNG:     Mersenne-Twister 
 Normal:  Inversion 
 Sample:  Rounding 

locale:
[1] LC_COLLATE=English_United States.1252  LC_CTYPE=English_United States.1252   
[3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C                          
[5] LC_TIME=English_United States.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_3.6.1            tools_3.6.1               RcppArmadillo_0.9.850.1.0
[4] Rcpp_1.0.3 

The below is the R environment on Linux

R version 3.6.3 (2020-02-29)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 16.04.6 LTS

Matrix products: default
BLAS:   /usr/lib/openblas-base/libblas.so.3
LAPACK: /usr/lib/libopenblasp-r0.2.18.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] compiler_3.6.3            tools_3.6.3              
[3] RcppArmadillo_0.9.850.1.0 Rcpp_1.0.4  

The below is The codes of "test.cpp"

// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>

using namespace Rcpp;

// [[Rcpp::export]]
NumericVector timesTwo(NumericVector x) {
  return x * 2;
}

// [[Rcpp::export]]
arma::vec check1(arma::vec x1, arma::vec x2, int rep){
  int n = x1.size();
  arma::vec y(n);
  y.fill(0);
  for(int i = 0; i < rep; i ++){
    y += x1 * arma::dot(x1, x2);
  }
  return y;
}

// [[Rcpp::export]]
arma::fvec check2(arma::fvec x1, arma::fvec x2, int rep){
  int n = x1.size();
  arma::fvec y(n);
  y.fill(0);
  for(int i = 0; i < rep; i ++){
    y += x1 * arma::dot(x1, x2);
  }
  return y;
}

// You can include R code blocks in C++ files processed with sourceCpp
// (useful for testing and development). The R code will be automatically 
// run after the compilation.
//

/*** R
timesTwo(42)
n = 100000
x1 = rnorm(n)
x2 = rnorm(n)
rep = 1000
system.time(y1 <- check1(x1, x2, rep))
system.time(y2 <- check2(x1, x2, rep))
head(y1)
head(y2)
*/

The below is the output on Linux

> system.time(y1 <- check1(x1, x2, rep))
   user  system elapsed 
  0.156   0.000   0.160 

> system.time(y2 <- check2(x1, x2, rep))
   user  system elapsed 
  0.088   0.000   0.100
halfer
  • 19,824
  • 17
  • 99
  • 186
Wenjian Bi
  • 11
  • 3

1 Answers1

1

There are two questions here:

  1. Why did it work on Linux but not Windows?

R only has int and double, but not float (or 64-bit integer). On Windows you may be linking with R's own internal LAPACK which likely only has double. On Linux float may be present in the system LAPACK. That is my best guess.

  1. Can you / should you use float with Armadillo?

Not really. R only has double and not float so to get values back and forth will always involve copies and is less efficient. I would stick with double.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Thanks for the response. As for 1. I also noticed that for linux, sessionInfo() outputs the following information with BLAS and LAPACK. But I do not know what to do so that windows can also work. Matrix products: default BLAS: /usr/lib/openblas-base/libblas.so.3 LAPACK: /usr/lib/libopenblasp-r0.2.18.so As for 2, I previously use double but I recently found that float is faster. > system.time(y1 <- check1(x1, x2, rep)) user system elapsed 0.156 0.000 0.160 > system.time(y2 <- check2(x1, x2, rep)) user system elapsed 0.088 0.000 0.100 – Wenjian Bi Apr 03 '20 at 12:36
  • And if you do that on Windows you likely see the internal LAPACK listed confirming my hunch. Anyway, best to get used to using `double` only. – Dirk Eddelbuettel Apr 03 '20 at 12:39
  • It seems not easy to make it work on Windows. I have decided to give it up and just focus on Linus. Thank you Dirk anyway. – Wenjian Bi Apr 03 '20 at 17:51