NArrayっぽいやつをいろいろ試しました
はじめに
「MF / Numo::NArray を試してみる」を拝見し、NumRu::NArrayもあると思ったので試してみました。ほぼ真似です。すみません。
実行環境は以下の通りです。
- MacBook Pro (Late 2013)
- OS X El Capitan 10.11.5
- rbenvで入れたRuby 2.3.1
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::NArrayはNArrayに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は、GSLのRubyバインディングで使えます。
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が最も速いという結果になりました。
各OSのPATHの初期値
はじめに
FreeBSD 10.1で
$ pkg install ctags
として、Exuberant Ctagsを入れたのに
$ ctags -R ctags: illegal option -- R usage: ctags [-BFTaduwvx] [-f tagsfile] file ...
と言われます。/usr/local/bin/ctags
ではなく/usr/bin/ctags
が呼ばれていて、FreeBSDのPATH
の初期値が、Debianと違うことに今さら気付きました。以下、自分のためのメモです。
Debian Sidの場合
/etc/login.defs
で設定。
ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
/usr/bin
よりも/usr/local/bin
が優先される。
OSX Yosemiteの場合
/etc/paths
(と/etc/paths.d/
)で設定
/usr/local/bin /usr/bin /bin /usr/sbin /sbin
/usr/bin
よりも/usr/local/bin
が優先される。
FreeBSD 10.1の場合
/etc/login.conf
で設定
default:\ :passwd_format=sha512:\ :copyright=/etc/COPYRIGHT:\ :welcome=/etc/motd:\ :setenv=MAIL=/var/mail/$,BLOCKSIZE=K:\ :path=/sbin /bin /usr/sbin /usr/bin /usr/games /usr/local/sbin /usr/local/bin ~/bin:\
/usr/local/bin
よりも/usr/bin
が優先される。
最後に
わかってないと地味にひっかかりそう…
Ruby/TkでTk拡張を使っているRubyスクリプトをexe化
はじめに
Ruby/TkとTk拡張で作ったちょっとしたツールをWindows利用者に使ってもらう場合、RubyやTk拡張をインストールしてもらう必要があり、気軽に使ってもらうのは難しいです。そこでocraを使って単一のexeファイルにしたのですが、結構てこずりました。
RubyとActiveTclとTk拡張(Plotchart)のインストール
RubyとActiveTclのインストールについては前の記事を見てください。
Plotchartは、前の記事ではteacup
でインストール後C:\Ruby21\lib\ruby\2.1.0\tkextlib\setup.rb
を編集してRuby/Tkに認識させましたが、これだとC:\Tcl\lib\teapot\package\tcl\lib\Plotchart2.3.3
がC:\Ruby21
の外にあるため(?)、ocraでexe化する時に取り込まれません。
そこでsetup.rb
は編集せず、Plotchart2.3.3
フォルダごとC:\Ruby21\lib\tcltk
内にコピーしました。C:\Ruby21\lib\tcltk
内は、下記のような感じになります。
ocraのインストール
「スタートメニュー」→「Ruby 2.1.5p273」→「Rubyコマンドプロンプトを開く」から
C:\Users\hoge>gem install ocra
と入力しocraをインストールしますが、
ERROR: Could not find a valid gem 'ocra' (>= 0), here is why: Unable to download data from https://rubygems.org/ - SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://api.rubygems.org/latest_specs.4.8.gz)
と言われるかもしれません。これはバグらしいので、こちらのサイトの記載の通りここにあるAddTrustExternalCARoot-2048.pem
をC:\Ruby21\lib\ruby\2.1.0\rubygems\ssl_certs
にコピーして、再度試してください。
ocraでexe化
無事ocraがインストールできたら、こちらのサイトを参考に、前の記事のスクリプトをexe化してみます。
C:\Users\hoge>ocra plot.rbw C:\Ruby21\lib\tcltk --no-autoload --add-all-core
うまくいきましたと言いたいところですが
C:/Users/hoge/plot.rbw:18:in `<top (required)>': uninitialized constant DATA (NameError)
と言われるので、少しコードを修正します。
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'csv' require 'tk' require 'tkextlib/tcllib/plotchart' # plotchart.rb を修正するモンキーパッチ module Tk::Tcllib::Plotchart class XYPlot def pixel_to_coords(x, y) list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) end end end # データ data = <<EOS 32.78,1074 62.72,12131 92.70,13944 122.72,13110 152.79,11859 182.90,13204 213.05,11647 243.24,8780 273.47,7412 303.75,6632 334.07,6460 364.43,6369 394.83,6503 425.28,6566 455.76,5250 486.29,2766 516.86,1574 547.48,1062 578.13,914 608.83,3532 639.57,15018 670.35,18992 701.18,6495 732.04,660 762.95,177 793.90,157 824.89,134 855.93,154 887.00,131 918.12,124 949.28,129 980.48,113 1011.73,96 1043.01,103 1074.34,112 1105.72,92 1137.13,95 1168.58,86 1200.08,85 1231.62,66 1263.20,50 1294.83,29 1326.49,40 1358.20,33 1389.95,47 1421.74,93 1453.57,111 1485.45,67 1517.37,41 1549.33,19 1581.33,17 1613.38,11 1645.46,13 1677.59,18 1709.76,15 1741.98,10 1774.23,6 1806.53,13 1838.87,15 1871.25,11 1903.67,6 1936.14,8 1968.64,6 2001.20,8 EOS # データを読み込み en, cn = CSV.parse(data).map { |r| [r[0].to_f, r[1].to_i] }.transpose # データをプロット pl = Tk::Tcllib::Plotchart::XLogYPlot .new([0, en.size, 10**Math.log10(en.size).floor], [1, 10**Math.log10(cn.max).ceil], width: 600, height: 400) do title 'Spectrum' xtext 'Channel' ytext 'Counts/Channel' dataconfig('series1', color: :red) cn.each_with_index { |c, i| plot('series1', i, c) } pack(fill: :both) end # マウスの位置の値の表示 label = TkLabel.new.pack pl.bind(:Motion, '%x %y') do |x, y| ch = pl.pixel_to_coords(x, y)[0].to_i if 0 <= ch && ch < en.size label.text(sprintf('%10d ch, %10.1f keV, %10d counts', ch, en[ch], cn[ch])) end end # イベントループ Tk.mainloop
再度exe化を試みます。
C:\Users\hoge>ocra plot.rbw C:\Ruby21\lib\tcltk --no-autoload --add-all-core
グラフが表示されるので[x]をクリックして終了させると、以下のようにうまくexe化されました。
サイズは5.14MBになりました。
実行結果
できあがったexeをダブルクリックすると、下記のようなグラフが表示されます。
RubyやActiveTclがインストールされていないWindows環境でも動作するはずです。
最後に
ちょっと大変でしたが、一度やればいいことなので、まあいいか。
Windows 7上でRuby/Tkを使ってPlotchart
はじめに
以前の記事で書いたコードがWindows 7でも動くようにします。
Ruby 2.1.5のインストール
RubyのWindows版バイナリは何種類かありますが、今回はRubyInstaller for Windowsを使います。現時点の最新であるRuby 2.1.5をC:\Ruby21
にインストールしますが、その際、下記のように「Tcl/Tkサポートをインストールする」に必ずチェックを入れます。加えて、「.rbと.rbwファイルをRubyに関連づける」にチェックを入れておくと、Rubyスクリプトをダブルクリックするだけで実行できて便利です。
ActiveTclのインストール
RubyInstaller for WindowsのRuby 2.1.5に付属のTcl/Tkは8.5なので、ActiveTclのWindows (x86) 8.5.17.0をC:\Tcl
にインストールしました。その後、こちらのサイトをマネさせていただいて、C:\Ruby21\lib\ruby\2.1.0\tkextlib\setup.rb
に以下を追記しました。
['C:\Tcl\lib\teapot\package\tcl\lib', 'C:\Tcl\lib\teapot\package\win32-ix86\lib'].each do |dir| TkPackage.add_path(File.expand_path(dir)) end
これでRubyからActiveTclの拡張が使えるようになりました。
Plotchartのインストール
ActiveTclにはPlotchartが含まれていないので、コマンドプロンプトから下記のように追加します。
C:\Users\hoge>teacup install Plotchart
これでRuby/TkでPlotchartが使えるようになりました。
実は、PlotchartをインストールするためにActiveTclに含まれているteacup
が必要なだけだったので、この後ActiveTclをアンインストールしても、RubyInstaller for Windows付属のTcl/Tkだけで、Plotchartが使えたりします。
実行結果
以下のように、以前の記事で書いたコードがそのままWindows 7で動きました。
最後に
ちょっとしたツールをRuby/Tkで作ってWindows利用者に配布したかったのですが、上記のような作業を皆にやってもらうのは大変なので、ocraを試したいと思います。
VirtualBox上のFreeBSD 10.1でホストのOSX Yosemiteとsshfsでファイル共有
はじめに
OSX Yosemite上のVirtualBox内にFreeBSD 10.1を入れました。早速
$ pkg install virtualbox-ose-additions
として、virtualbox-ose-additions
をインストールしましたが、現時点で「共有ホルダー」は使えないようです。(ここで開発中らしいです。期待しています。)
そこで、sshfsでOSX YosemiteのフォルダをFreeBSDにマウントしたのですが、ちょっとてこずりました。以下、手順メモです。
OSX Yosemiteでリモートログインを有効にする
これが無いと始まりません。「システム環境設定」→「共有」→「リモートログイン」にチェックを入れます。
VirtualBoxの設定
下記のように、外部との通信用の「アダプター1」(NAT)に加えて、OSX Yosemiteとやりとりするための「アダプター2」(ホストオンリーアダプター)を追加します。
FreeBSD 10.1の設定
fusefs-sshfsのインストール
$ pkg install fusefs-sshfs
/boot/loader.confの編集
FUSEを有効化する。
fuse_load="YES"
/etc/rc.conf
にfusefs_enable="YES"
とするという記事を見かけますが、変わったようです。(参考)
/etc/sysctl.confの編集
ユーザランドでマウントが利用できるようにする。
vfs.usermount=1
/etc/rc.confの編集
ifconfig_em0="DHCP" ifconfig_em1="inet 192.168.56.203 netmask 255.255.255.0" vboxguest_enable="YES" vboxservice_enable="YES"
em1
が「アダプター2」(ホストオンリーアダプター)です。OSX Yosemiteのvboxnet0
が192.168.56.1
なので、適当に192.168.56.203
の固定アドレスを設定しました。
/etc/groupの編集
operator:*:5:root,[自分のアカウントを追記]
やっとマウント
FreeBSDを一旦再起動して、ログイン後
$ mkdir hostdir $ sshfs -o idmap=user 192.168.56.1: hostdir
とすると、パスワードを聞かれるので入力します。うまくいけば、OSX Yosemiteのホームディレクトリがhostdir
にマウントされて、読み書きできるようになるはずです。
最後に
かなり前にFreeBSD(98)をいじって遊んだことがあるので、いろいろなつかしいです。
OSX Yosemiteにrbenvとruby-buildでRuby 2.2.0を入れる時のconfigureオプション
自分がOSX Yosemiteにrbenvとruby-buildでRuby 2.2.0を入れる時のconfigureオプションを、覚え書きとして残しておきます。
$ RUBY_CONFIGURE_OPTS="--enable-pthread --enable-shared \ --with-readline-dir=`brew --prefix readline` \ --with-openssl-dir=`brew --prefix openssl` \ --with-libyaml-dir=`brew --prefix libyaml` \ --with-opt-dir=`brew --prefix gdbm`:`brew --prefix gmp`:`brew --prefix libffi`" \ rbenv install 2.2.0
見ての通りHomebrewでreadline、openssl、libyaml、gdbm、gmp、libffiを入れて、それらを使うようにしています。
Tcl/Tkに関するオプションは何もありませんが、Ruby/TkでOSX Yosemiteに入っているTcl/Tk 8.5が普通に使えました。
Ruby/Tkで少しだけインタラクティブなグラフを表示する
はじめに
以前書いたように、Ruby/TkとPlotchartでグラフを表示できるのですが、それだけではつまらないので、ちょっとだけマウスと連動させてみます。
コード
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'csv' require 'tk' require 'tkextlib/tcllib/plotchart' # plotchart.rb を修正するモンキーパッチ module Tk::Tcllib::Plotchart class XYPlot def pixel_to_coords(x, y) list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) end end end # データを読み込み en, cn = CSV.parse(DATA).map { |r| [r[0].to_f, r[1].to_i] }.transpose # データをプロット pl = Tk::Tcllib::Plotchart::XLogYPlot .new([0, en.size, 10**Math.log10(en.size).floor], [1, 10**Math.log10(cn.max).ceil], width: 600, height: 400) do title 'Spectrum' xtext 'Channel' ytext 'Counts/Channel' dataconfig('series1', color: :red) cn.each_with_index { |c, i| plot('series1', i, c) } pack(fill: :both) end # マウスカーソルの位置の値を表示 label = TkLabel.new.pack pl.bind(:Motion, '%x %y') do |x, y| ch = pl.pixel_to_coords(x, y)[0].to_i if 0 <= ch && ch < en.size label.text(sprintf('%10d ch, %10.1f keV, %10d counts', ch, en[ch], cn[ch])) end end # イベントループ Tk.mainloop __END__ 32.78,1074 62.72,12131 92.70,13944 122.72,13110 152.79,11859 182.90,13204 213.05,11647 243.24,8780 273.47,7412 303.75,6632 334.07,6460 364.43,6369 394.83,6503 425.28,6566 455.76,5250 486.29,2766 516.86,1574 547.48,1062 578.13,914 608.83,3532 639.57,15018 670.35,18992 701.18,6495 732.04,660 762.95,177 793.90,157 824.89,134 855.93,154 887.00,131 918.12,124 949.28,129 980.48,113 1011.73,96 1043.01,103 1074.34,112 1105.72,92 1137.13,95 1168.58,86 1200.08,85 1231.62,66 1263.20,50 1294.83,29 1326.49,40 1358.20,33 1389.95,47 1421.74,93 1453.57,111 1485.45,67 1517.37,41 1549.33,19 1581.33,17 1613.38,11 1645.46,13 1677.59,18 1709.76,15 1741.98,10 1774.23,6 1806.53,13 1838.87,15 1871.25,11 1903.67,6 1936.14,8 1968.64,6 2001.20,8
実行結果
OSX Yosemiteで実行した結果です。下記のように、マウスカーソルの位置の値がグラフの下に表示されます。
Ruby 2.2.0同梱のplotchart.rbのバグ
グラフ内におけるマウスカーソルの座標を取得するためにTk::Tcllib::Plotchart::XLogYPlot#pixel_to_coords
を使ったのですが、Ruby 2.2.0 同梱のplotchart.rb
にはバグがあるので、下記のようにモンキーパッチを当てています。
module Tk::Tcllib::Plotchart class XYPlot def pixel_to_coords(x, y) list(tk_call_without_enc('::Plotchart::pixelToCoords', @path, x, y)) end end end
既に修正が本家に取り込まれたようなので、そのうち必要なくなると思います。
最後に
Ruby/TkとPlotchartさえ入っていればWindowsでも動きます。しかし、WindowsはPlotchartを使えるようにするまでがちょっと面倒でした(こちらに書きました)。