ボイラーのチラシ裏

テクノロジーやフィギュア、ゲームに関すること

.NETコードからCuPyを使用できるラッパーライブラリを作った

こんばんは。

まえおき

私には、AI開発やってみたいなぁというささやかな望みがあるのですが、AI開発のためにPythonの軍門に下るのは何か違う気がして。

で、世の中には.NETコードからNumpy等のAI開発でよく利用されているライブラリを作って、利用できるようにしている謎?の団体「SciSharp」がいらっしゃる様子。

NuGet Gallery | SciSharp

SciSharpが作ったTensorFlow.NETを利用するのも悪くなかったと思うのですが、何せまだまだ私自身の理解が浅いので、書籍「ゼロから作るディープラーニング」シリーズの著者の斎藤 康毅(さいとう こうき)さんが開発したDeZeroを見よう見真似で.NETに移植してみようというのが私の野望です。

で、「ゼロから作るディープラーニング③ フレームワーク編」を読んでみますと、ステップ52 GPU対応という節があります。

えっ、NumpyってGPU対応してないの?と思った方、安心してください。私も最初はそう思いました。

Numpyの互換でGPUに対応しているライブラリを、株式会社Preferred Networks さんが作っています。

CuPy(クーパイ)というライブラリです。

www.preferred.jp

そして、話は戻りますが、Numpy.NETのIssuesにこんなIssueが立てられていました。

github.com

「Is there a way to support CuPy too? Their Python call APIs seem to be the same.」 (CuPyもサポートする方法はありますか?Pythonの呼び出しAPIは同じようです。)

「I am not gonna be able to do it for lack of time. Sorry, but if you are interested you could look at how I did it with Numpy and do the same.」 (時間がなくてできないんだ。申し訳ないが、もし興味があれば、僕がNumpyでどのようにやったか見て、同じようにやってみるといい。)

と言っていたので、まずはNumpy.NETを真似て、CuPy.NETという.NETライブラリを作ってみようということになりました。それが、去年2023年2月頃。

私のデスクトップPCに搭載されているGPUGeForce GTX 1080 でもはや化石です。最初はAWSGPU付きWindowsインスタンスを借りようということになりました。

いざ借りてみると月額2000~3000円かかります。ケチな私はAWSインスタンスを使うのを止め、myデスクトップPCでがんばることにします。

そして、月日は経ち、先日CuPy.NETのv2.1.0をリリースできました。

www.nuget.org

(まえおき長いよ!)

今週のお題

さて、CuPy.NETを作ったので、これを使って、Numpy互換のメソッドを触ってみようと思います。

今回のサンプルコードはこちら↓

github.com

サンプルコンソールアプリケーションプロジェクトを作り、NuGetでCuPy.NETをインストールします。

そして、Program.csに書くコードは以下の通り。

using Cupy;
using Python.Runtime;

Runtime.PythonDLL = @"C:\Users\boiler\AppData\Local\Programs\Python\Python311\python311.dll";
PythonEngine.Initialize();

// before starting the measurement, let us call CuPy once to get the setup checks done. 
cp.arange(1);

var a1 = cp.arange(60000).reshape(300, 200);
var a2 = cp.arange(80000).reshape(200, 400);

var result = cp.matmul(a1, a2);

Console.WriteLine(result.repr);

2つのNDarrayから行列積をとった結果をコンソールに表示するだけのサンプルです。

これを実行するとこのようになります。

サンプルコンソールアプリケーションを実行した結果

これを見ると、とりあえずNDarrayの各要素がきれいに並べて出力できていることがわかります。

このきれいに並べて出力するのに1年かかってしまったのです。。。自分って凡人だなぁ。。。

まあまあ、とりあえず第一歩は踏み出せたのではないでしょうか?

そう自分に言い聞かせることにします。

サンプルコードの解説

Runtime.PythonDLL = @"C:\Users\boiler\AppData\Local\Programs\Python\Python311\python311.dll";
PythonEngine.Initialize();

CuPy.NETが利用しているPythonnetライブラリを使う時は、Runtime.PythonDLLプロパティに端末にインストールされているPythonのDLLへのフルパスを指定してあげる必要があります。(あっ、もしかしたら環境変数PATHを通しておけば、フルパスでなくても大丈夫かも?未確認です。) その後の、PythonEngine.Initialize()を実行して文字通りPythonエンジンを初期化します。これで準備OKと言いたいところですが、CuPy.NETを使用するにも制約があります。

詳しくはCuPy.NETのREADMEをご覧いただきたいのですが、ハードウェアについてはもちろんNVIDIA GPUは必要ですね。そしてソフトウェアにもVisual Studio 2022、CUDA Toolkit 12.3、cuDNNのインストールが必要となっています。

github.com

このあたりの解説はまた別の機会にすることにしましょう。

次回予告

ゼロから作るディープラーニング③ ステップ52 GPU対応を読んでみると CPU演算しかできない時はNumpyを、GPUが使える時はCuPyを使うみたいな使い分けをしていました。私もそれを真似て、Numpy ✕ CuPyのハイブリットライブラリを作ってみようと足掻く話をしたいです。