将RIT与R一起使用可能存在的缺点?

问题描述 投票:34回答:4

我最近发现可以使用编译器包使用JIT(及时)编译R(我总结了我在a recent blog post中关于这个主题的发现)。

我被问到的一个问题是:

有任何陷阱吗?这听起来好得令人难以置信,只需输入一行代码即可。

环顾四周后,我发现一个可能的问题与JIT的“启动”时间有关。但是在使用JIT时还有其他问题需要注意吗?

我想与R的环境架构有一些限制,但我想不出一个简单的问题,我的头脑,任何建议或危险信号将有很大的帮助?

performance r compiler-construction jit
4个回答
4
投票

上面给出的rpart示例,似乎不再是一个问题:

library("rpart")
fo = function() {
  for(i in 1:500){
    rpart(Kyphosis ~ Age + Number + Start, data=kyphosis)
  }
}    system.time(fo())
#   user  system elapsed 
#  1.212   0.000   1.206 
compiler::enableJIT(3)
# [1] 3
system.time(fo())
#   user  system elapsed 
#  1.212   0.000   1.210 

我还尝试过其他一些例子,例如

  • 生长矢量;
  • 这个函数只是mean的包装器

虽然我并不总是加速,但我从来没有经历过显着的减速。


R> sessionInfo()
R version 3.3.0 (2016-05-03)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 16.04 LTS

11
投票

使用rpart进行简单测试的输出可能是在所有情况下都不使用enableJIT的建议:

library(rpart)
fo <- function() for(i in 1:500){rpart(Kyphosis ~ Age + Number + Start, data=kyphosis)}
system.time(fo())
#User      System verstrichen 
#2.11        0.00        2.11 

require(compiler)
enableJIT(3)
system.time(fo())
#User      System verstrichen 
#35.46        0.00       35.60

任何解释?


1
投票

原则上,一旦编译和加载了字节码,它应该始终被解释为至少与原始AST解释器一样快。一些代码将受益于大的加速,这通常是具有大量标量操作和循环的代码,其中大部分时间用于R解释(我已经看到10x加速的示例,但是任意微基准确实可以根据需要对其进行充气)。一些代码将以相同的速度运行,这通常是代码很好地矢量化,因此几乎没有时间进行解释。现在,编译本身可能很慢。因此,即时编译器现在不会编译函数,因为它猜测它不会得到回报(并且启发式随时间变化,这已经在3.4.x中)。启发式并不总是猜对了,所以可能存在编译无法获得回报的情况。典型的有问题的模式是代码生成,代码修改和对闭包中捕获的环境的绑定的操纵。

软件包可以在安装时进行字节编译,这样就不会在运行时(重复)支付编译成本,至少对于提前知道的代码。现在这是R的开发版本中的默认值。虽然加载编译代码比编译它快得多,但在某些情况下,可能正在加载甚至不会执行的代码,因此实际上可能存在开销,但总体而言预编译是有益的。最近调整了GC的一些参数以降低加载不会执行的代码的成本。

我对包编写器的建议是使用默认值(默认情况下,在发布版本中,即时编译现已开启,包安装时的字节编译现在在开发版本中)。如果您找到字节码编译器效果不佳的示例,请提交错误报告(我在早期版本中也看到了涉及rpart的案例)。我建议不要使用代码生成和代码操作,特别是在热循环中。这包括在闭包捕获的环境中定义闭包,删除和插入绑定。绝对不应该在热循环中执行eval(parse(text=(这已经很糟糕,没有字节编译)。使用分支总是比动态生成新的闭包(没有分支)更好。使用循环编写代码比使用大表达式(没有循环)动态生成代码更好。现在使用字节码编译器,现在通常可以编写在R中的标量上运行的循环(性能不会像以前那样糟糕,所以人们可以更频繁地离开而无需切换到C以获得性能关键部分) 。


-2
投票

继前面的答案之后,实验表明问题不在于循环的编译,而在于闭包的编译。 [enableJIT(0)或enableJIT(1)保持代码快速,enableJIT(2)显着减慢代码,enableJIT(3)比前一个选项略快(但仍然非常慢)]。与Hansi的评论相反,cmpfun在相似程度上减缓了执行速度。

© www.soinside.com 2019 - 2024. All rights reserved.