トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

BugTrack-R備忘録/19

R備忘録 /状態空間モデリング/donlp2/その他のメモ

R備忘録 - 記事一覧

R(R言語)で並列処理 - Atlasを使う

  • 投稿者: みゅ
  • カテゴリ: なし
  • 優先度: 普通
  • 状態: 完了
  • 日時: 2009年01月15日 19時48分27秒

内容

Rで並列処理を行うためのtipsを書いていこうと思います.「snow」とか「multicore」とかいったパッケージについても、そのうち触れてみたいと思います.
まずは「Atlas」.AtlasはAutomatically Tuned Linear Algebra Softwareの略です.
みゅ自身もよくわかっていませんが、

  • 行列演算をCPUのキャッシュを効率よく使えるように分割して実行
  • 使えるCPUが2個以上の場合はスレッド化して複数のCPUを使って行列演算を行う.

というものです.
基本的に、大きな行列の演算に対して、すばらしいパフォーマンスを発揮してくれます.

  • 経験上、数ギガとかある行列の演算で、10時間以上かかっていた計算が、Atlasを使うことで数分で終わりました.
  • 一方、小さなサイズの行列演算に関しては、スレッド化する分だけほんの少しパフォーマンスは落ちます.

リンク

メモ

  • ATLASをインストールしてlapackを使うためには、先にちゃんとlapackをインストールというかビルドしなければならない模様.ちゃんと読めば書いてあった・・・
../ATLAS/configure -b 32 -t 2 -Fa alg -fPIC --with-netlib-lapack=../lapack-3.2.1/lapack_LINUX.a
  • lapackインストール
    • make.incに以下が必要
OPTS     = -fPIC
NOOPT    = -fPIC
When linking, remember that order is important.  So, if you want uniprocessor
libs, your link line would contain IN THIS ORDER:
   -LLIBDIR -llapack -lcblas -lf77blas -latlas
And if you want to utilize an SMP version, it would be:
   -LLIBDIR -llapack -lptcblas -lptf77blas -latlas

環境

いろいろな条件でパフォーマンスを計測できるように、仮想化環境(vmware)を使用します.

  • ホストOSはWINDOWS XP
    • CPU Athlon x2 Dual Core BE-2400 2.3GHz
    • メモリ 4Gバイト(ただしOSで認識できるのは3.37Gバイト)
  • ゲストOSはGentooLinux
    • amd64でカーネルを構築 => 変更
      • amd64だと、時間が正確に測れないので、x86バージョンに
    • パフォーマンスの計測のみなのでとりあえずメモリは512Mバイトにしておきます.
    • また、2CPUの場合と1CPUの場合の違いを見るために、1CPUのゲストと2CPUを使うゲスト、2種類を用意します.

こんな感じです.
Rをインストールする前に、blasとlapackをインストールしておきます.Gentooだとportageにあるのでらくちん.

emerge -v lapack

これで、blasとlapackがインストールされます.
Atlasを入れる前と入れた後での違いを見るために、Atlasはここではインストールしません.

Rのインストール

  • Rをインストールします.「R-2.8.1.tar.gz」をダウンロードしてきて、解凍.
$ ./configure --with-blas --with-lapack --enable-R-shlib

「--enable-R-shlib」オプションは計算速度とは関係ないのですが、あとで必要になるかもしれないので、とりあえず入れておきます.これは「libR.so」という共有ライブラリを作成するためのオプションです.
コンフィギュアが終わると

R is now configured for x86_64-unknown-linux-gnu

  Source directory:          .
  Installation directory:    /usr/local

  C compiler:                gcc -std=gnu99  -g -O2
  Fortran 77 compiler:       gfortran  -g -O2

  C++ compiler:              g++  -g -O2
  Fortran 90/95 compiler:    gfortran -g -O2
  Obj-C compiler:

  Interfaces supported:      X11
  External libraries:        readline, BLAS(generic), LAPACK(generic)
  Additional capabilities:   iconv, MBCS, NLS
  Options enabled:           shared R library, R profiling

  Recommended packages:      yes

