Memparalelkan kode di R dalam beberapa menit

Jika Anda yakin dengan stereotip tersebut, maka bahasa R adalah sesuatu yang sangat khusus untuk statistik dan pembelajaran mesin. Stereotipe kedua adalah bahwa kode R murni tidak terlalu cepat: pertama, karena diinterpretasikan, dan kedua, karena dijalankan secara berurutan. Tentu saja, stereotip memiliki semacam hubungan dengan kenyataan, jika tidak, stereotip tidak akan ada, tetapi itulah mengapa stereotip adalah stereotip, yang memberikan gambaran yang sangat disederhanakan tentang dunia di mana banyak detail yang hilang. Secara khusus, hari ini saya ingin membagikan cara yang sangat sederhana untuk menambahkan paralelisme ke R dan menggandakan mempercepat eksekusi kode yang ada tanpa harus membuat perubahan besar apa pun padanya. Semua ini selesai hanya dalam beberapa menit.



Katakanlah kita memiliki matriks atau tabel data yang berisi sejumlah baris dan kolom, dan kita ingin melakukan beberapa jenis penghitungan yang sama untuk setiap baris. Misalnya, hitung jumlah kuadrat dari nilainya. Adalah logis untuk memindahkan kalkulasi ke dalam fungsi dan memanggilnya untuk setiap baris.



Data awal:



a <- matrix(rnorm(500000, mean=0, sd=2), 100000, 50)


Fungsi:



sum.of.squares <- function(n) {
  n_sq <- sapply(n, function(x) x^2)
  sum(n_sq)
}


Anda cukup mengulang garis dan menerapkan fungsi ini ke masing-masing baris, tetapi ini bukan cara yang paling direkomendasikan untuk R. Perhitungan untuk setiap baris akan dilakukan secara berurutan, semua perhitungan akan dilakukan pada inti yang sama. Kode semacam ini sangat tidak efisien. Untuk berjaga-jaga, mari tulis opsi ini dan ukur waktu eksekusi:



b <- vector()
for(i in 1:dim(a)[1]) {
  b[i] <- sum.of.squares(a[i,])
}


Kami mengukur waktu eksekusi:



b <- vector()
start_time <- Sys.time()
for(i in 1:dim(a)[1]) {
  b[i] <- sum.of.squares(a[i,])
}
timediff <- difftime(Sys.time(), start_time)
cat(" : ", timediff, units(timediff))


Kita mendapatkan:



 :  4.474074 secs


Kami akan menggunakan waktu ini sebagai titik awal untuk membandingkan dengan metode lain.



. R apply(). , : 1, 2. , . – sapply(), . – . , apply() :



b <- apply(a, 1, function(x) sum.of.squares(x))


, . , , :



start_time <- Sys.time()
b <- apply(a, 1, function(x) sum.of.squares(x))
timediff <- difftime(Sys.time(),start_time)
cat(" : ", timediff, units(timediff))


:



 : 4.484046 secs


, . : , .



, , R , . : apply(), , . , , . , apply(). apply() by(), eapply(), lapply(), Map(), .mapply(), mapply(), replicate(), sapply(), tapply(), vapply(). , future_apply:



install.packages("future.apply") 


– . , :



library("future.apply")
plan(multiprocess)


. , . future::plan(). , , apply "future_". :



b <- future_apply(a, 1, function(x) sum.of.squares(x))


:



start_time <- Sys.time()
b <- future_apply(a, 1, function(x) sum.of.squares(x))
timediff <- difftime(Sys.time(),start_time)
cat(" : ", timediff, units(timediff))


:



 :  1.283569 secs


Intel Core i7-8750H 12 . 12-, .



. , , , , , . , , future_sapply, . . – . , , , (a <- data.frame(a)), , 8 . .



Nah, itu saja. Caranya cukup sederhana. Bagi saya, ketika saya mengetahui tentang dia, itu hanya berkah. Apakah benar R saat ini tidak mendukung komputasi paralel? Bergantung pada sudut pandang tentang masalah ini, pada tingkat keparahan pernyataannya. Tetapi dalam arti tertentu, kita dapat berasumsi bahwa itu memang mendukung.




All Articles