#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とパワースペクトル)
以下のソースと結果はこちら
下の図のような【 元画像 ⇒ フーリエ変換 ⇒ フーリエ逆変換】を
こんなかんじで簡単にできます。
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
と非常に高速になっていました。