configure: WARNING: you cannot build DVI versions of the R manuals
configure: WARNING: you cannot build PDF versions of the R manuals
configure: WARNING: I could not determine a browser
configure: WARNING: I could not determine a PDF viewer

と出力されて、BLASとLAPACKがライブラリとして使用されることがわかります.ただしまだatlasではありません.

  • make
make
LANG=C LC_ALL=C make check
  • インストール.rootになって
make install

1CPUと2CPUの比較

  • 注意! : まだ、AtlasをリンクしたRではありません.
  • 1プロセスでは1個のCPUしか使えませんから、1CPUでも2CPUでも、パフォーマンスは同じはずです.ホストOSや、ほかのゲストOSで負荷がかかっていない状態で実行します.
  • Rjpにもでてくるtest2関数
test2 <- function ( n=500, iter=10, stime=5 )
{
    A<-array(rnorm(n^2), dim=c(n,n))
    B<-array(rnorm(n^2), dim=c(n,n))
    C<-array(rnorm(n^2), dim=c(n,n))
    D<-array(rnorm(n^2), dim=c(n,n))
    BA <- B%*%A
    Sys.sleep(stime)
    old_time <- Sys.time()
    print(old_time)
    for( i in 1:iter )print(system.time(A%*%solve(t(BA)%*%BA+C)%*%BA%*%D ))
    Sys.sleep(stime)
    cur_time <- Sys.time()
    print(cur_time)
    print( cur_time - old_time - stime )
    NULL
}
  • これで、比較できると思ったのですが、思わぬ落とし穴が.このamd64 + WindowsXPが影響しているかどうか不明ですが、2CPUの場合負荷をかけた計算ではclockが異常に遅れます.そのため体感では1CPUでも2CPUでも計算にかかっている時間は変わらないのですが、表示される計算時間が2CPUでは、短くなってしまいます.つまり2CPUの方が、早く計算できていることに.負荷をかけるとclockが遅れるので、こうなってしまうのですが・・・
  • と、いうことでホストOSは同じで
  • ゲストOSにGentoo LinuxのX86版にしてみたところ、clockの遅れはほとんどでなくなったのでこちらで検証を行うことにしました.
  • 1CPUの場合
> test2(stime=0)
[1] "2009-01-17 14:09:46 JST"
   user  system elapsed
  2.190   0.060   2.253
   user  system elapsed
  2.170   0.060   2.249
   user  system elapsed
  2.230   0.030   2.272
   user  system elapsed
  2.190   0.040   2.258
   user  system elapsed
  2.220   0.040   2.257
   user  system elapsed
  2.160   0.050   2.228
   user  system elapsed
   2.27    0.03    2.33
   user  system elapsed
  2.170   0.080   2.261
   user  system elapsed
  2.200   0.050   2.266
   user  system elapsed
   2.14    0.11    2.26
[1] "2009-01-17 14:10:09 JST"
Time difference of 22.85281 secs

で、約23秒.

  • 2CPUの場合
> test2(stime=0)
[1] "2009-01-17 14:07:11 JST"
   user  system elapsed
  2.210   0.080   2.289
   user  system elapsed
  2.250   0.050   2.306
   user  system elapsed
  2.200   0.110   2.305
   user  system elapsed
  2.260   0.040   2.297
   user  system elapsed
  2.220   0.100   2.317
   user  system elapsed
  2.210   0.120   2.329
   user  system elapsed
  2.260   0.060   2.313
   user  system elapsed
  2.270   0.050   2.321
   user  system elapsed
  2.160   0.120   2.283
   user  system elapsed
  2.290   0.050   2.341
[1] "2009-01-17 14:07:34 JST"
Time difference of 23.34357 secs

で、約23秒をちょっと超えるくらい.

  • 仮想化環境で実行した場合ゲストOSのクライアントが2CPUを使うオーバーヘッドがあるんでしょうか.2CPUを割り当てたゲストOSの実行速度が若干遅くなる感じがします.
  • ですが、その分を考慮に入れても約24秒、ほとんど一緒です.

1CPUと2CPUの比較、プロセスを同時に2個走らせた場合

  • 一方、プロセスを同時に2個走らせた場合は、1CPUは同時に使えるCPUが1個しかありませんから、2CPUよりも時間がかかるはずです.
  • 1CPUの場合
    • プロセス1
