LoginSignup
145
147

More than 5 years have passed since last update.

pythonで簡単にGPU計算ができるCupyを紹介

Last updated at Posted at 2018-04-23

Cupyについて

pythonで行列計算をする場合は通常CPUで計算するNumpyを使いますが、行列数が多い場合はGPUで計算ができるCupyが便利です。
GPUはコア数が圧倒的の多いので場合によっては数倍~数百倍で計算できることがあります。
参考:CupyとNumpyのパフォーマンスを比較してみた

Cupyは元々DeeplearningのフレームワークのChainerの一部でしたが、Chainerのv2よりCupyが分離されました。
簡単なコードで手軽にGPU行列計算ができるので、物理シミュレーションなどにも使ってみるとよいかもしれません。

環境

現状linuxの方が簡単にインストールできると思いますが、Windowsでも動かないわけではありません。
(公式にはサポートされてないですし、どうも動かないときは動かないです。。)
 ※2018/4/27追記:今後cupy v5ではwindowsがサポートされいるかもしれません。
 https://www.slideshare.net/pfi/cupy-v4-and-v5-roadmap

 ※2018/5/25追記:cupy v5.0.0b1よりwindowsにおけるwheelでのインストールが試験的に始まりました。
  cudaのバージョンに合わせて以下のようにインストールが試せます

pip install cupy-cuda80
pip install cupy-cuda90
pip install cupy-cuda91

とりあえず、今回のテスト環境は以下で行いました。

  • Windows 10 Professional
  • CPU:Core i5-6600(3.9GHz、4コア)
  • GPU:GeForce GTX 1070(1.8GHz、1920コア)
  • Visual C++ Build Tools
  • CUDA Toolkit 8.0 (8.0.44)
  • cuDNN 6.0
  • Anaconda3 5.1 (Python 3.6)
  • Cupy 4.0.0

簡単な使い方

使い方は簡単で、下のようにnumpyと同じようにcupyを使うだけで行列の足し算や積などいろいろできます。
ただし、numpyで使われる一部の関数はcupyで使えないものもあるのでcupyの公式ドキュメントを参照してみてください。

以下のソースはこちら

配列の生成

import cupy as cp
A = cp.arange(9).reshape(3, 3).astype('f') #cupy上で3*3の行列を生成
B = cp.arange(9).reshape(3, 3).astype('f') #cupy上で3*3の行列を生成
print('A = \n', A)
print('B = \n', B)

-----------
A = 
 [[0. 1. 2.]
 [3. 4. 5.]
 [6. 7. 8.]]

B = 
 [[0. 1. 2.]
 [3. 4. 5.]
 [6. 7. 8.]]

行列の和、積

C = A + B #行列の和
print('和:A + B = \n', C)

D = cp.dot(A, B) #行列の積
print('積:A・B = \n', D)

-----------
和:A + B = 
 [[ 0.  2.  4.]
 [ 6.  8. 10.]
 [12. 14. 16.]]

積:A・B = 
 [[ 15.  18.  21.]
 [ 42.  54.  66.]
 [ 69.  90. 111.]]

numpyの配列 ⇔ cupyの配列の変換

cupyで定義した配列はGPU上にあるので、そのままだと他のライブラリで使えないことが多いです。
また、逆にnumpyの配列をcupyの配列に変換して、GPU上で計算したいこともよくあります。

numpy配列とcupy配列の変換は「cupy」の関数
・cupy ⇒ numpy配列へ変換:cupy.asnumpy
・numpy ⇒ cupy配列へ変換:cupy.asarray
を使うとできます。

E = cp.arange(9).reshape(3, 3).astype('f') #cupyで生成するとcupy配列
print('「E」のクラスは', type(E)) 

E_np = cp.asnumpy(E) #cupy ⇒ numpy配列へ変換
print('「E_np」のクラスは', type(E_np))

E_cp = cp.asarray(E_np) #numpy ⇒ cupy配列へ変換
print('「E_cp」のクラスは', type(E_cp))

-----------
「E」のクラスは <class 'cupy.core.core.ndarray'>
「E_np」のクラスは <class 'numpy.ndarray'>
「E_cp」のクラスは <class 'cupy.core.core.ndarray'>

2次元フーリエ変換

Cupy v4より2次元フーリエ変換も使えるようになりました。

numpyでの2次元FFTの参考:
Pythonで画像処理(2次元FFTとパワースペクトル)

以下のソースと結果はこちら

下の図のような【 元画像 ⇒ フーリエ変換 ⇒ フーリエ逆変換】を

20180423_cupy_fft.png

こんなかんじで簡単にできます。

cp_fimg = cp.fft.fftshift(cp.fft.fft2(cp_img))#フーリエ変換+シフト
cp_ffimg = cp.fft.ifft2(cp.fft.ifftshift(cp_fimg))#シフト+フーリエ逆変換
#(一部略)

4096*4096pixのモノクロ画像を10回計算した時間は
- numpy:30.4 s
- cupy:34.1 ms
と非常に高速になっていました。

145
147
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
145
147