釣りっぽいタイトルをつけてみました
今回使用したファイルや詳細な情報は Github に公開しているので興味のある方はご覧ください
Ruby で行列演算をしたくなることがあると思います
Ruby の場合は標準で matrix
ライブラリが用意されているのでこれを使うことが多いと思います
しかし matrix
ライブラリは pure ruby 実装で逆行列なども私が見た限りは普通に掃き出し法によって実装されているようです
掃き出し法は大学一年生レベルの知識ですし,理論も実装も大して難しくないですが,ひたすら for 文を回していくことになるので LL だと遅い気がします
私が調べた限りは PHP には C 拡張による行列演算ライブラリ存在しないようですが(もしあるなら教えて欲しいです),Ruby には C 拡張を使用した gem がいくつか公開されているようです
その中で現在でも活発に開発が進めている NMatrix
がとても良さそうな気配がします
ということでベンチマークをとってみました
試す演算は 28x28 次元の正方行列の逆行列を求めて,その後ベクトルと掛けるものです
入力値である行列は事前に用意した乱数に基づいて生成します
極力正確な値を取るために入力値を 42837 個準備しました
以下にベンチマークの ruby ファイルの一部を上げます
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
今回は特殊なケースなので完全なる公平なベンチマークではないので,参考程度にどうぞ