Help us understand the problem. What is going on with this article?

Rのforは遅いと誰が言った? (data.frameの高速演算には列ごとならlapply、行ごとならReduceを使おうの補足)

More than 1 year has passed since last update.

先日の

data.frameの高速演算には列ごとならlapply、行ごとならReduceを使おう

がTwitter上で予想以上のLike, Retweetを頂いております。
軽い気持ちで書いた記事だったのでもう少し踏み込みます。

先日の記事について

matrixを行ごとの和を求める場合、100行100列なら

rowSums < apply < for

であることを示しました。
また、data.frameの場合は、

Reduce < rowSums < apply < for

であることを示しました。

そして、rowSumsやapplyはmatrixに特化しており、data.frameをmatrixに変換するオーバーヘッドが発生するのに対し、Reduceはdata.frameをそのまま扱うことが可能なことが一因と説明し、データごとに最適な計算を考えましょうと訴えました。

しかし、以下の疑問が浮いてきました。

  • Reduceに入力された変数は、要素を順々に処理するので、行が増えた場合、rowSumsやapplyより遅くなるのでは?
  • forならdata.frameに最適なコードを記述すれば、matrix用の関数(rowSumsやapply)より速くなってもいいのでは?
    • しかもイマドキ(R > 3.4.0)ではJITがforも加速する

実験

先日のコードの修正したものをもとに、100行100列のdata.frameを始めとして、100行10万列までテストデータを巨大化しつつ、ベンチマークします。

library(microbenchmark) # ベンチマークようのパッケージ
set.seed(123) # 乱数を固定
nr <- 100 # テストデータの行数
nc <- 1e+2 # テストデータの列数

x <- as.data.frame(matrix(runif(nr*nc), nr, nc))
# テストデータの生成

plot(microbenchmark(
  Reduce = Reduce(`+`, x),
  rowSums = rowSums(x),
  apply = apply(x, 1, sum),
  "for" = {
      y <- numeric(ncol(x2))
      for(i in 1:nrow(x2)) y <- y + x[[i]]
      y
  }
), xlab = '', ylab = 'nano sec', log = 'y')

100行100列

000005.png

Reduce速い!
forおっそ!

100行1,000列

000009.png

Reduce速い!
やはりforおっそ!

100行10,000列

00000b.png

Reduce速いけど、あ、あれ?! for頑張ってる?

100行100,000列

00000d.png

おおお?! forはええ!!

結論

先日結論した通りデータに最適なコードはやはり大事。
data.frameの行の和を求める場合

Reduce < rowSums < apply

の関係は少なくとも100行100列から100行10万列までは変わらない。

forは列数(すなわち繰り返し回数)が少ない時は遅いが、多い時は最速にすらなりうる(最適化は大前提として)。
多分、forの場合、繰り返し回数が少ないとJITコンパイルの所要時間が相対的に長いのだと思う。

おまけ

100行100,000列のmatrixもforが速い!!

image.png

Enjoy!!

Atsushi776
EPMAデータをより効果的に扱うべくRを使い始めた。 専門は変成岩岩石学。
https://blog.atusy.net
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした