fast large matrix multiplication in R

后端 未结 1 1429
谎友^
谎友^ 2020-12-03 02:13

I have two matrices in R that I want to multiply:

a = matrix(rnorm(20*10000, mean=0, sd=5), 20, 10000)
b = matrix(rnorm(20*10000, mean=0, sd=5), 20, 10000)
t         


        
相关标签:
1条回答
  • 2020-12-03 02:18

    There are many ways to approach this depending upon your code, effort, and hardware.

    1. Use the 'best' function for the job

    The simplest is to use crossprod which is the same as t(a)%*% b (Note - this will only be a small increase in speed)

    crossprod(a,b) 
    
    1. Use Rcpp (and likely RcppEigen/RcppArmadillo).

    C++ will likely greater increase the speed of your code. Using linear algebra libraries will likely also help this further (hence Eigen and Armadillo). This however assumes you are willing to write some C++.

    1. Use a better backend

    After this point you are looking at BLAS backends such as OpenBLAS, Atlas, etc. Hooking these up to R varies depending upon your OS. It is quite easy if you are using a Debian system like Ubuntu. You can find a demo here. These can sometimes be leveraged further by libraries such as Armadillo and Eigen.

    1. GPU Computing

    If you have a GPU (e.g. AMD, NVIDIA, etc.) you can leverage the many cores within to greatly speed up your computations. There are a few that could be useful including gpuR, gputools, and gmatrix

    EDIT - to address @jenesaiquoi comment on benefit of Rcpp

    test.cpp

    // [[Rcpp::depends(RcppArmadillo, RcppEigen)]]
    
    #include <RcppArmadillo.h>
    #include <RcppEigen.h>
    
    // [[Rcpp::export]]
    SEXP armaMatMult(arma::mat A, arma::mat B){
        arma::mat C = A * B;
    
        return Rcpp::wrap(C);
    }
    
    // [[Rcpp::export]]
    SEXP eigenMatMult(Eigen::MatrixXd A, Eigen::MatrixXd B){
        Eigen::MatrixXd C = A * B;
    
        return Rcpp::wrap(C);
    }
    
    // [[Rcpp::export]]
    SEXP eigenMapMatMult(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
        Eigen::MatrixXd C = A * B;
    
        return Rcpp::wrap(C);
    }
    

    test.R

    library(Rcpp)
    
    A <- matrix(rnorm(10000), 100, 100)
    B <- matrix(rnorm(10000), 100, 100)
    
    library(microbenchmark)
    sourceCpp("test.cpp")
    microbenchmark(A%*%B, armaMatMult(A, B), eigenMatMult(A, B), eigenMapMatMult(A, B))
    
    Unit: microseconds
                      expr     min       lq     mean   median       uq      max neval
                   A %*% B 885.846 892.1035 933.7457 901.1010 938.9255 1411.647   100
         armaMatMult(A, B) 846.688 857.6320 915.0717 866.2265 893.7790 1421.557   100
        eigenMatMult(A, B) 205.978 208.1295 233.1882 217.0310 229.4730  369.369   100
     eigenMapMatMult(A, B) 192.366 194.9835 207.1035 197.5405 205.2550  366.945   100
    
    0 讨论(0)
提交回复
热议问题