numo-narray と malloc の不可解さ

RubyKaigi 2018 が終わった後、Red Data Tools に参加しようかと思い numo-narray を見ていたりするのですが、ベンチマークが不可解な値を示して頭を悩ませています。

使用しているベンチマークは公式の Wiki にあった Tentative Benchmark を用いてます。

require 'numo/narray'
N = 100000
M = 10000

a = Numo::DFloat.new(N).seq
b = Numo::DFloat.new(N).seq

M.times{|i| c = a + b }

これを macOS で実行した結果が以下のようになります。

$ rbenv install 2.5.1
$ gem install numo-narray
$ time ruby bench.rb
ruby bench.rb  1.59s user 1.26s system 99% cpu 2.866 total

公式の Wiki には比較用に Python のコードも載っていたので実行すると 3 倍くらい遅い感じです。 試しに macOS 上に Ubuntu の仮想マシンを用意し同様に実行すると以下のような値を示します。

$ time ruby bench.rb
ruby narray.rb  0.89s user 0.06s system 100% cpu 0.944 total

OS を変えただけで 3 倍違う値になります。ここで2週間ほど悩んでいたのですが、macOS 上で実行したときには、半分程度は system の実行時間になっています。

jemalloc を使ってみた

system 部分に時間がかかる理由が、malloc くらいしか思い浮かばなかったので、とりあえず jemalloc を使ってみました。

$ RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install 2.5.1
$ gem install numo-narray
$ time ruby bench.rb
ruby bench.rb  0.91s user 0.10s system 99% cpu 1.019 total

macOS 上での実行時間が 1/3 になりました!同じように Ubuntu の仮想マシンで実行すると、

$ time ruby bench.rb
ruby narray.rb  1.02s user 1.89s system 99% cpu 2.908 total

実行時間が 3 倍になった・・・。

とりあえず、macOS のメモリアロケータは open になっているので、そのうち読んでみようかと。

所感

macOS で Ruby をやるなら jemalloc 使うのが良さそうだが、jemalloc が万能とは限らなそう。

追記:2018-07-07

master では直っているという情報をいただきました。ありがとうございます(\( ⁰⊖⁰)/)