> test2(stime=0)
[1] "2009-01-17 14:15:22 JST"
   user  system elapsed
   2.12    0.09    4.30
   user  system elapsed
  2.170   0.060   4.447
   user  system elapsed
   2.19    0.10    4.51
   user  system elapsed
  2.160   0.070   4.521
   user  system elapsed
  2.150   0.080   4.458
   user  system elapsed
  2.180   0.050   4.421
   user  system elapsed
  2.200   0.040   4.508
   user  system elapsed
  2.120   0.080   4.513
   user  system elapsed
  2.150   0.100   4.464
   user  system elapsed
  2.200   0.080   4.457
[1] "2009-01-17 14:16:07 JST"
Time difference of 45.01486 secs
    • プロセス2
> test2(stime=0)
[1] "2009-01-17 14:15:24 JST"
   user  system elapsed
  2.210   0.070   4.532
   user  system elapsed
  2.200   0.050   4.576
   user  system elapsed
  2.210   0.030   4.492
   user  system elapsed
   2.20    0.06    4.59
   user  system elapsed
  2.180   0.060   4.506
   user  system elapsed
  2.230   0.080   4.581
   user  system elapsed
  2.170   0.070   4.472
   user  system elapsed
  2.160   0.100   4.572
   user  system elapsed
  2.170   0.040   4.526
   user  system elapsed
  2.170   0.060   3.155
[1] "2009-01-17 14:16:09 JST"
Time difference of 44.4571 secs

と、このように、2倍の時間かかっています.

  • 2CPUの場合
    • プロセス1
> test2(stime=0)
[1] "2009-01-17 14:14:05 JST"
   user  system elapsed
  2.440   0.090   2.584
   user  system elapsed
  2.470   0.080   2.555
   user  system elapsed
  2.440   0.090   2.535
   user  system elapsed
  2.470   0.060   2.543
   user  system elapsed
  2.410   0.090   2.504
   user  system elapsed
  2.470   0.060   2.535
   user  system elapsed
  2.430   0.100   2.526
   user  system elapsed
   2.42    0.10    2.53
   user  system elapsed
  2.450   0.070   2.521
   user  system elapsed
  2.330   0.120   2.453
[1] "2009-01-17 14:14:31 JST"
Time difference of 25.53348 secs
    • プロセス2
> test2(stime=0)
[1] "2009-01-17 14:14:06 JST"
   user  system elapsed
   2.41    0.09    2.50
   user  system elapsed
  2.320   0.140   2.453
   user  system elapsed
  2.460   0.060   2.516
   user  system elapsed
  2.490   0.050   2.535
   user  system elapsed
  2.460   0.080   2.541
   user  system elapsed
   2.38    0.10    2.48
   user  system elapsed
  2.420   0.100   2.522
   user  system elapsed
   2.44    0.08    2.52
   user  system elapsed
  2.410   0.110   2.533
   user  system elapsed
  2.320   0.120   2.445
[1] "2009-01-17 14:14:32 JST"
Time difference of 25.27888 secs

と、このように、若干時間は延びたものの、ほぼ同じパフォーマンスを出すことができます.

  • CPU(コア)が2個あっても、データのとおるパイプラインは共通ですし、1プロセスとまったく同様のパフォーマンスを出すことができるわけではありません.でも、1CPUに比べると、この計算に関してはパフォーマンスの落ち込みはほとんど無いことがわかります.

AtlasをリンクしたRをインストールする.

  • Atlasをインストールする前の環境をとっておくために、1CPUバージョン2CPUバージョン両方とも仮想化環境をコピーしました.つまりこんな感じ
CPU数
Atlasなし
Atlasあり
  • Rをインストールする前に、まずはインストールしてあるRをアンインストール

Atlasをインストール

emerge -v lapack-atlas

1CPU

  • コンフィグ
./configure --disable-R-profiling \
    --with-blas='-L/usr/lib/blas/atlas -lblas -L/usr/lib -latlas' \ 
    --with-lapack="-L/usr/lib/blas/atlas -llapack -L/usr/lib -latlas" \
    --enable-R-shlib
  • コンフィグの結果
