はじめに
RubyにはNumPyのように行列計算を行うライブラリとして、NArrayというものがあります。
NArrayはあまり高くありませんが、旧NArrayも含めると20年以上の歴史をもち、その性能の高さからRubyのAI関係のライブラリではデファクトスタンダートとなっています。
NArrayはC言語で書かれているので読み解くのが私にとっては難しくて、趣味でプログラミングを勉強し始めてからNArrayのコードを理解するというのが一つの大きな目標になっていました。
通常はQiitaは、ある程度ものごとを理解したと思ってから書くことが多いのですが、NArrayは私にとってはラスボスなので、全容を理解してから書こうと思うと歳をとってしまいます。そこで、ちょこちょこ雑なメモのような記事を書きますがお許しください。
NArrayのコンパイル
git clone https://github.com/ruby-numo/numo-narray
cd numo-narray
rake compile
コードの量をつかむ
まずは tokei
コマンドでコードの量を把握します。
===============================================================================
Language Files Lines Code Comments Blanks
===============================================================================
C 96 18424 14378 2436 1610
C Header 31 3456 2791 185 480
Ruby 29 5484 4488 585 411
===============================================================================
ほとんどのコードはCで実装されている
多くの部分がC言語で実装されていることがわかります。C言語は約20000行弱あります。
しかし、numo-narray は erb テンプレートで C言語のコードを書くという、あまり見られない特殊な技法で書かれています。(この技法によってなかなかRuby関係者以外の開発者が参入しなくなっている状況があると、どこかで作者が述べられていた気がします)ですから、実際には一部のC言語のコードは数倍に増加しますので、これよりも多くのコードがあると考えなければなりません。しかし、それらの多くは型が異なる共通コードでしょうから、複雑さの指標としてはこのぐらいの行数だと思っても良いでしょう。
すこし話題はずれますが、ヘッダーの行数がそれほど多くないことから、header に処理内容を書くタイプのライブラリにはなっていないことがわかります。つまり、NArrayからRubyに依存する部分を整理して切り出すことによって、汎用のC言語の行列計算ライブラリとして使うことができるかもしれません。
Rubyで実装されている部分もある
次に、Rubyの行数も5000行ありますが、これは実際にはもっと少ないです。というのは、現在では全く使われていない setup.rb というファイルがこのうちの 1295行を占めており、テストコードも 863行を占めているからです。
それでも、./lib/numo/narray/extra.rb というファイルがあり、これを読むと、行列のサイズが増減するなど、新たなメモリ確保が必要になるようなメソッドを中心に記述されていることがわかります。
ディレクトリの構造
次にディレクトリの構造を観察しましょう。
tree -d
├── binder
├── doc
├── ext
│ └── numo
│ └── narray
│ ├── gen
│ │ ├── def
│ │ ├── tmpl
│ │ └── tmpl_bit
│ └── numo
│ └── types
├── fft
├── lib
│ └── numo
│ └── narray
└── test
17 directories
binder
binder ディレクトリは、おそらくbinderプロジェクトに関係するもので見る必要はありません。
doc
doc ディレクトリは、よくあるドキュメントが自動生成されるディレクトリではありません。Numo::NArrayの開発メモと思われるファイルがいくつか入っている重要なディレクトリです。現時点では読んでもわからないのでChatGPTに要約してもらいました。
ファイル名 | 内容の概要 |
---|---|
api.ja.md | NArrayのAPI仕様について記述されている。特にNArrayの型、ループ処理、インプレース操作について説明。また、イテレータ関数の実装例や関連するC言語の構造体について詳しく説明。 |
memo.ja.md |
メモリーリークを防ぐために、メモリをスタックに確保する方法とその実装を改善するためのアイデアを記述。特に、ndfunc_t 構造体 をスタックでどう扱うかについて説明。 |
note.md | Numo::NArrayに関する一般的なノート。RSpecの実行方法や、YARDを用いたドキュメント生成の手順について説明。 |
memo2.ja.md | NArrayの演算処理における詳細な考慮点を記述。具体的な関数の動作や特別な処理(例えば、inplaceの取り扱いやキャスト処理の判定)についての説明、およびna_ndloopの詳細な処理の流れに関するメモ。 |
ext
ext ディレクトリはRubyのC拡張つまり、NArrayの本体が配置されている場所です。
fft は、大浦のFFTと呼ばれる 高速フーリエ/コサイン/サイン変換 のパッケージだそうです。Numo::NArrayシリーズには、Numo::FFTW もありますが、デフォルトではこちらが利用されるのでしょうか?
lib
lib はRubyのファイルが含まれています。
まとめ
え、もうこの記事おしまい?
と思ったかも知れませんが、おしまいです。
私の頭だと、Numo::NArrayを理解するのはかなり難しいことです。十分に理解できていないなあと思うと、そこで思考と手がストップしてしまい、そうやって10年が過ぎてしまいました。
なので1回あたりの勉強量はこのぐらいにとどめて、恥ずかしいぐらい低品質でもアウトプット優先でやっていきたいです。(線形代数もなにもわかってないしね)
完全にプログラミング初心者に戻った気持ちですね。
この記事は以上です。
次の記事