I was wondering if anybody has tried to use Rcpp and MAGMA to accelerate linear algebra operations in R by using the CPU and GPU? I tried culatools last month and it worked with Rcpp (link), but culatools is a commercial product that costs money to get access to all functions.
Asked
Active
Viewed 1,302 times
1 Answers
5
It was pretty straightforward to use Rcpp and MAGMA after having tinkered around with culatools. Here is the .cpp file:
#include<Rcpp.h>
#include<magma.h>
using namespace Rcpp;
RcppExport SEXP gpuQR_magma(SEXP X_)
{
// Input
NumericMatrix X(X_);
// Initialize magma and cublas
magma_init();
cublasInit();
// Declare variables
int info, lwork, n_rows = X.nrow(), n_cols = X.ncol(), min_mn = min(n_rows, n_cols);
double tmp[1];
NumericVector scale(min_mn);
// Query workspace size
magma_dgeqrf(n_rows, n_cols, &(X[0]), n_rows, &(scale[0]), &(work[0]), -1, &info);
lwork = work[0];
NumericVector work(lwork);
// Run QR decomposition
magma_dgeqrf(n_rows, n_cols, &(X[0]), n_rows, &(scale[0]), &(work[0]), lwork, &info);
// Scale factor result
for(int ii = 1; ii < n_rows; ii++)
{
for(int jj = 0; jj < n_cols; jj++)
{
if(ii > jj) { X[ii + jj * n_rows] *= scale[jj]; }
}
}
// Shutdown magma and cublas
magma_finalize();
cublasShutdown();
// Output
return wrap(X);
}
The file can be compiled from R into a shared library using:
library(Rcpp)
PKG_LIBS <- sprintf('-Wl,-rpath,/usr/local/magma/lib -L/usr/local/magma/lib -lmagma /usr/local/magma/lib/libmagma.a -Wl,-rpath,/usr/local/cuda-5.5/lib64 %s', Rcpp:::RcppLdFlags())
PKG_CPPFLAGS <- sprintf('-DADD_ -DHAVE_CUBLAS -I/usr/local/magma/include -I/usr/local/cuda-5.5/include %s', Rcpp:::RcppCxxFlags())
Sys.setenv(PKG_LIBS = PKG_LIBS , PKG_CPPFLAGS = PKG_CPPFLAGS)
R <- file.path(R.home(component = 'bin'), 'R')
file <- '/path/gpuQR_magma.cpp'
cmd <- sprintf('%s CMD SHLIB %s', R, paste(file, collapse = ' '))
system(cmd)
The shared library can now be called in R. Comparing the results with with R's qr() gives:
dyn.load('/path/gpuQR_magma.so')
set.seed(100)
n_row <- 3; n_col <- 3
A <- matrix(rnorm(n_row * n_col), n_row, n_col)
qr(A)$qr
[,1] [,2] [,3]
[1,] 0.5250957 -0.8666925 0.8594266
[2,] -0.2504899 -0.3878643 -0.1277838
[3,] 0.1502909 0.4742033 -0.8804247
.Call('gpuQR_magma', A)
[,1] [,2] [,3]
[1,] 0.5250957 -0.8666925 0.8594266
[2,] -0.2504899 -0.3878643 -0.1277838
[3,] 0.1502909 0.4742033 -0.8804247
Below are the results from a benchmark using a NVIDIA GeForce GTX 675MX GPU with 960 CUDA cores and OpenBLAS:
n_row <- 3000; n_col <- 3000
A <- matrix(rnorm(n_row * n_col), n_row, n_col)
B <- A; dim(B) <- NULL
res <- benchmark(.Call('gpuQR_magma', A), .Call('gpuQR_cula', B, n_row, n_col), qr(A), columns = c('test', 'replications', 'elapsed', 'relative'), order = 'relative')
test replications elapsed relative
2 .Call("gpuQR_cula", B, n_row, n_col) 100 18.704 1.000
1 .Call("gpuQR_magma", A) 100 70.461 3.767
3 qr(A) 100 985.411 52.685
Seems like as if MAGMA is a bit slower compared to culatools (in this example). However, MAGMA comes with out-of-memory implementations and that is something I value a lot given only 1Gb of GPU memory.

chris
- 461
- 2
- 10
-
4The Rcpp authors encourage people with nice example like yours to post on http://gallery.rcpp.org/ to share nice examples like yours. From my point of vue your stuff deserve a spot there... Let's see what they think – statquant Aug 23 '13 at 11:53
-
There are existing CRAN packages like WideLm which use Rcpp to get from R to the C-based API of CUDA; one could easily do the same for Magma. – Dirk Eddelbuettel Aug 23 '13 at 18:04
-
There is actually the [magma *R*-package](http://cran.r-project.org/web/packages/magma/index.html). It does not use *Rcpp* though. I posted my code for later references. Documentation for *MAGMA* is really thin and even thinner when it comes to using it with *Rcpp*. – chris Aug 23 '13 at 19:23
-
Doh. Should have remembered the CRAN package magma. – Dirk Eddelbuettel Aug 23 '13 at 21:06
-
Yes, I took that package as a starting point for my code. Does it make sense to submit a *Rcpp/MAGMA* example to the *Rcpp* gallery? – chris Aug 23 '13 at 21:27
-
You would probably need to package it a bit more. It would need to run on the box converting the Rmd (or cpp) file for the post. Which needs to have Magma installed... – Dirk Eddelbuettel Aug 24 '13 at 01:46
-
I have it as a R package now with configure and makefile. It looks for MAGMA on the box and runs with R CMD INSTALL ... What is next to get it in the gallery? – chris Sep 05 '13 at 05:54
-
error: no matching function for call to 'min(int&, int&)' – thistleknot Oct 22 '20 at 22:42
-
okay, used std::min... now my issue is "error: 'work' was not declared in this scope" – thistleknot Oct 22 '20 at 22:51