R is now configured for i686-pc-linux-gnu

  Source directory:          .
  Installation directory:    /usr/local

  C compiler:                gcc -std=gnu99  -g -O2
  Fortran 77 compiler:       gfortran  -g -O2

  C++ compiler:              g++  -g -O2
  Fortran 90/95 compiler:    gfortran -g -O2
  Obj-C compiler:

  Interfaces supported:      X11, tcltk
  External libraries:        readline, BLAS(ATLAS), LAPACK(generic)
  Additional capabilities:   PNG, JPEG, TIFF, iconv, MBCS, NLS
  Options enabled:           shared R library

  Recommended packages:      yes

configure: WARNING: you cannot build DVI versions of the R manuals
configure: WARNING: you cannot build PDF versions of the R manuals
configure: WARNING: I could not determine a browser
configure: WARNING: I could not determine a PDF viewer
  • LAPACKがATLASになってません・・・が、気にせず続行・・・
    • もしかして↓こうかも・・・?(ためしてません)
./configure --disable-R-profiling \
    --with-blas='-L/usr/lib/blas/atlas -lblas -L/usr/lib -latlas' \ 
    --with-lapack="-L/usr/lib/>>>lapack<<</atlas -llapack -L/usr/lib -latlas" \
    --enable-R-shlib
  • make
make
LANG=C LC_ALL=C make check
  • インストール.rootになって
make install

2CPU

  • コンフィグ
  • スレッド化されたのを使います.
./configure --disable-R-profiling 
    --with-blas='-L/usr/lib/blas/threaded-atlas -lblas -L/usr/lib -latlas' 
    --with-lapack='-L/usr/lib/lapack/atlas -llapack -L/usr/lib -latlas'
    --enable-R-shlib
  • コンフィグの結果
R is now configured for i686-pc-linux-gnu

  Source directory:          .
  Installation directory:    /usr/local

  C compiler:                gcc -std=gnu99  -g -O2
  Fortran 77 compiler:       gfortran  -g -O2

  C++ compiler:              g++  -g -O2
  Fortran 90/95 compiler:    gfortran -g -O2
  Obj-C compiler:

  Interfaces supported:      X11, tcltk
  External libraries:        readline, BLAS(ATLAS), LAPACK(generic)
  Additional capabilities:   PNG, JPEG, TIFF, iconv, MBCS, NLS
  Options enabled:           shared R library

  Recommended packages:      yes

configure: WARNING: you cannot build DVI versions of the R manuals
configure: WARNING: you cannot build PDF versions of the R manuals
configure: WARNING: I could not determine a browser
configure: WARNING: I could not determine a PDF viewer

やっぱりLAPACKはなってない・・・

  • make
make
LANG=C LC_ALL=C make check
  • インストール.rootになって
make install

1CPUと2CPUの比較、Atlas導入後

  • 1CPUの場合
> test2(stime=0)
[1] "2009-01-17 17:27:40 JST"
   user  system elapsed
  0.430   0.090   0.537
   user  system elapsed
  0.440   0.090   0.535
   user  system elapsed
  0.420   0.110   0.532
   user  system elapsed
  0.430   0.100   0.527
   user  system elapsed
  0.450   0.090   0.538
   user  system elapsed
  0.400   0.130   0.541
   user  system elapsed
  0.490   0.080   0.568
   user  system elapsed
  0.470   0.070   0.543
   user  system elapsed
  0.470   0.070   0.539
   user  system elapsed
  0.490   0.050   0.546
[1] "2009-01-17 17:27:46 JST"
Time difference of 5.996144 secs

このように、このケースでは約4倍早く計算することができるように、なりました.もっと大きな行列だと、もっと効果があると思います.

  • 2CPUの場合
> test2(iter=10, stime=0)
[1] "2009-01-17 19:06:55 JST"
  user  system elapsed
 0.440   0.070   0.487
  user  system elapsed
 0.420   0.090   0.482
  user  system elapsed
 0.400   0.090   0.477
  user  system elapsed
 0.450   0.090   0.494
  user  system elapsed
 0.350   0.090   0.445
  user  system elapsed
 0.410   0.090   0.449
  user  system elapsed
 0.380   0.080   0.461
  user  system elapsed
 0.430   0.080   0.507
  user  system elapsed
 0.280   0.090   0.379
  user  system elapsed
  0.32    0.14    0.46
