在 R 中的大向量中设置元素

Setting elements in a big vector in R

我在 R 中使用向量,存储 bigz 对象 (GMP package)。当向量不是太大(最多 200 个元素)时它工作正常,但是当向量增长时,性能会急剧下降。

为了找到瓶颈所在,我使用 profvis 库执行我的程序,我发现问题出在下一段代码:

res <- as.bigz(rep(0, length(resT))) #resT is a list of bigz of length 600
res[[1]] <- sum.bigz(a_bigz_elem, another_bigz_elem)
i <- 1
while (i <= length(resT) - 1) {
    res[[i + 1]] <- sum.bigz(resT[[i + 1]], resE[[i + 1]])
    i <- i + 1
}

更具体地说,在第 5 行(列表中的元素赋值)。

我知道这个解决方案比增长向量更好,即 res <- c(res, sum.bigz(resT[[i + 1]], resE[[i + 1]])),但我很确定有更有效的方法来完成分配。

我已经阅读了 SO 中的相关 post 和 Advanced R 参考文档,但没有任何提高我的表现的方法。知道如何改进吗?

res <- as.bigz(rep(0, length(resT))) #resT is a list of bigz of length 600

不是创建list。当您将其更改为:

res <- as.list(as.bigz(rep(0, length(resT))))

您创建了一个列表,执行时间应该会减少。

一个可重现的例子如下:

library(gmp)

resT  <- as.list(urand.bigz(600, seed=0))
resE  <- as.list(urand.bigz(600, seed=1))
a_bigz_elem  <- resT[[1]]
another_bigz_elem  <- resE[[1]]

res <- as.list(as.bigz(rep(0, length(resT))))
res[[1]] <- sum.bigz(a_bigz_elem, another_bigz_elem)
i <- 1
while (i <= length(resT) - 1) {
  res[[i + 1]] <- sum.bigz(resT[[i + 1]], resE[[i + 1]])
  i <- i + 1
}

这里有一个简洁的方法,比@GKi的方案效率高一点:

mapply(sum.bigz, resT, resE, SIMPLIFY = FALSE)

基准:

library(gmp)

resT_list  <- as.list(urand.bigz(1000, seed=0))
resE_list  <- as.list(urand.bigz(1000, seed=1))

f1 <- function(){
  a_bigz_elem  <- resT_list[[1]]
  another_bigz_elem  <- resE_list[[1]]
  res <- as.list(as.bigz(rep(0, length(resT_list))))
  res[[1]] <- sum.bigz(a_bigz_elem, another_bigz_elem)
  i <- 1
  while (i <= length(resT_list) - 1) {
    res[[i + 1]] <- sum.bigz(resT_list[[i + 1]], resE_list[[i + 1]])
    i <- i + 1
  }
  res
}

f2 <- function(){
  mapply(sum.bigz, resT_list, resE_list, SIMPLIFY = FALSE)
}

library(microbenchmark)
microbenchmark(
  f1 = f1(),
  f2 = f2(),
  times = 10
)
# Unit: milliseconds
# expr      min       lq     mean   median       uq      max neval cld
#   f1 15.27488 16.48450 19.84019 17.51613 25.25338 28.10120    10   b
#   f2 11.83838 12.21875 13.30705 12.87080 14.37143 15.75504    10  a