LoginSignup
12
12

More than 5 years have passed since last update.

Ruby で行列演算するなら NMatrix を使った方が 100 倍速い

Posted at

釣りっぽいタイトルをつけてみました

今回使用したファイルや詳細な情報は Github に公開しているので興味のある方はご覧ください

catatsuy/ruby_matrix_bench

Ruby で行列演算をしたくなることがあると思います
Ruby の場合は標準で matrix ライブラリが用意されているのでこれを使うことが多いと思います

しかし matrix ライブラリは pure ruby 実装で逆行列なども私が見た限りは普通に掃き出し法によって実装されているようです
掃き出し法は大学一年生レベルの知識ですし,理論も実装も大して難しくないですが,ひたすら for 文を回していくことになるので LL だと遅い気がします

私が調べた限りは PHP には C 拡張による行列演算ライブラリ存在しないようですが(もしあるなら教えて欲しいです),Ruby には C 拡張を使用した gem がいくつか公開されているようです
その中で現在でも活発に開発が進めている NMatrix がとても良さそうな気配がします

SciRuby/nmatrix

ということでベンチマークをとってみました

試す演算は 28x28 次元の正方行列の逆行列を求めて,その後ベクトルと掛けるものです
入力値である行列は事前に用意した乱数に基づいて生成します
極力正確な値を取るために入力値を 42837 個準備しました

以下にベンチマークの ruby ファイルの一部を上げます

bench.rb
Benchmark.bm do |x|
  x.report do
    cc_n_a.each.with_index do |cc_n, index|
      cc_n.invert.dot NMatrix.new([term, 1], cs[index])
    end
  end
  x.report do
    cc_a.each.with_index do |cc, index|
      Matrix.rows(cc).inv * Vector.elements(cs[index])
    end
  end
end

上が NMatrix で下が matrix です

これを 3 回実行したときの結果です

% bundle exec ruby bench.rb
       user     system      total        real
   6.460000   0.070000   6.530000 (  6.982642)
 666.870000   1.180000 668.050000 (694.251381)

% bundle exec ruby bench.rb
       user     system      total        real
   6.540000   0.090000   6.630000 (  6.942445)
 683.680000   6.830000 690.510000 (786.069864)

% bundle exec ruby bench.rb
       user     system      total        real
   7.070000   0.060000   7.130000 (  7.923331)
 667.280000   1.500000 668.780000 (700.111114)

約 100 倍ほど実行時間に差があります

ということで NMatrix をおすすめしたいですが,残念ながら NMatrix は依存パッケージがあったり,環境変数を通さなければいけなかったりとインストールが少々面倒です
詳しくは公式のドキュメントをお読みください

Installation · SciRuby/nmatrix Wiki

今回は特殊なケースなので完全なる公平なベンチマークではないので,参考程度にどうぞ

12
12
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
12
12