我已经学习了R一段时间了,并且已经为像我这样的编程类型提出了很多建议来进行矢量化操作.作为一名程序员,我对它为何/如何更快感兴趣.一个例子:
n = 10^7
# populate with random nos
v=runif(n)
system.time({vv<-v*v; m<-mean(vv)}); m
system.time({for(i in 1:length(v)) { vv[i]<-v[i]*v[i] }; m<-mean(vv)}); m
Run Code Online (Sandbox Code Playgroud)
这给了
user system elapsed
0.04 0.01 0.07
[1] 0.3332091
user system elapsed
36.68 0.02 36.69
[1] 0.3332091
Run Code Online (Sandbox Code Playgroud)
最明显的事情是我们正在运行本机代码,即从C或C++编译的机器代码,而不是解释代码,如两个示例之间的用户时间的巨大差异(大约3个数量级)所示.但还有什么事吗?例如,R会这样做:
狡猾的原生数据结构,例如存储稀疏向量或矩阵的巧妙方法,以便我们只在需要时进行乘法运算?
惰性评估(例如,在矩阵乘法上)不会在需要时评估单元格.
并行处理.
还有别的.
为了测试是否存在一些稀疏向量优化,我尝试使用差异向量内容进行点积
# populate with random nos
v<-runif(n)
system.time({m<-v%*%v/n}); m
# populate with runs of 1 followed by 99 0s
v <-rep(rep(c(1,rep(0,99)),n/100))
system.time({m<-v%*%v/n}); m
# populate with 0s
v <-rep(0,n)
system.time({m<-v%*%v/n}); m
Run Code Online (Sandbox Code Playgroud)
然而,时间上没有显着差异(大约0.09已过去)
(Matlab的类似问题:为什么矢量化代码比MATLAB中的循环运行得更快?)
您在两个示例中都运行了解释代码和本机代码.不同之处在于,在第二个阶段,您在R级别进行循环,导致需要解释的更多函数调用,然后调用C代码.在你的第一个例子中,循环发生在已编译的代码中,因此R的解释要少得多,R代码调用少得多,编译代码调用也少得多.