Pertanyaan Kemungkinan kekurangan untuk menggunakan JIT dengan R?


Saya baru-baru ini menemukan bahwa seseorang dapat menggunakan JIT (tepat pada waktunya) kompilasi dengan R menggunakan paket kompiler (saya merangkum temuan saya tentang topik ini di posting blog baru-baru ini).

Salah satu pertanyaan yang saya ajukan adalah:

Apakah ada jebakan? kedengarannya terlalu bagus untuk menjadi kenyataan, hanya menempatkan satu baris   kode dan hanya itu.

Setelah melihat-lihat, saya dapat menemukan satu kemungkinan masalah yang berkaitan dengan waktu "start up" untuk JIT. Tetapi apakah ada masalah lain yang harus diperhatikan saat menggunakan JIT?

Saya rasa akan ada beberapa keterbatasan yang harus dilakukan dengan arsitektur lingkungan R, tetapi saya tidak dapat memikirkan ilustrasi sederhana dari masalah di atas kepala saya, saran atau bendera merah akan sangat membantu?


32
2018-04-11 13:20


asal


Jawaban:


Itu rpart contoh yang diberikan di atas, sepertinya tidak lagi menjadi masalah:

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 

Saya juga mencoba sejumlah contoh lain, seperti

  • menumbuhkan vektor;
  • Fungsi yang hanya dibungkus mean

Meskipun saya tidak selalu mendapatkan peningkatan kecepatan, saya tidak pernah mengalami perlambatan yang signifikan.


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

4
2018-05-21 18:34



output dari tes sederhana dengan rpart bisa menjadi saran untuk tidak menggunakan enableJIT dalam SEMUA kasus:

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

Penjelasan apa saja?


11
2018-04-12 19:16



Pada prinsipnya, setelah kode byte dikompilasi dan dimuat, itu harus selalu ditafsirkan setidaknya secepat juru bahasa AST asli. Beberapa kode akan mendapatkan keuntungan dari kecepatan besar, ini biasanya kode dengan banyak operasi skalar dan loop di mana sebagian besar waktu dihabiskan dalam interpretasi R (saya telah melihat contoh dengan 10x speedup tetapi benchmark mikro sewenang-wenang memang bisa mengembang ini sesuai kebutuhan). Beberapa kode akan berjalan pada kecepatan yang sama, ini biasanya kode vektorisasi dengan baik dan karenanya menghabiskan hampir tidak ada waktu dalam interpretasi. Sekarang, kompilasi itu sendiri bisa lambat. Oleh karena itu, compiler just in time sekarang tidak mengkompilasi fungsi ketika ia menebak itu tidak akan melunasi (dan heuristik berubah seiring waktu, ini sudah di 3.4.x). Heuristik tidak selalu menebak dengan benar, jadi mungkin ada situasi ketika kompilasi tidak akan terbayar. Pola problematik yang khas adalah pembuatan kode, modifikasi kode dan manipulasi binding lingkungan yang ditangkap dalam penutupan.

Paket dapat dikompilasi byte pada waktu instalasi sehingga biaya kompilasi tidak dibayar (berulang kali) pada waktu proses, setidaknya untuk kode yang diketahui sebelumnya. Ini sekarang menjadi default dalam versi pengembangan R. Sementara pemuatan kode yang dikompilasi jauh lebih cepat daripada mengkompilasi, dalam beberapa situasi seseorang mungkin memuat kode yang bahkan tidak akan dieksekusi, jadi sebenarnya mungkin ada overhead, tetapi secara keseluruhan pra-kompilasi bermanfaat. Baru-baru ini beberapa parameter GC telah disetel untuk mengurangi biaya pemuatan kode yang tidak akan dieksekusi.

Rekomendasi saya untuk penulis paket adalah menggunakan default (kompilasi just-in-time sekarang secara default dalam versi yang dirilis, kompilasi byte pada waktu instalasi paket sekarang dalam versi pengembangan). Jika Anda menemukan contoh di mana compiler kode byte tidak berfungsi dengan baik, harap kirimkan laporan bug (Saya juga telah melihat kasus yang melibatkan rpartdi versi sebelumnya). Saya akan merekomendasikan terhadap generasi kode dan manipulasi kode dan khususnya dalam loop yang panas. Ini termasuk mendefinisikan penutupan, menghapus dan memasukkan binding dalam lingkungan yang ditangkap oleh penutupan. Tentunya yang seharusnya tidak dilakukan eval(parse(text= dalam hot loop (dan ini sudah buruk tanpa kompilasi byte). Itu selalu lebih baik menggunakan cabang daripada menghasilkan penutupan baru (tanpa cabang) secara dinamis. Juga lebih baik menulis kode dengan loop daripada secara dinamis menghasilkan kode dengan ekspresi besar (tanpa loop). Sekarang dengan compiler byte-code, sekarang sering ok untuk menulis loop yang beroperasi pada skalar di R (kinerja tidak akan seburuk sebelumnya, jadi orang bisa lebih sering melarikan diri tanpa beralih ke C untuk kinerja bagian penting) .


0
2018-03-06 14:20



Lebih jauh ke jawaban sebelumnya, eksperimen menunjukkan masalahnya tidak dengan kompilasi loop, itu dengan kompilasi penutupan. [enableJIT (0) atau enableJIT (1) meninggalkan kode dengan cepat, enableJIT (2) memperlambatnya secara dramatis, dan memungkinkanJIT (3) sedikit lebih cepat dari opsi sebelumnya (tapi masih sangat lambat)]. Juga bertentangan dengan komentar Hansi, cmpfun memperlambat eksekusi ke tingkat yang sama.


-2
2017-10-04 19:18