为什么R diff函数很慢?

为什么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){

使用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){
  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[]对于小尺寸的性能更好是由于检查。非常感谢你。