且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

R中的快速大矩阵乘法

更新时间:2022-05-09 04:04:20

有很多方法可以解决此问题,具体取决于您的代码,工作量和硬件.

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

  1. 为工作使用***"功能

最简单的方法是使用与t(a)%*% b相同的crossprod(注意-这只是速度的小幅提高)

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. 使用 Rcpp (可能还有 RcppArmadillo ).
  1. Use Rcpp (and likely RcppEigen/RcppArmadillo).

C ++可能会极大地提高您的代码速度.使用线性代数库也可能会进一步帮助(因此,Eigen和Armadillo).但是,这假设您愿意编写一些C ++.

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. 使用更好的后端

在这之后,您将查看BLAS后端,例如OpenBLAS,Atlas等.将它们挂接到R上的情况取决于您的操作系统.如果您使用的是Debian系统(例如Ubuntu),这将非常容易.您可以找到一个演示

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计算

如果您拥有GPU(例如AMD,NVIDIA等),则可以利用其中的许多内核来大大加快计算速度.有一些可能有用的内容,包括 gpuR gputools

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

编辑-解决@jenesaiquoi关于Rcpp利益的评论

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