35

私は最近、コンパイラパッケージを使用してRでJIT(ジャストインタイム)コンパイルを使用できることを発見しました(このトピックに関する私の発見を最近のブログ投稿に要約しています)。

私が尋ねられた質問の1つは次のとおりです。

落とし穴はありますか?あまりにも良さそうに聞こえますが、1行のコードを入力するだけです。

周りを見回した後、JITの「起動」時間に関係する可能性のある問題を1つ見つけることができました。しかし、JITを使用する際に注意すべき他の問題はありますか?

Rの環境アーキテクチャに関係するいくつかの制限があると思いますが、頭のてっぺんから問題の簡単な図を考えることはできません。何か提案や危険信号は大いに役立ちますか?

4

4 に答える 4

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

説明はありますか?

于 2012-04-12T19:16:24.570 に答える
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
于 2016-05-21T18:34:34.730 に答える
2

原則として、バイトコードがコンパイルおよびロードされると、少なくとも元のASTインタープリターと同じ速度で常に解釈される必要があります。一部のコードは大幅な高速化の恩恵を受けます。これは通常、多くのスカラー演算とループを備えたコードであり、ほとんどの時間がRの解釈に費やされます(10倍の高速化の例を見てきましたが、任意のマイクロベンチマークで必要に応じてこれを膨らませることができます)。一部のコードは同じ速度で実行されます。これは通常、適切にベクトル化されたコードであるため、解釈にほとんど時間を費やしません。現在、コンパイル自体が遅くなる可能性があります。したがって、ジャストインタイムコンパイラは、それが報われないと推測したときに関数をコンパイルしないようになりました(そして、ヒューリスティックは時間とともに変化します。これはすでに3.4.xにあります)。ヒューリスティックは常にそれを正しく推測するとは限らないため、コンパイルがうまくいかない場合があります。

パッケージはインストール時にバイトコンパイルできるため、少なくとも事前にわかっているコードの場合、実行時にコンパイルコストが(繰り返し)支払われることはありません。これは現在、Rの開発バージョンのデフォルトです。コンパイルされたコードのロードはコンパイルよりもはるかに高速ですが、状況によっては、実行されないコードでもロードされる場合があるため、実際にはオーバーヘッドが発生する可能性がありますが、全体として事前コンパイルは有益です。最近、GCの一部のパラメーターが調整され、実行されないコードのロードコストが削減されました。

パッケージ作成者への私の推奨事項は、デフォルトを使用することです(リリースされたバージョンでは、ジャストインタイムコンパイルがデフォルトでオンになり、開発バージョンでは、パッケージインストール時のバイトコンパイルがオンになります)。バイトコードコンパイラがうまく機能しない例を見つけた場合は、バグレポートを提出してください(rpart以前のバージョンに関係するケースも見ました)。コード生成とコード操作、特にホットループではそうしないことをお勧めします。これには、クロージャの定義、クロージャによってキャプチャされた環境でのバインディングの削除と挿入が含まれます。絶対にすべきではありませんeval(parse(text=ホットループで(そしてこれはバイトコンパイルなしですでに悪いことでした)。新しいクロージャー(ブランチなし)を動的に生成するよりも、ブランチを使用する方が常に優れています。また、(ループなしで)巨大な式を使用してコードを動的に生成するよりも、ループを使用してコードを作成する方が適切です。バイトコードコンパイラを使用すると、Rでスカラーを操作するループを記述できるようになります(パフォーマンスは以前ほど悪くないため、パフォーマンスが重要な部分をCに切り替えることなく回避できることが多くなります) 。

于 2018-03-06T14:20:20.383 に答える
-2

前の答えに加えて、実験は、問題がループのコンパイルにあるのではなく、クロージャのコンパイルにあることを示しています。[enableJIT(0)またはenableJIT(1)はコードを高速のままにし、enableJIT(2)はコードを劇的に遅くし、enableJIT(3)は前のオプションよりわずかに高速です(ただし、非常に低速です)]。また、Hansiのコメントに反して、cmpfunは実行を同程度に遅くします。

于 2013-10-04T19:18:30.907 に答える