furrr パッケージで ggplot のリストの表示を高速化する

カテゴリ: r

はじめに

前に hoxo-m/pforeach パッケージを利用して, ggplot のリストを並列処理し,描写の高速化を行いました.

しかし, hoxo-m/pforeach パッケージの霊圧が消えてしまったので, furrr パッケージを試してみることにしました.

https://github.com/DavisVaughan/furrr

furrr パッケージは purrr パッケージと似た感覚で操作でき,事前に plan(multiprocess) としておくだけで並列化してくれる化け物.関数名も future_map など, purrr パッケージの関数名に future_ という prefix がつくだけで覚えやすい. plan(sequential) すれば並列化を解除できます.

multiprocesssequential 以外にも様々な strategy が選べますが,詳しくは, ?future::plan を見ましょう.

実装とテスト

前回 pforeach::pforeach() 関数を用いて実装した print_gglist()furrr::future_map() を用いて再実装しました. strategy 引数と ... 引数で plan() をコントロールできます.

library(pacman)
p_load(furrr, ggplot2, grid, magrittr, purrr)

print_gglist <- function(x, strategy = multiprocess, ...) {
  current_plan <- plan()
  plan(strategy, ...)
  future_map(x, ~ ggplot_gtable(ggplot_build(.x))) %>%
    walk(function(x) { # 順次出力
        grid.newpage()
        grid.draw(x)
      })
  plan(current_plan)
  invisible(x)
}

g <- ggplot(iris, aes(Sepal.Length)) + geom_histogram()
print_gglist(list(g, g))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

ベンチマーク

p_load(microbenchmark)
g_list <- rep(list(g), 10)
bench <- microbenchmark(
  'single thread' = walk(g_list, print),
  'multi thread' = print_gglist(g_list)
)
bench
plot(bench)
## Unit: milliseconds
##           expr      min       lq     mean   median       uq      max neval
##  single thread 774.9664 846.9223 911.0551 896.0701 952.7812 1303.653   100
##   multi thread 572.6841 610.1190 667.7990 643.0180 693.4269 1216.081   100

うまくいきましたね!!

感想

furrr パッケージは簡単,便利!!