最近の記事

RubyでRactor::Selectorを使う(C APIをRubyから呼び出す)

July 14, 2025

Rubyで並列処理をするにあたってRuby3から導入されたRactor(日本語のドキュメントが見つからなかったので英語版で…)を使ってみています。まだ試験的導入(Ractor入りのスクリプトを実行すると warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.とでる)であるため、日々改良が重ねられているようですが、つーすを読んでみると隠し機能があることがわかりました。

Ractor間の通信があったことを補足するRactor::select(*ractors)という関数があるのですが、複数のRactorのメッセージを全て完了するのに、一つずつ減らしながらselectを何度も呼び出すのはオーバーヘッドが大きそうだということに気が付きました。内部的にはRuby 3.3, 3.4ではRactor::Selectorというクラスのインスタンスを生成して、そこにractorsを登録するような仕組みになっていますので、selectを呼ぶためにRactor::Selectorを作ります。もしRactor::Selectorが再利用できれば、オーバーヘッドを少しでも減らせそうです。

しかし残念ながらRactor::Selectorを直接RubyからいじるにはRubyをビルドする時にUSE_RACTOR_SELECTORをdefineする必要がありました。一方よく見てみると、rb_init_ractor_selector()というRactor::SelectorをRubyから見えるようにする関数も公開されていることがわかりました(Ruby 3.4では2567行目付近、3.3も同様の定義です)。

Rubyをビルドしなおすのも少々面倒なので、ここからはサブタイトルになっているRubyのC API(今回でいうとrb_init_ractor_selector)を呼び出すことを考えます。C関数を呼び出せるFFIまたはFiddleを使うことにしました。下記のコードで達成できます。Using Ruby's C API inside Rubyが参考になりました。

最後にもともとのRactor::selectの効率化ですがRactor::Selector#wait, #removeなどが定義されていますので、これを使って実現しました。

HDL-AAX2 シャットダウンスクリプト

July 24, 2024

自宅NASのIO-DATA HDL-AAX2ですが、リモートでシャットダウンする必要があり、方法を検討しました。少し古い機種のHDL2-Aのシャットダウンスクリプトが見つかったのですが、それをそのまま適用することはできなかったので、少し改造して使うことにしました。

出来上がったのが以下のRubyスクリプトです。

mechanizeというwebの自動巡回を可能とするgem(クローラ)を使うことで実現しています。少し古いRuby(< 2.6.0)でも簡潔に書けるよう、Kernel#thenがない場合に備えて自己定義しています(古いRubyに最新の機能を入れ込むbackports gemKernel#yield_selfのコードを参考にしました)。

曜日を求める(8bit範囲で)

July 04, 2024

マイコンを使って年月日から曜日を求めたいケースがありました。普通の環境ならC言語を前提とすれば<time.h>にあるmktime関数とlocaltime関数を使うことで実現できます。


裏では曜日を求めるアルゴリズム(色々あります)のどれかを使って求めていると思います。


今回は対象がマイコンということもあり、機能を限定することでコンパクトなアルゴリズムに改変してみました。


sakamoto's methodを元にしました。日時範囲はGPS時刻を前提とすることで1980年以降とし、また2099年まで使えればよい割り切りをしています。すると、うるう年の計算が100で割り切れて400で割り切れない年を考慮する必要がなくなり、簡略化されました。また型を最小のunsigned charで統一してみました。


検証はRubyのRspecでやってみています。


上記CコードとRubyでのDate#wdayとの一致を見ています。なおテストの実装にあたっては、RubyInlineを使ってRubyの中でC言語コードを直接扱ってみました。

Assisted GPS (A-GPS)クライアントの実装

April 02, 2024

GPS関係の処理をRubyから使えるようにしたgps_pvt gemは色々なストリームやファイル、シリアルポート(GPSデバイス直結)から情報を読み込めるようにしてあります。このたびv0.10で初期測位を早めるためのAssisted GPS (A-GPS)に対応しました。単独測位をするのであればgemをインストール後に以下のコマンドで例えばAndroidなどて使われているGoogleのサーバから情報を取得してA-GPSを利用できます。

$ gps_pvt supl://supl.google.com/ (Ntrip等のリアルタイムストリームを指定)

生データに近い物が見たければ、以下のコマンドでJSON形式でエフェメリス等が得られます。

$ gps_get supl://supl.google.com/

エフェメリス(軌道情報)を読み込む程度なので実装は簡単かなと思って始めたのですが、結果的に色々調べる必要がありました。羅列ですが、調べたものを残しておこうと思います。

