ござるのブログ

覚え書きいろいろ

NArrayっぽいやつをいろいろ試しました

はじめに

MF / Numo::NArray を試してみる」を拝見し、NumRu::NArrayもあると思ったので試してみました。ほぼ真似です。すみません。

実行環境は以下の通りです。

NArray 0.6.1.2

他のNArrayっぽいやつに多大な影響を与えたと思われる旧バージョンです。これのおかげで、いろんなデータ解析が捗りました。作者様ありがとうございます。

require 'narray'
require 'benchmark'

SIZE = 16384

Benchmark.bmbm do |x|
  x.report do
    a = NArray.float(SIZE, SIZE).random
    b = NArray.float(SIZE, SIZE).random
    c = a * b
  end
end

実行結果

 benchmark_narray.rb:10:in `float': allocation size is too large (ArgumentError)
    from benchmark_narray.rb:10:in `block (2 levels) in <main>'

旧NArrayではこんなに大きいサイズは扱えないようです。

NumRu::NArray 1.0.3

NumRu::NArrayNArrayにbig memory supportを加えたものだそうです。

require 'numru/narray'
require 'benchmark'

# ENV['OMP_NUM_THREADS'] = '4'

include NumRu

SIZE = 16384

Benchmark.bmbm do |x|
  x.report do
    a = NArray.float(SIZE, SIZE).random
    b = NArray.float(SIZE, SIZE).random
    c = a * b
  end
end

実行結果

       user     system      total        real
   9.370000   7.030000  16.400000 ( 20.239738)

NArrayではエラーになったサイズの計算ができました。

Numo::NArray 0.9.0.1

Numo::NArrayは、期待の新NArrayです。GSLとのインタフェースもあるようです。すばらしいです。

require 'numo/narray'
require 'benchmark'

include Numo

SIZE = 16384

Benchmark.bmbm do |x|
  x.report do
    a = DFloat.new(SIZE, SIZE).rand
    b = DFloat.new(SIZE, SIZE).rand
    c = a * b
  end
end

実行結果

       user     system      total        real
   7.840000   2.570000  10.410000 ( 12.739366)

おお、NumRu::NArrayより速い。

NMatrix 0.2.1

NMatrixは、Rubyでscientific computingをやろうというSciRubyのfast numerical linear algebra libraryです。以前はNArrayと同時にはインストールできなかったのですが、require 'nmatrix/nmatrix'とすれば使えるようになったようです。

require 'nmatrix/nmatrix'
require 'benchmark'

SIZE = 16384

Benchmark.bmbm do |x|
  x.report do
    a = NMatrix.random([SIZE, SIZE])
    b = NMatrix.random([SIZE, SIZE])
    c = a * b
  end
end

実行結果

       user     system      total        real
 129.120000   6.300000 135.420000 (137.681446)

遅いです。

GSL::Matrix 1.16.0.6

GSL::Matrixは、GSLRubyバインディングで使えます。

require 'gsl'
require 'benchmark'

include GSL

SIZE = 16384

Benchmark.bmbm do |x|
  x.report do
    r = Rng.alloc
    a = Matrix.alloc(SIZE, SIZE).map { r.uniform }
    b = Matrix.alloc(SIZE, SIZE).map { r.uniform }
    c = a.mul_elements(b)
  end
end

実行結果

       user     system      total        real
  54.000000   6.220000  60.220000 ( 62.904272)

このコードでは乱数を生成してセットする部分にワンクッションあるのでどうしても遅くなります。でも、NMatrixよりは速いです。

まとめ

今回は、Numo::NArrayが最も速いという結果になりました。