ござるのブログ

覚え書きいろいろ

M1 MacでDocker Desktopに頼らずにx86_64のlRubyを使うまで

はじめに

Docker Desktopと同様に、limaでも、M1 Macx86_64のIRubyが動作します。以下、その手順です。

limaを使えるようにする

前回の記事qemu-virglをインストールするところまで実施します。

5zalt.hatenablog.com

x86_64のlimaを起動

$ limactl start amd64

amd64の部分は何でもよいです。

以下のように表示されるので、矢印キーでOpen an editor to override the configurationを選択してreturn。

? Creating an instance "amd64"  [Use arrows to move, type to filter]
  Proceed with the default configuration
> Open an editor to override the configuration
  Exit

エディタが起動するので、以下のように書き換えて保存し終了。

@@ -4,7 +4,7 @@

 # Arch: "default", "x86_64", "aarch64".
 # "default" corresponds to the host architecture.
-arch: "default"
+arch: "x86_64"

 # An image must support systemd and cloud-init.
 # Ubuntu and Fedora are known to work.
@@ -49,7 +49,7 @@
   # A localhost port of the host. Forwarded to port 22 of the guest.
   # Currently, this port number has to be specified manually.
   # Default: none
-  localPort: 60022
+  localPort: 61022
   # Load ~/.ssh/*.pub in addition to $LIMA_HOME/_config/user.pub .
   # This option is useful when you want to use other SSH-based
   # applications such as rsync with the Lima instance.

x86_64のLinuxイメージのダウンロードと環境構築が始まります。結構時間がかかります。

IRubyの構築と起動

以下のようなDockerfileを用意。

FROM jupyter/base-notebook:latest
USER root
RUN apt-get update \
  && apt-get install --no-install-recommends -y \
  libczmq-dev \
  libtool \
  make \
  ruby-dev \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*
RUN gem install --no-document \
  cztop \
  iruby
USER $NB_USER
RUN iruby register --force

Dockerfileを置いたディレクトリで以下を実行。

$ limactl shell amd64 nerdctl build -t iruby .

とても時間がかかります。私の環境では30分以上かかりました。コーヒーを飲みながら待ちます。

無事完了したら、以下のコマンドでIRubyを起動。

$ mkdir /tmp/lima
$ limactl shell amd64 nerdctl run -it --rm -p 8888:8888 -e JUPYTER_ENABLE_LAB=yes -v /tmp/lima:/home/jovyan/work iruby

ブラウザでアクセス

表示されるhttp://127.0.0.1:8888/lab?token=…にブラウザでアクセス

f:id:gzalt:20210920141345p:plain
IRubyの画面

すばらしい。

おわりに

なぜこんなことをしているかというと、手元のIRuby notebookで使っている neilslater/convolverがaarch64では使えないから。

icm7216/narray-convolveを使えばいいのでは? まぁ、そうですね…

M1 MacでDocker Desktopに頼らずにJupyter Labを使う(たぶん)最短の手順

はじめに

Jupyter Labをたまに使いたい私にはlimaはとてもありがたいツール。limaの開発はとても活発で頭が下がる思いです。

github.com

以下はJupyter Labを使えるようにするまでの手順メモです。

Homebrewをインストール

Homebrewをインストール。詳細は割愛。

limaをインストール

$ brew install lima

依存関係で入るqemuをunlinkしてqemu-virglをインストール

hvfパッチが当たったqemuでないと動かないらしいので、依存関係で入るqemuをunlinkしてqemu-virglをインストール

依存関係で入るqemuがアップデートされてqemu-virglを入れる必要がなくなりました。

limaを起動

$ limactl start

以下のように表示されるのでそのままreturn

? Creating an instance "default"  [Use arrows to move, type to filter]
> Proceed with the default configuration
  Open an editor to override the configuration
  Exit

Jupyter Labの構築と起動

$ mkdir /tmp/lima
$ lima nerdctl run -it --rm -p 8888:8888 -e JUPYTER_ENABLE_LAB=yes -v /tmp/lima:/home/jovyan/work jupyter/base-notebook

