[Cupy 10.1 対応] Arch Linux 環境で、cuSparseLt 対応の Cupy をビルドする



# やったこと
Preferred Networks が開発している、CUDA上線形代数計算ライブラリ[Cupy](https://www.preferred.jp/ja/projects/cupy/)をArch Linux でビルドする。その際、NVIDIAから新しくでたライブラリ[cuSPARSELt](https://developer.nvidia.com/blog/exploiting-ampere-structured-sparsity-with-cusparselt/)も組み込んだ。
'''1月20日'''にCupy 10.1.0 が正式リリースされた（ような）ので、作り直し。

# cuSPARSELtって何？
（自分のいい加減な理解レベルです）NVIDIAが開発したスパース行列（疎行列）計算のためのライブラリ。従来はCUDAの機能の中に、cuSPARSE というライブラリが存在している。cuSPARSELtは NVIDIA の Ampere アーキテクチャに特化した実装で、疎行列計算の高速化を目指している。現在は、仕様や対応するOS/アーキテクチャの追加変更（Ver0.1.0ではWindows/ARMなどもサポートされた）などがCUDAよりも頻繁に起こるので個別のライブラリで出しているのだろうと勝手に思っている（いずれCUDAに統合されるんだろうけど）。

cuSPARSELtは、従来（Ver0.0.1）はSM_80(DGX-A100)にしか対応してなかった。
2021年4月後半に、cuSPARSELtを組み込める[Cupy9.0](https://medium.com/cupy-team/cupy-v9-is-here-27e9cbfbf7e5)がリリースされ、ほぼ同時期に、cuSPARSELtの[バージョン0.1.0](https://developer.nvidia.com/blog/cusparselt-v0-1-0-now-available-arm-and-windows-support/)がリリースされ、SM_86（要は、GeForce RTX3090/3080/3070/3060 といったコンシューマー向けグラボ等）も動作対応するようになった。そこで、Cupy+cuSPARSELtの組み合わせが実際に動くか試してみた。
執筆時点では、[機能が追加](https://docs.nvidia.com/cuda/cusparselt/release_notes.html)された[バージョン0.2.0](https://docs.nvidia.com/cuda/cusparselt/release_notes.html)で説明している。

#ビルド方法
[GitHubリンク](https://github.com/gdaisukesuzuki/PKGBUILD_rapidsai_2112)に、PKGBUILDとかビルド順とか。で済ませたいですが、補足説明を。

#事前想定
* NVIDIA GeForce RTX30X0(Ti)を持っている人
* CUDA含めた開発環境が揃っている。
* Arch Linux の使い手。EndeavourOSなど派生ディストリビューションでもOKだが、Manjaro のように独自リポジトリを持ち、カーネル、ドライバなどのリリースのペースが異なるものは関知しません。
* yay とか PKGBUILD とかが何やってるかが、ある程度わかること。

##ビルド順
1. [cuSPARSELt](https://github.com/gdaisukesuzuki/PKGBUILD_rapidsai_2112/tree/main/cusparselt)
  通常 NVIDIAのライブラリをビルドするときは、
  a. NVIDIA の Developer Network にアカウント登録してログイン認証する.
  b. ライブラリをダウンロードする
 c. ダウンロードしたファイルを適切な場所において、makepkg コマンドを実行。
という3手間が発生するが、いまのところ、PKGBUILDファイルを置いた場所で makepkg コマンド実行すればちゃんと作られる（はず）。

2. [Cupy](https://github.com/gdaisukesuzuki/PKGBUILD_rapidsai_2112/tree/main/python-cupy)
  パッケージが不足した状態て、makepkg すると「インストールされてない！」とメッセージが出てくるので、未導入パッケージを pacman / yay でインストールすること（特に、python-fastrlock は yay でないと入れられない）

#動くか試してみる。
1 まずは、python を起動し、cupyをインポート後、設定を確認する。cuSparseLt の情報がでてくれば一応成功。

```
Python 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cupy as cp
>>> cp.show_config()
OS                           : Linux-5.16.5-arch1-1-x86_64-with-glibc2.33
Python Version               : 3.10.2
CuPy Version                 : 10.1.0
CuPy Platform                : NVIDIA CUDA
NumPy Version                : 1.22.1
SciPy Version                : 1.7.3
Cython Build Version         : 0.29.25
Cython Runtime Version       : 0.29.27
CUDA Root                    : /opt/cuda
nvcc PATH                    : /opt/cuda/bin/nvcc
CUDA Build Version           : 11060
CUDA Driver Version          : 11060
CUDA Runtime Version         : 11060
cuBLAS Version               : (available)
cuFFT Version                : 10600
cuRAND Version               : 10209
cuSOLVER Version             : (11, 3, 2)
cuSPARSE Version             : (available)
NVRTC Version                : (11, 6)
Thrust Version               : 101301
CUB Build Version            : 101301
Jitify Build Version         : 60e9e72
cuDNN Build Version          : 8301
cuDNN Version                : 8301
NCCL Build Version           : 21104
NCCL Runtime Version         : 21104
cuTENSOR Version             : 10400
cuSPARSELt Build Version     : 200
Device 0 Name                : NVIDIA GeForce RTX 3080
Device 0 Compute Capability  : 86
Device 0 PCI Bus ID          : 0000:01:00.0
>>> 


```

2 動作確認

Cupy のソースコード中に実行例が含まれているので、そこでサンプルプログラムを実行する。そこで以下のように枝刈りプルーニング前後の計算が出てくればOK。やってるのはNVIDIAの[サンプルプログラム](https://docs.nvidia.com/cuda/cusparselt/getting_started.html#code-example)をPython+Cupy の言葉で書き換えたもの。そもそも、Cupyでやってるのも、cuSPARSELtが提供する操作を Cupy の行列などの書き方でそのまま操作できるようにしていることではある。

```
% cd (置いた場所)/cupy/examples/cusparselt/
% python matmul.py 
Before pruning, A[0]:
[0.2678 0.6387 0.8125 ... 0.7817 0.26   0.1311]
After pruning, A[0]:
[0.     0.6387 0.8125 ... 0.7817 0.26   0.    ]
A.sum(axis=1): [345.2 346.2 339.8 ... 339.  347.5 339.2]
C[:, 0]: [345.2 346.2 339.8 ... 339.  347.5 339.2]
%
```

#そのほかに取り込み可能なもの
１.[cuTensor](https://developer.nvidia.com/cutensor)...GPUを使ったテンソル計算ライブラリ。
２.**cuGRAPH**...NVIDIAの rapidsai に含まれるグラフ計算処理ライブラリ。[別記事](https://qiita.com/daisuzu_/items/9a9cd44a535da0f6aed7)でビルド方法は紹介してる。

cusparseLtは、cupy のバックエンドとして使っているだけだが、上二つは、Cupy のアドオン的な使われ方のようだ。

#今後？
2021年11月9日、NVIDIAのオンラインイベントで、[cuNumeric](https://developer.nvidia.com/blog/nvidia-announces-availability-for-cunumeric-public-alpha/)という行列計算ライブラリが発表された。RapidsAIのコンポーネントで、PFN製のCupyを置き換えるためなのか、それとも共存させるのかは、まずは半年は見ておく必要がありそう。現状、CUDAまわりのコンパイラのオプション挙動が変？（プリプロセッサ部分）なのでビルドできないのだが（ベータレベルになったら手をつけよう・・・）。



#記録
1. (2021.5.18 23:18 JST)...初版
2. (2021.5.19 20:40 JST)...CUDAパッケージが更新され今のArch Linuxでもビルドできるおしらせ。
2. (2021.5.25 20:14 JST)...Cupy Ver 9.1.0 に対応。またディスクレーマーを少し修正。
2. (2021.5.28.9.15 JST)...タグ変更
2. (2021.7.21 1:13 JST)...Pythron対応パッチ& Cupy Ver 9.2.0対応。
2. (2021.8.22 15:40 JST)...Cupy Ver 10.0.0b1 対応
2. (2021.10.08 1:39 JST)...Cupy Ver 10.0.0b3 対応
2. (2021.10.16 0:52 JST)...Cupy の今後のリリース日付を記載
2. (2021.11.16 23:30 JST)...Cupy Ver 10.0.0rc1 対応ついでにCUDA11.5対応。また、cuNumeric についても軽く触れた。
2. (2021.11.18 08:55 JST)...cuGRAPHビルド記事を作ったのでそのリンク。
2. (2021.12.10 12:50 JST)...Cupy Ver 10.0.0 対応 (正式版)
2. (2021.12.21 19:45 JST)...Python3.10 対応＆記述ミスの訂正
2. (2022.2.4 10:35 JST)...Cupy Ver 10.1.0 対応


#おことわり
この記事は、筆者以外の方の環境でも同様に成功することを保証するものではありません。**ビルドや動作確認の失敗**、（ないとは思いますが）**環境が破壊されても責任は一切負いかねます**（基本的には自己責任でお願いします。）。

#今回紹介したリンク
[https://github.com/gdaisukesuzuki/PKGBUILD_rapidsai_2112](https://github.com/gdaisukesuzuki/PKGBUILD_rapidsai_2112)