1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

tikzDeviceの書き出しを高速化する

Posted at

問題提議

tikzDeviceはRのグラフをTeXのグラフィックフレームワークであるTikZ形式を出力するパッケージです。
基本的には普通の画像形式(pdf,pngなど)のデバイスを指定するかわりにtikz()を使用するだけで.tex形式で書き出しができますが、書き出しが非常に遅いという問題点があります。

以下はpdf,png,tikzで10000個の点をプロットした結果です(@MacBook Air Early 2015)。

(bash)

$ time Rscript -e "library(tikzDevice); pdf('out'); plot(1:10000); dev.off();"
real    0m0.529s
$ time Rscript -e "library(tikzDevice); png('out'); plot(1:10000); dev.off();"
real    0m0.604s
$ time Rscript -e "library(tikzDevice); tikz('out'); plot(1:10000); dev.off();"
real    0m3.884s

このように、TikZにするだけで約7倍も時間がかかってしまいます。

原因

書き出しが遅くなる理由は、tikz関数内でTeXで使用される文字や文字列の幅を実行時にpdflatexを使用してチェックするためです。
対話形式で実行時に表示されるログを見ると以下のようなファイルが処理されることが確認できます。

(R)
> plot(1:10000)
Measuring dimensions of: m
Running command: '/path/to/pdflatex' ... '/var/.../tikzDevice15ad45b476a03/tikzStringWidthCalc.tex'
Measuring dimensions of: 0
Running command: '/path/to/pdflatex' ... '/var/.../tikzDevice15ad42d8119c6/tikzStringWidthCalc.tex'
Measuring dimensions of: \char77
Running command: '/path/to/pdflatex' ... '/var/.../tikzDevice15ad476c32d80/tikzStringWidthCalc.tex'
Measuring dimensions of: 2000
Running command: '/path/to/pdflatex' ... '/var/.../tikzDevice15ad47e06b6a/tikzStringWidthCalc.tex'
...

対策1

tikzDeviceではこの計測結果をファイルにキャッシュするためのtikzMetricsDictionaryオプションを提供しています(正確には未指定時にはランダムなパスでキャッシュファイルが作成され、Rの終了時に削除されます)。

(bash)
$ time Rscript -e "library(tikzDevice); options(tikzMetricsDictionary='/tmp/dict'); tikz('out'); plot(1:10000); dev.off()"
real    0m3.815s
$ time Rscript -e "library(tikzDevice); options(tikzMetricsDictionary='/tmp/dict'); tikz('out'); plot(1:10000); dev.off()"
real    0m0.512s

これを常に静的なパスに設定すれば2回目以降の出力は高速化されますが、複数のRプロセスを同時に動かす場合に競合してエラーが発生する場合があります。

(bash)
$ Rscript -e "library(tikzDevice); options(tikzMetricsDictionary='/tmp/dict'); tikz('1'); plot(1:10000); dev.off()" &
$ Rscript -e "library(tikzDevice); options(tikzMetricsDictionary='/tmp/dict'); tikz('2'); plot(1:10000); dev.off()" &
$ Rscript -e "library(tikzDevice); options(tikzMetricsDictionary='/tmp/dict'); tikz('3'); plot(1:10000); dev.off()" &
$ Rscript -e "library(tikzDevice); options(tikzMetricsDictionary='/tmp/dict'); tikz('4'); plot(1:10000); dev.off()" &
$ wait
 createLockFile(lockname) でエラー:
  cannot create lock file ‘/private/tmp/dict___LOCK’
 呼び出し:  plot ... evalWithoutInterrupts -> dbInsert -> dbInsert -> createLockFile
 実行が停止されました

tikzDeviceの使い方としては論文中の複数のグラフをRで生成することが想定されるため、このままでは並列コンパイル(make -j)が正常に動かなくなります。

対策2

上記のエラーは、Rscript実行時のコマンドライン引数等を使ってハッシュをとることで簡易的に対策することができます。

.Rprofile
library(openssl) # md5を使用
pwd.and.args = paste(c(getwd(), commandArgs(trailingOnly=F)), collapse="")
pwd.and.args.hash = md5(pwd.and.args)
options(tikzMetricsDictionary=paste0("/tmp/tikz-", pwd.and.args.hash))

以上を.Rprofileなどに書いておくと/tmp/tikz-[適当なハッシュ値]にキャッシュされます。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?