我在阅读这个回答中的基准测试结果,想要将它们与另一个答案中使用的diag
进行比较。不幸的是,看起来diag
需要很长时间:
nc <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)
microbenchmark(
diag = diag(m),
cond = m[row(m)==col(m)],
vec = m[(1:nc-1L)*nc+1:nc],
mat = m[cbind(1:nc,1:nc)],
times=10)
评论:我使用 identical
进行了测试。我从一个回答中的“cond”来自这个作业问题。用一个整数矩阵,1:26
代替 letters
结果类似。
结果:
Unit: microseconds
expr min lq mean median uq max neval
diag 604343.469 629819.260 710371.3320 706842.3890 793144.019 837115.504 10
cond 3862039.512 3985784.025 4175724.0390 4186317.5260 4312493.742 4617117.706 10
vec 317.088 329.017 432.9099 350.1005 629.460 651.376 10
mat 272.147 292.953 441.7045 345.9400 637.506 706.860 10
这只是一个矩阵子集操作,所以我不知道为什么会有这么多开销。查看函数内部,我看到了一些检查,然后是 c(m)[v]
,其中 v
是在“vec”基准测试中使用的相同向量。计时这两个操作...
v <- (1:nc-1L)*nc+1:nc
microbenchmark(diaglike=c(m)[v],vec=m[v])
# Unit: microseconds
# expr min lq mean median uq max neval
# diaglike 579224.436 664853.7450 720372.8105 712649.706 767281.5070 931976.707 100
# vec 334.843 339.8365 568.7808 646.799 663.5825 1445.067 100
看起来我找到了罪魁祸首。因此,我的新问题变成了:为什么在diag
中会有一个看似不必要且非常耗时的c
?
c
是因为它可以删除所有属性。您可以在 r-devel 邮件列表上提问。 - Rolanddiag
的不同用法。尝试使用.Internal(diag(1, 2, 2))
来查看它的作用。 - Rolandm[seq.int(1,nc^2,nc+1)]
在我的电脑上是最快的。 - cryo111