为什么R diff函数很慢?
使用R中的向量时,为什么R diff函数很慢?,r,diff,benchmarking,R,Diff,Benchmarking,使用R中的向量时,diff函数计算每个值与上一个值之间的差值。从?差异: 如果x是长度n和differences=1的向量,则计算结果等于连续的差值x[(1+lag):n]-x[1:(n-lag)] 但是,当我测试diff函数的执行时间与它们的理论表达式(使用microbenchmark软件包中的microbenchmark函数)时,diff函数的执行速度较慢。这是我的密码: library(microbenchmark) mb.diff1 <- function(n, seed){
diff
函数计算每个值与上一个值之间的差值。从?差异:
如果x
是长度n
和differences=1
的向量,则计算结果等于连续的差值x[(1+lag):n]-x[1:(n-lag)]
但是,当我测试diff
函数的执行时间与它们的理论表达式(使用microbenchmark
软件包中的microbenchmark
函数)时,diff
函数的执行速度较慢。这是我的密码:
library(microbenchmark)
mb.diff1 <- function(n, seed){
set.seed(seed)
vec <- runif(n)
out <- diff(vec)
return(out)
}
mb.diff2 <- function(n, seed){
set.seed(seed)
vec <- runif(n)
out <- vec[2:n]-vec[1:(n-1)]
return(out)
}
times.diff1 <- c()
times.diff2 <- c()
vec.sizes <- c(1e1, 1e2, 1e3, 1e4)
for (n in vec.sizes){
bench <- microbenchmark(
mb.diff1(n,1),
mb.diff2(n,1))
times.median <- aggregate(
bench$time,
by = list(bench$expr),
FUN = median)
times.diff1 <- c(times.diff1, times.median[1,2])
times.diff2 <- c(times.diff2, times.median[2,2])
}
perf.ratio <- times.diff1/times.diff2
names(perf.ratio) <- vec.sizes
print(perf.ratio)
库(微基准)
mb.diff1这里有一些代码可以帮助扩展和说明我在评论中提出的观点
library(microbenchmark)
mb.diff2 <- compiler::cmpfun(function(vec) {
n <- length(vec)
vec[2:n]-vec[1:(n-1L)]
})
times.diff1 <- c()
times.diff2 <- c()
times.diff3 <- c()
vec.sizes <- c(1e1, 1e2, 1e3, 1e4, 1e5)
for (n in vec.sizes) {
set.seed(21)
vec <- runif(n)
bench <- microbenchmark(diff(vec), mb.diff2(vec), diff.default(vec))
times.median <- aggregate(bench$time, by = list(bench$expr), FUN = median)
times.diff1 <- c(times.diff1, times.median[1,2])
times.diff2 <- c(times.diff2, times.median[2,2])
times.diff3 <- c(times.diff3, times.median[3,2])
}
setNames(times.diff1/times.diff2, vec.sizes)
setNames(times.diff1/times.diff3, vec.sizes)
下面是一些代码,可以帮助扩展和说明我在评论中提出的观点
library(microbenchmark)
mb.diff2 <- compiler::cmpfun(function(vec) {
n <- length(vec)
vec[2:n]-vec[1:(n-1L)]
})
times.diff1 <- c()
times.diff2 <- c()
times.diff3 <- c()
vec.sizes <- c(1e1, 1e2, 1e3, 1e4, 1e5)
for (n in vec.sizes) {
set.seed(21)
vec <- runif(n)
bench <- microbenchmark(diff(vec), mb.diff2(vec), diff.default(vec))
times.median <- aggregate(bench$time, by = list(bench$expr), FUN = median)
times.diff1 <- c(times.diff1, times.median[1,2])
times.diff2 <- c(times.diff2, times.median[2,2])
times.diff3 <- c(times.diff3, times.median[3,2])
}
setNames(times.diff1/times.diff2, vec.sizes)
setNames(times.diff1/times.diff3, vec.sizes)
R-3.1.2超过2岁。您的计时包括生成一个随机向量,因此您没有隔离您所询问的差异。使用只调用diff
和vec[]
的简化函数,diff
在运行R-3.3.2的Ubuntu 14.04机器上运行得更快diff
也是通用的,因此方法调度会有一些成本。直接调用diff.default
更快(一般不建议这样做)。另外diff.default
将其输入转换为矩阵并进行一些检查。谢谢@JoshuaUlrich,我将Ubuntu更新为16.04并安装了R3.3.2。我还在函数外部调用了runif,以便可以测量diff函数的实际执行时间。尽管如此,对于大于1e4的向量,diff的性能稍好一些。我认为vec[]对于小尺寸的性能更好是由于检查。非常感谢。R-3.1.2已经超过2岁了。您的计时包括生成一个随机向量,因此您没有隔离您所询问的差异。使用只调用diff
和vec[]
的简化函数,diff
在运行R-3.3.2的Ubuntu 14.04机器上运行得更快diff
也是通用的,因此方法调度会有一些成本。直接调用diff.default
更快(一般不建议这样做)。另外diff.default
将其输入转换为矩阵并进行一些检查。谢谢@JoshuaUlrich,我将Ubuntu更新为16.04并安装了R3.3.2。我还在函数外部调用了runif,以便可以测量diff函数的实际执行时间。尽管如此,对于大于1e4的向量,diff的性能稍好一些。我认为vec[]对于小尺寸的性能更好是由于检查。非常感谢你。