performance - 在 R 中未命名(变为命名)时对向量的分配非常慢

标签 performance r vector

我的代码遇到了性能障碍,我可以在此代码段中重现该问题

rm (z)
z = c()
system.time({z[as.character(1:10^5)] = T})
user  system elapsed 
48.716   0.023  48.738 

我试图预先分配 z
z = logical(10^5)

但这没什么区别。
然后我预先分配了名称
names(z) = character(10^5)

仍然没有速度差异。
system.time({z[as.character(1:10^5)] = T})
user  system elapsed 
50.345   0.035  50.381 

如果我重复测试,无论是否进行预分配,速度都会恢复到合理水平(快 100 倍以上)。
system.time({z[as.character(1:10^5)] = T})
user  system elapsed 
0.037   0.001   0.039 

最后我找到了一个不太好的解决方法:
names(z) = as.character(1:10^5)
system.time({z[as.character(1:10^5)] = T})
user  system elapsed 
0.035   0.001   0.035 

要回到缓慢的时间,您可以 rm(z) 并以不同的方式初始化它,但即使将名称改回其他名称也会使时间变回缓慢。
我是说这不是一个很好的解决方法,因为我不明白它为什么有效,所以很难概括到我事先不知道名称的实际用例。当然,考虑到两个数量级的差异,有人怀疑涉及一些非矢量化或解释器繁重的操作,但您可以看到我的代码是无循环的,并且没有调用我能想到的任何解释代码。然后尝试使用较小的向量,我发现执行时间的增长速度比线性增长快得多,可能是二次的,这指向其他东西。问题是这种速度行为的原因是什么以及使它更快的解决方案是什么。

平台是带有 R 15.2 的 OS X mt lion。谢谢

安东尼奥

最佳答案

我可以推测发生了什么,因为下面的时间似乎符合我的假设。

以下是三个相关的运行:

# run 1 - slow
rm (z)
n <- 3*10^4
z <- vector("logical", n)
system.time({
z[as.character(1:n)] <- T
})
#    user  system elapsed 
#    5.08    0.00    5.10

# run 2 - fast
rm (z)
n <- 3*10^4
z <- vector("logical", n)
system.time({
names(z) <- as.character(1:n)
z[as.character(1:n)] <- T
})
#    user  system elapsed 
#    0.03    0.00    0.03 

# run 3 - slow again
rm (z)
n <- 3*10^4
z <- vector("logical", n)
system.time({
for (i in 1:n) names(z)[i] <- as.character(i)
z[as.character(1:n)] <- T
})
#    user  system elapsed 
#    6.10    0.00    6.09 

运行 #3 是我认为在后台发生的事情,或者至少是这样的事情:在按名称进行分配时,R 一次查找一个名称,如果没有找到,则在最后分配它名称向量。一次做这件事就是杀死它...

您还指出按以下方式预先分配名称 names(z) <- character(1:n)没有帮助。呵呵,看到了character(1:n)返回 ""所以它没有像你想象的那样设置名称。毫不奇怪,它没有多大帮助。您打算使用 as.character而不是 character .

最后,您问有什么解决方案可以加快速度?我会说你已经找到了一个(运行#2)。你也可以这样做:
keys   <- as.character(1:n)
values <- rep(T, n)
z <- setNames(values, keys)

关于performance - 在 R 中未命名(变为命名)时对向量的分配非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16615401/

相关文章:

sql-server - 为什么 UPDATE 比 SELECT 花费的时间长得多?

c++ - 如何使用 vector 修改结构体C++

c# - 通用扩展方法比非通用扩展方法慢

javascript - 在javascript中从剪贴板抓取部分数据

python - 与用零替换现有数组的值相比,为什么 Numpy 创建零数组要快得多?

r - R 中 prcomp 对象的子集

r - 在 R 中的文本文件中输出 J48 树

r - Shiny 的应用程序在控制台中提交代码时运行,但在选择“运行应用程序”按钮时不运行

c++ - 提供错误值的 vector 迭代器

c++ - 多线程安全插入 vector 的最快方法是什么?