为什么diag功能这么慢? [在R 3.2.0或更早版本中] [英] Why is the diag function so slow? [in R 3.2.0 or earlier]

查看:72
本文介绍了为什么diag功能这么慢? [在R 3.2.0或更早版本中]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在查看此答案中的基准,并希望将它们与diag(用于不同的答案).不幸的是,diag似乎需要一段时间:

I was looking at the benchmarks in this answer, and wanted to compare them with diag (used in a different answer). Unfortunately, it seems that diag takes ages:

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相似.

Comments: I tested these with identical. I took "cond" from one of the answers to this homework question. Results are similar with a matrix of integers, 1:26 instead of 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"基准测试中使用的相同向量.给这两个计时...

It is just a matrix-subsetting operation, so I don't know why there's so much overhead. Looking inside the function, I see a few checks and then c(m)[v], where v is the same vector used in the "vec" benchmark. Timing these two...

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?

...it seems I have found my culprit. So, the new variation on my question is: Why is there a seemingly unnecessary and very time-consuming c in diag?

推荐答案

摘要

R版本3.2.1 (World-著名的宇航员)diag()已收到更新.讨论移至 r-devel ,其中指出c()会剥离非名称属性,这可能就是将其放置在其中的原因.尽管有些人担心删除c()会在类似矩阵的对象上引起未知的问题,但是Peter Dalgaard发现,"diag()内的c()起作用的唯一情况是M[i,j] != M[(i-1)*m+j] AND c(M)会以列优先顺序将M字符串化,以使M[i,j] == c(M)[(i-1)*m+j]."

As of R version 3.2.1 (World-Famous Astronaut) diag() has received an update. The discussion moved to r-devel where it was noted that c() strips non-name attributes and may have been why it was placed there. While some people worried that removing c() would cause unknown issues on matrix-like objects, Peter Dalgaard found that, "The only case where the c() inside diag() has an effect is where M[i,j] != M[(i-1)*m+j] AND c(M) will stringize M in column-major order, so that M[i,j] == c(M)[(i-1)*m+j]."

卢克·蒂尔尼(Luke Tierney)测试了@Frank对c()的删除,发现它对CRAN或BIOC没有任何影响,因此在第27行.这导致diag()中相对较大的加速.下面是一个速度测试,显示了R 3.2.1版本的diag()的改进.

Luke Tierney tested @Frank 's removal of c(), finding it did not effect anything on CRAN or BIOC and so was implemented to replace c(x)[...] with x[...] on line 27. This leads to relatively large speedups in diag(). Below is a speed test showing the improvement with R 3.2.1's version of diag().

library(microbenchmark)
nc  <- 1e4
set.seed(1)
m <- matrix(sample(letters,nc^2,replace=TRUE), ncol = nc)

    microbenchmark(diagOld(m),diag(m))
    Unit: microseconds
           expr        min          lq        mean      median         uq        max neval
     diagOld(m) 451189.242 526622.2775 545116.5668 531905.5635 540008.704 682223.733   100
        diag(m)    222.563    646.8675    644.7444    714.4575    740.701   1015.459   100

这篇关于为什么diag功能这么慢? [在R 3.2.0或更早版本中]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