MemoryViewのラッパー
StringとかFiddle::Pointerとかその他のRubyオブジェクトをラップするオブジェクト。 MemoryViewのために必要だけど元のオブジェクトに欠けている項目は、ラップする時にユーザーから受け取る
code:ruby
Wrapper.new(binary_string, shape: 2, 3) みたいな感じ
「ラッパー」というのはちょっと言葉が違うのかも。
shapeがNULLの時に自動的に他の要素から決められるとかあるのでそこだけケアする
Fiddle::Pointerみたいにフォーマットや型がないやつにその情報を持たせられるようにする意味はある。C拡張でラッパーを書く価値がはある
Stringも同様。OnnxRuntimeではStringを渡すとゼロコピーで使ってくれるけど、一般にそれをやるにはラッパーが必要
Stringを受け取ってそのポインターからデータを読み込むこと自体はC拡張で今でも可能
Fiddle::Pointerと同様で、formatとかshapeとかそういう情報を持たせる意味はある
すると、OrtValue.from_memory_viewだけで追加して、あとはラッパーでなんとかできる
手探りだけどこんな感じ:
READMEアウトライン
一言説明
NDAVはMemoryView(Pythonで言うbuffer protocol)の薄いラッパーで、各多次元配列を扱うライブラリーで共有するグルー(相互運用レイヤーの方が?)になることを意図したライブラリーです。
code:txt
NDAV is a thin wrapper around Ruby's MemoryView.
It provides a common multidimensional array view that can be shared
between libraries such as Torch, Numo::NArray, and ONNX Runtime.
図
SYNOPSIS
一番使いそうなコード例
概要
ライブラリー間で簡単に変換できるようにすることで、自分で計算したテンソル、機械学習の推論エンジン、画像やオーディオデータなどを相互に変換できるようにすることを意図しています。
ゼロコピーです
code:txt
NDAV acts as a glue layer between these libraries,
allowing data to be shared without copying.
背景
Numo::NArray
こうした変換にはNumo::NArrayがよく使われている
しかしNumo::NArrayから他の形式に変換する際にはコピーが発生する
Numo::NArrayはメモリービューをエクスポートしないし、受け取ることもできない
Red Arrow
MemoryViewのエクスポートであればRed Arrowが対応している
配列はMemoryViewエクスポートできるが、テンソルはできない
Numo::NArrayとの相互変換機能を提供するライブラリーもある
一次元配列であれば正直Red Arrowはかなりいい。が、Torch::Tensor -> Numo::NArray -> Red Arrow -> MemoryViewと変換する手間がある。簡単ではあるが、何段階もあるので億劫になる
MemoryViewを受け取ることはできない
使い方
Torch::Tensor#to_ndav / NDAV#to_torch_tensor
OrtValue.from_ndav(tensor) / NDAV.from_ort_value(tensor)
OrtValue(tensor) / NDAV(tensor)
メモリー管理の注意点
NDAVはメモリーを共有する
変換後に元のオブジェクトでメモリーを変更すると、変換後のオブジェクトにも反映されるので注意
変換元オブジェクトがRubyのGCで解放されるとダングリングポインターになる
主にブリッジ制作者が気を付けるべきだが、ブリッジにバグがあるとユーザー側が問題に直面する
のでここで書いておいたほうがいい?
インストール方法
ブリッジ
ブリッジ一覧
ndav-ort_value
ndav-torch-tensor
ndav-numo-narray
ndav-onnxruntime-torch-tensor
ブリッジの作成。ライブラリー作成者向け
ブリッジを作るより、元のライブラリーにMemoryViewをエクスポートさせてほしい。本人であれば実装、そうでなければ要望を出す。
MemoryViewとは
しかし、ライブラリーの作者本人でなかったり、手早くやりたい場合はNDAVのブリッジを使うのもいい
(NDAVを使うとライブラリー製作者じゃない人も手早くブリッジを作れる)
実装方法
コンテナーモジュールを用意する
FromNDAVとToNDAVを実装する
FromTorchTensorとToTorchTensorは自動導出される
オプションでConverter::TorchTensor()を実装する
メモリー管理の注意点
基本的には参照を使ってゼロコピーにする
RubyのGCで変換前のオブジェクトが解放されるとダングリングポインターになる
コード例
RubyのGCとは関係なく、変換前のオブジェクトのCのレイヤーでメモリーが開放されることもある
SEGVを引き起こす
RubyのGCがCのポインターを追跡できないので
NDAVからの変換では、メモリー領域を指すポインターを共有するStringを使って、Rubyオブジェクトのインスタンス変数に埋め込むのが典型的なリスク軽減手段
NDAVへの変換ではlifetime引数にオブジェクトを渡せるので、それを使うこともできる
将来
MemoryViewが広まればこのライブラリーは役割を終える