Numo::NArrayを理解するための準備の準備 - リポジトリ全体の観察編

## はじめに

RubyにはNumPyのように行列計算を行うライブラリとして、NArrayというものがあります。

https://github.com/ruby-numo/numo-narray

NArrayはあまり高くありませんが、旧NArrayも含めると20年以上の歴史をもち、その性能の高さからRubyのAI関係のライブラリではデファクトスタンダートとなっています。

NArrayはC言語で書かれているので読み解くのが私にとっては難しくて、趣味でプログラミングを勉強し始めてからNArrayのコードを理解するというのが一つの大きな目標になっていました。

通常はQiitaは、ある程度ものごとを理解したと思ってから書くことが多いのですが、NArrayは私にとってはラスボスなので、全容を理解してから書こうと思うと歳をとってしまいます。そこで、ちょこちょこ雑なメモのような記事を書きますがお許しください。

## NArrayのコンパイル

```sh
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 というファイルがあり、これを読むと、行列のサイズが増減するなど、新たなメモリ確保が必要になるようなメソッドを中心に記述されていることがわかります。

https://github.com/ruby-numo/numo-narray/blob/master/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](https://jupyter.org/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](https://www.kurims.kyoto-u.ac.jp/~ooura/fft-j.html)と呼ばれる　高速フーリエ/コサイン/サイン変換 のパッケージだそうです。Numo::NArrayシリーズには、[Numo::FFTW](https://github.com/ruby-numo/numo-fftw) もありますが、デフォルトではこちらが利用されるのでしょうか？

https://www.kurims.kyoto-u.ac.jp/~ooura/fft-j.html

### lib

lib はRubyのファイルが含まれています。

## まとめ

え、もうこの記事おしまい？
と思ったかも知れませんが、おしまいです。

私の頭だと、Numo::NArrayを理解するのはかなり難しいことです。十分に理解できていないなあと思うと、そこで思考と手がストップしてしまい、そうやって10年が過ぎてしまいました。

なので１回あたりの勉強量はこのぐらいにとどめて、恥ずかしいぐらい低品質でもアウトプット優先でやっていきたいです。（線形代数もなにもわかってないしね）

完全にプログラミング初心者に戻った気持ちですね。

この記事は以上です。

## 次の記事

https://qiita.com/kojix2/items/096ff319df38b05334b1