読者です 読者をやめる 読者になる 読者になる

ChainerのCupyでGPUを有効活用しよう

お久しぶりです、@mktozkです。 2ヶ月くらいブログの更新をしてませんでした。 おちこんだりもしたけれど、私はげんきです。

さて、今日はディープラーニングのフレームワークであるChainerに含まれているCupyというライブラリについて話します。 ChainerはCupyを使って様々な計算をGPU (CUDA) で行っています。 今回はこのCupyを使って楽に色んな計算をGPUに投げることを目指します。 ディープラーニングの話は全くしません。

chainer.org

この記事を読んだらわかること

  • Cupyの使い方
  • CupyとNumpyの両方に対応したコードの簡単な書き方

この記事には書いてないこと

この記事で使用したコードはここここから取得できます。

ちなみに、Chainerはv1.5.1です。


GPUは速い

まず、どうしてCPUではなくGPUで計算を行いたいのでしょうか。

なぜなら、同じ処理でも、GPU実装はCPU実装よりも計算が速いことが多いからです。 例として、行列の掛け算を行います。

CPUの場合。

f:id:mktozk:20151216003934p:plain

GPUの場合。

f:id:mktozk:20151216003938p:plain

GPUのほうが1000倍以上速い!

ということで積極的にGPUを使いましょう。 以下はGPUに関する関連資料です。

www.slideshare.net

Cupyとは

さて、前置きはこのくらいにしてCupyの話です。

CupyはディープラーニングのフレームワークであるChainerのGPUバックエンドです。 ChainerではPyCUDAやscikit-cudaをGPUバックエンドとして使用していましたが、v1.3からCupyに置き換えられました。

CupyはNumpyとの互換性が強く意識されています。 つまり、Numpyと同じ書き方をするだけで、GPU上で計算できるということです。

Cupyの導入

CupyはChainerに含まれているので、ChainerをインストールすればCupyも自動的にインストールされます。 Chainerのインストール方法については、公式のガイドを参照してください。

Cupyの使い方

とりあえず numpy -> cupy

numpy の代わりに cupy を使う(だいたい動く)

CupyはNumpyとの互換性が高いので、本当にだいたい動きます。レッツトライ!

numpy -> cupy で動かない場合

行列の各行についてノルムを計算したい場合、Numpyではnumpy.linalg.normのようにして計算できますが、cupy.linalg.normはまだ実装されていません。

f:id:mktozk:20151216005111p:plain

このようにCupyで実装されていない処理を行いたい場合は、どうにかして既存のCupyの関数で実装してみましょう。 例えば、先ほどのノルムの計算はこのように書くことができます。

f:id:mktozk:20151216005541p:plain

このように、自分が行いたい処理を分解することでCupyで実装できます。

(ちなみに、ユーザー定義カーネルを使って計算する方法がここにあります)

NumpyとCupy互換のコードの書き方

ここにいくつかの例をあげました。 また、chainer.functionschainer.linksのコードを読むのも参考になると思います。

ところで、GPUは速い場合が多いですが、そうでない場合もあります。 GPUが得意な計算とそうでない計算があるからです。

例えば、画像から小さい領域(パッチ)を取り出す処理をCupyで書いてみました。

f:id:mktozk:20151216011519p:plain

CPUとGPUの速度比較をしてみると...

f:id:mktozk:20151216011617p:plain

(CPUとGPUの得手不得手を考えれば当たり前ですが)GPU10倍遅いという結果に。

したがって、なんでもかんでもGPUに投げれば良いというわけではないのです。 ですが、NumpyとCupyのどちらでも動くコードを書いておけば、速度比較が簡単にできて便利です。 臨機応変にNumpyとCupyを使い分けましょう。

この場合なら、

image = cuda.to_cpu(image)
patches = im2patch(image, patch_size, stride)

とすればCPUで実行できます。

まとめ

今回はCupyというライブラリを紹介しました。 また、速度比較やNumpy互換なコードの書き方を紹介しました。

Cupyの存在意義がChainerのGPUバックエンドというだけではもったいないので、Cupy自体を積極的に使いましょう!

繰り返しですが、コードはここ、またはここにありますので、ご参考までに。