SUPL
Secure user plane location。A-GPSの事実上の標準実装(という理解)。プロトコル名としてはUserPlane Location Protocol(ULP)。表面を覆っているのがULPで、中身のペイロードにはLPPやRRLPといった別のプロトコルが使われる。実装例が少ない中、tajuma/suplgoogle/supl-clientが参考になった。
LPP (TS 37.355)
LTE Positioning Protocol。エフェメリスなどの定義がある。GPS以外の定義もしっかりされている。
RRLP (TS 44.031)
Radio Resource Location service Protocol。LPP同様エフェメリスなどの定義があるが古めの規格。プロトコルとしてはGPS以外も使えそうに見えるが、GoogleのSUPLサーバに問い合わせてもGPSのエフェメリスしかくれない模様。
ASN.1 (X.680)
Abstract Syntax Notation One。ULP, LPP, RRLPなどの文法は全てこれで書かれている。Rubyにも主にSSL証明書をパースする目的でOpenSSL::ASN1の実装があるが、機能が限定的で今回は使わなかった。代わりにRubyの構文解析ツールであるRaccを使う前提で文法asn1.yを定義し、asn.1形式の文法ファイルをパースできるようにした。asn.1をasn1.y(から作ったRubyコード)で事前にJSONに変換(upl.json.gz)して本番では利用している(rake upl.json)。Samayou Oharikuiの和文解説Gusztáv ADAMISさん(ERICSSON)のスライド(PDF)がとても参考になった。OSS NokalvaObjective Systemsも参考にした。
PER (X.691)
Packed Encoding Rules。SUPLではバイナリで情報がやり取りされるが、その時のエンコーディングルールにBasic Unaligned PERが指定されている。前述の参考資料にも解説あり。RSpecで(asn.1から変換した)JSONとPER間のテストを書いて検証した。

最後におまけとなりますが、SUPLサーバに対しては携帯のようにIMEIを渡すわけではなく、問い合わせホストのGlobal IPを渡すようにしてみています。

HDL-AAX2の修理

March 17, 2024

自宅NASのIO-DATA HDL-AAX2から少し異音がしていたので確認してみたところ、ファンから異音が出ていました。そこで修理をしてみることにしました。

HDL-AAX_fan_before_Sunon.jpg

元々ついていたファンはSunonのHA40101V4-1Q01C-F99というファンでした。残念ながら全く同じ型番のファンを見つけることができませんでしたが、DC12Vで40mm角の10mm厚、回転パルス出力付きのものであれば交換可能だろうということで、違うものに変えてみました。選んだのはAINEX CFY-40SAです。

HDL-AAX_fan_after_AINEX.jpg

ぴったりはまりました。コネクタだけは加工する必要があって、秋月電子千石電商などで買えるJST XHシリーズの3ピンコネクタ(ハウジング:XHP-3, コンタクト:SXH-001T-P0.6)に付け替えています。

ExcelでMarkdownの表を編集

July 03, 2023

先日boost::math::distributionsのRuby gemを公開しましたが、その時にboostのバージョンによって含まれている分布の違いの一覧表を作りました。Markdownで作ったのですが、編集は元情報のExcelでやって、そこに便利なExcelアドインCopyToMarkdownAddInでMarkdownの表形式にコピペ(エクスポート)をしていました。逆コピペ(Excelにインポート)もできる優れものです。便利なツールがあって助かりました。
またハイパーリンクを付けても機能するようにしたかっので、少し改修して使いました。現在PRしたので、もしかしたらそのうちまーどされるかもしれません。

Rubyで確率分布の性質を求めるgem

June 24, 2023

Rubyで確率分布の性質、例えば標準偏差が1、平均が0の正規分布において50%点はどこかというと0、といったことを求められるようにgemを作ってみました。boost_distributionsというgemで、名前が示す通りC++の標準的なライブラリであるboostの1パッケージとして確率分布を扱っているboost::math::distributionsを呼び出せるようにしてみました。

Githubのレポジトリでコードを公開しています。インストール方法(gemの前にboost本体のインストールが必要)や、使い方概要もそちらご参照ください。

実は2020年に書いていたコードがようやくgem化された形になります。gem化するにあたって、一緒にコンパイルするboostのバージョン依存性を吸収するなどの細工(ラッパーC++コードを生成するためのswigインターフェイスファイル BoostDistributions.i参照)をしています。