[1] "2009-01-17 19:07:00 JST"
Time difference of 4.850254 secs

このくらいの計算だと1CPUでも2CPUでもほとんどパフォーマンスは変わらないですね.気持ち早くなっていますが.

Atlas導入の効果を見る

  • ということで、その効果を測るために、test2関数の引数を「n=1000」として、計算してみます.

2CPUで、Atlas導入前

    • Atlas入れてないので、1CPUと計算速度は同じと思ってください.
> test2(n=1000, stime=0)
[1] "2009-01-17 19:07:52 JST"
   user  system elapsed
 19.600   0.450  21.123
   user  system elapsed
 19.910   0.340  21.151
   user  system elapsed
 19.700   0.470  21.074
   user  system elapsed
 20.040   0.230  21.126
   user  system elapsed
 19.930   0.410  21.101
   user  system elapsed
 19.880   0.340  21.005
   user  system elapsed
 19.570   0.470  20.994
   user  system elapsed
 19.640   0.430  20.906
   user  system elapsed
  19.51    0.32   20.72
   user  system elapsed
  19.88    0.39   21.00
[1] "2009-01-17 19:11:22 JST"
Time difference of 3.508183 mins

こうなります.一回の計算に20秒以上.で「top」コマンドの表示を見ていると、RでのCPU使用率は100%.で、100%を超えません.

1CPU + Atlas

> test2(n=1000, stime=0)
[1] "2009-01-18 15:28:43 JST"
   user  system elapsed
   3.15    0.30    3.45
   user  system elapsed
   3.11    0.32    3.43
   user  system elapsed
   3.13    0.32    3.45
   user  system elapsed
   3.09    0.32    3.41
   user  system elapsed
   3.07    0.35    3.42
   user  system elapsed
   3.22    0.26    3.50
   user  system elapsed
   3.16    0.27    3.43
   user  system elapsed
   3.08    0.35    3.43
   user  system elapsed
   3.20    0.26    3.46
   user  system elapsed
   3.15    0.26    3.41
[1] "2009-01-18 15:29:18 JST"
Time difference of 34.67962 secs

Atlasを導入することで、かなり早くなっています.

  • 2CPU+Atlasなら、スレッド化して分割で計算してくれますから、CPU使用率は100%を超えるはず.そしてパフォーマンスも良いはず.

2CPUで、Atlas導入後

> test2(n=1000, stime=0)
[1] "2009-01-17 19:17:04 JST"
   user  system elapsed
   3.18    0.40    2.45
   user  system elapsed
  3.020   0.420   2.284
   user  system elapsed
  3.110   0.410   2.437
   user  system elapsed
  3.230   0.340   2.409
   user  system elapsed
  3.170   0.450   2.374
   user  system elapsed
  3.060   0.360   2.388
   user  system elapsed
  3.080   0.390   2.326
   user  system elapsed
  3.170   0.320   2.392
   user  system elapsed
  2.970   0.390   2.328
   user  system elapsed
  3.170   0.360   2.422
[1] "2009-01-17 19:17:28 JST"
Time difference of 24.15007 secs

どうですか、奥様!!

  • CPU使用率も150%くらいまで上がって、パフォーマンスも劇速.
    • 2CPUでスレッド化しても、パイプラインとか共通なので、200%にはなりませんよね.
  • ちょうど、パフォーマンスも1.5倍くらいですか.

結果とか感想とか

  • ということで、Atlasを使う計算であれば、CPUが2個以上乗っていれば、行列演算を効率よく分割して、スレッド化して計算してくれるので、並列処理していると、言っていいでしょう.
  • スレッド化するだけでなく、CPUのキャッシュをうまく使うような行列演算に分割してくれるので???1CPUだけでもAtlasの効果はあります.
  • 仮想化環境も使い方によっては最高!
  • さて次はなにしよう・・・multicoreかな・・・

コメント