首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.Primitive和.Internal的性能

.Primitive和.Internal的性能
EN

Stack Overflow用户
提问于 2015-05-12 14:45:26
回答 2查看 343关注 0票数 14

我通过从流程中删除一个步骤来进行一些优化:

代码语言:javascript
复制
> library(microbenchmark)
> microbenchmark(paste0("this","and","that"))
Unit: microseconds
                          expr   min    lq    mean median    uq    max neval
 paste0("this", "and", "that") 2.026 2.027 3.50933  2.431 2.837 34.038   100

> microbenchmark(.Internal(paste0(list("this","and","that"),NULL)))
Unit: microseconds
                                                 expr   min    lq    mean median    uq    max neval
 .Internal(paste0(list("this", "and", "that"), NULL)) 1.216 1.621 2.77596  2.026 2.027 43.764   100

到目前一切尚好。

但是当我注意到list被定义为

代码语言:javascript
复制
function (...)  .Primitive("list")

我试着进一步“简化”

代码语言:javascript
复制
> microbenchmark(.Internal(paste0(.Primitive("list")("this","and","that"),NULL)))
Unit: microseconds
                                                               expr   min    lq    mean median    uq    max neval
 .Internal(paste0(.Primitive("list")("this", "and", "that"), NULL)) 3.241 3.242 4.66433  3.647 3.648 80.638   100

时间越长越好!

我的猜测是,处理字符串"list"是问题的根源,并且在函数list的实际调用中处理方法不同。

但是怎么做呢?

免责声明:我知道这对可读性的伤害大于对性能的帮助。这仅适用于一些非常简单的函数,这些函数不会更改,而且经常使用,因此即使付出了这样的代价,也需要轻微的性能问题。

编辑回应乔希·奥布赖恩的评论:

我不知道这说明了他的想法,但是

代码语言:javascript
复制
library(compiler)
ff <- compile(function(...){.Internal(paste0(.Primitive("list")("this","and","that"),NULL))})
ff2 <- compile(function(...){.Internal(paste0(list("this","and","that"),NULL))})
microbenchmark(eval(ff),eval(ff2),times=10000)
> microbenchmark(eval(ff2),eval(ff),times=10000)
Unit: microseconds
      expr   min    lq     mean median    uq     max neval
 eval(ff2) 1.621 2.026 2.356761  2.026 2.431 144.257 10000
  eval(ff) 1.621 2.026 2.455913  2.026 2.431  89.148 10000

看一看微基准测试生成的图表(只需用plot()包起来亲眼看到)运行了那么多次,看起来它们的性能在统计上是相同的,尽管“最大”值看起来像ff2的最坏情况。我不知道该怎么做,但也许这会对某人有所帮助。所有这些基本上都表明它们编译成相同的代码。这是否意味着他的评论就是答案?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-05-12 21:15:06

.Internal(paste0(.Primitive("list")("this","and","that"),NULL))速度慢的原因似乎是Josh O'Brien猜测的结果。直接调用.Primitive("list")会带来一些额外的开销。

您可以通过一个简单的例子看到效果:

代码语言:javascript
复制
require(compiler)
pl <- cmpfun({.Primitive("list")})
microbenchmark(list(), .Primitive("list")(), pl())
# Unit: nanoseconds
#                  expr  min     lq median     uq   max neval
#                list()   63   98.0  112.0  140.5   529   100
#  .Primitive("list")() 4243 4391.5 4486.5 4606.0 16077   100
#                  pl()   79  135.5  148.0  175.5 39108   100

也就是说,您将无法从R提示符中提高.Primitive.Internal的速度。它们都是C代码的入口点。

没有理由尝试用.Internal替换对.Internal的调用。这是递归的,因为.Internal本身就是一个原语。

代码语言:javascript
复制
> .Internal
function (call)  .Primitive(".Internal")

如果你试图“直接”调用.Internal,你会得到同样的慢.如果编译“直接”调用,也会出现类似的“加速比”。

代码语言:javascript
复制
Internal. <- function() .Internal(paste0(list("this","and","that"),NULL))
Primitive. <- function() .Primitive(".Internal")(paste0("this","and","that"),NULL)
cPrimitive. <- cmpfun({Primitive.})
microbenchmark(Internal., Primitive., cPrimitive., times=1e4)
# Unit: nanoseconds
#         expr min lq median uq  max neval
#    Internal.  26 27     27 28 1057 10000
#   Primitive.  28 32     32 33 2526 10000
#  cPrimitive.  26 27     27 27 1706 10000
票数 11
EN

Stack Overflow用户

发布于 2015-05-12 17:41:27

R解释器对常见函数进行了硬编码优化,这比字节编译更深入:

代码语言:javascript
复制
> list2 <- list
> list3 <- cmpfun(list2)
> microbenchmark(
+   list(1,2),
+   list2(1,2),
+   list3(1,2)
+ )
Unit: nanoseconds
        expr min    lq    mean median    uq   max neval
  list(1, 2) 576 620.5  654.53  640.0 675.5   941   100
 list2(1, 2) 619 702.0 1123.43  728.0 761.0 39045   100
 list3(1, 2) 617 683.0  735.83  715.5 759.0  1964   100

以下是SEXP的样子。注意“列表”上的元数据

代码语言:javascript
复制
> .Internal(inspect(quote(list(1,2))))
@23b0ed0 06 LANGSXP g0c0 [NAM(2)] 
  @1ed8f48 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] "list" (has value)
  @2c7adf8 14 REALSXP g0c1 [] (len=1, tl=0) 1
  @2c7adc8 14 REALSXP g0c1 [] (len=1, tl=0) 2

list2缺少一些元数据:

代码语言:javascript
复制
> list2 <- list
> .Internal(inspect(quote(list2(1,2))))
@23b1578 06 LANGSXP g0c0 [NAM(2)] 
  @23b0a70 01 SYMSXP g0c0 [] "list2"
  @2c7ad08 14 REALSXP g0c1 [] (len=1, tl=0) 1
  @2c7acd8 14 REALSXP g0c1 [] (len=1, tl=0) 2

.Primitive("list")是一个更复杂的表达式:

代码语言:javascript
复制
> .Internal(inspect(quote(.Primitive("list")(1,2))))
@297e748 06 LANGSXP g0c0 [NAM(2)] 
  @297d9a0 06 LANGSXP g0c0 [] 
    @1ec4530 01 SYMSXP g1c0 [MARK,LCK,gp=0x4000] ".Primitive" (has value)
    @2c7a888 16 STRSXP g0c1 [] (len=1, tl=0)
      @1ed5588 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "list"
  @2c7a858 14 REALSXP g0c1 [] (len=1, tl=0) 1
  @2c7a828 14 REALSXP g0c1 [] (len=1, tl=0) 2
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30194281

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档