ブラウザでアクセス

表示されるhttp://127.0.0.1:8888/lab?token=…にブラウザでアクセス

f:id:gzalt:20210917103334p:plain
Jupyter Labの画面

すばらしい。

おわりに

素直にpipcondaで入れる方が最短じゃないか? まぁ、そうですね…

参考

zenn.dev

qiita.com

MacBook Air(M1, 2020)上でRuby/Tkを使ってPlotchart

久しぶりの更新。

はじめに

MacBook Air(M1, 2020)を手に入れたので、Ruby/Tkを使ってPlotchartできるようにします。

Homebrewのインストール

なにはともあれHomebrewをインストールします。詳細は割愛します。

Rubyのインストール

$ brew install ruby

tcl-tkのインストール

$ brew install tcl-tk

tklibのインストール

ここからtklibのソースをダウンロードします。現時点でtklib-0.6.tar.bz2から7年ぶり2020年2月にリリースされた tklib-0.7.tar.bz2が最新のようです(ここのブログも5年ぶりの更新ですが)。

ともかく、展開してインストールします。

$ tar xvf tklib-0.7.tar.bz2
$ cd tklib-0.7
$ PATH="$(brew --prefix tcl-tk)/bin:$PATH" \
 ./configure --prefix=$(brew --prefix tcl-tk)
$ make install

gemのインストール

Ruby本体から分離されてgemになっているRuby/Tkをインストールします。

$ PATH="$(brew --prefix tcl-tk)/bin:$PATH" \
gem install tk

動作確認

以前の記事に掲載したRubyスクリプトを動作させてみます。

f:id:gzalt:20210629114534p:plain
M1上Ruby/TkでPlotchart動作の様子

問題なく動作しました。

MDArrayを試してみました

はじめに

NArrayっぽいやつをいろいろ試しました - ござるのブログ」に続いて、JRubyのMDArrayも試してみました。

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

MDArray 0.6.1.2

MDArray は、JRuby用の多次元配列です。NumPy旧NArray にinspireされたものだそうです。

require 'mdarray'
require 'benchmark'

SIZE = 16384

Benchmark.bmbm do |x|
  x.report do
    r = Random.new
    a = MDArray.fromfunction('double', [SIZE, SIZE]) { r.rand }
    b = MDArray.fromfunction('double', [SIZE, SIZE]) { r.rand }
    c = a * b
  end
end

実行結果

 Error: Your application used more memory than the safety cap of 500M.

メモリが足りないと言われました。-J-Xmx12Gというオプションを付けて再実行します。

       user     system      total        real
  71.180000   3.840000  75.020000 ( 73.881698)

おわりに

やはり乱数を生成してセットするところが遅いようです。

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が最も速いという結果になりました。

各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が呼ばれていて、FreeBSDPATHの初期値が、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)のインストール

RubyActiveTclのインストールについては前の記事を見てください。

Plotchartは、前の記事ではteacupでインストール後C:\Ruby21\lib\ruby\2.1.0\tkextlib\setup.rbを編集してRuby/Tkに認識させましたが、これだとC:\Tcl\lib\teapot\package\tcl\lib\Plotchart2.3.3C:\Ruby21の外にあるため(?)、ocraでexe化する時に取り込まれません。

そこでsetup.rbは編集せず、Plotchart2.3.3フォルダごとC:\Ruby21\lib\tcltk内にコピーしました。C:\Ruby21\lib\tcltk内は、下記のような感じになります。

f:id:gzalt:20150216215501p:plain

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.pemC:\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化されました。

f:id:gzalt:20150216222753p:plain

サイズは5.14MBになりました。

実行結果

できあがったexeをダブルクリックすると、下記のようなグラフが表示されます。

f:id:gzalt:20150216124756g:plain

RubyActiveTclがインストールされていないWindows環境でも動作するはずです。

最後に

ちょっと大変でしたが、一度やればいいことなので、まあいいか。