我注意到在R(版本3.6.1)中,使用较大矩阵进行矩阵乘向量的操作速度明显比Matlab(版本2019b)慢,尽管两种语言都依赖于(同一个?)BLAS库。以下是一个最简示例:
在Matlab中:
n=900;
p=900;
A=reshape(1:(n*p),[n,p]);
x=ones(p,1);
tic()
for id = 1:1000
x = A*x;
end
toc()
R语言中:
n=900
p=900
A=matrix(c(1:(n*p)),nrow=n,ncol=p)
x=rep(1,ncol(A))
t0 <- Sys.time()
for(iter in 1:1000){
x = A%*%x
}
t1 <- Sys.time()
print(t1-t0)
我在使用相同计算机时,在Matlab中运行时间大约为0.05秒,而在R中为3.5秒。有什么原因导致这样的差异吗?
谢谢。
[编辑]: 我添加了下面在C语言中使用CBLAS库进行的类似计算(使用
gcc cblas_dgemv.c -lblas -o cblas_dgemv
进行编译,其中cblas_dgemv.c表示下面的源文件)。我得到的运行时间大约为0.08秒,非常接近使用Matlab(0.05秒)获得的运行时间。我仍在尝试找出R中巨大运行时间的原因(3.5秒)。#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include "cblas.h"
int main(int argc, char **argv)
{
int m=900,adr;
double *A,*x,*y;
struct timeval t0,t1;
/* memory allocation and initialization */
A = (double*)malloc(m*m*sizeof(double));
x = (double*)malloc(m*sizeof(double));
y = (double*)malloc(m*sizeof(double));
for(adr=0;adr<m;adr++) x[adr] = 1.;
for(adr=0;adr<m*m;adr++) A[adr] = adr;
/* main loop */
gettimeofday(&t0, NULL);
for(adr=0;adr<1000;adr++)
cblas_dgemv(CblasColMajor,CblasNoTrans,m,m,1.,A,m,x,1,0.,y,1);
gettimeofday(&t1, NULL);
printf("elapsed time = %.2e seconds\n",(double)(t1.tv_usec-t0.tv_usec)/1000000. + (double)(t1.tv_sec-t0.tv_sec));
/* free memory */
free(A);
free(x);
free(y);
return EXIT_SUCCESS;
}
请注意,在cblas_dgemv例程中,我无法设置y=x。因此,这个C语言计算与上述R和Matlab代码略有不同。但是编译时没有使用优化标志(没有-O3选项),并且我检查了矩阵向量积确实在循环的每次迭代中被调用(执行10倍更多的迭代会导致运行时间增加10倍)。
sessionInfo()
,它会显示“矩阵乘积”的内容是什么? - MrFlickmayHaveNaNOrInf
测试的误报响应,因为在这种情况下,矩阵-向量乘积应该使用内部未优化的3循环算法来完成,这将更慢。实际上,通过设置options(matprod = "internal")
,我得到了超过1分钟的运行时间!此外,根据(https://stat.ethz.ch/R-manual/R-devel/library/base/html/options.html),设置`options(matprod = "blas")应该可以避免这个
mayHaveNaNOrInf`测试。这真是令人沮丧! - RémyA