Successfully reported this slideshow.                     Upcoming SlideShare
×

# CuPy解説

114,897 views

Published on

CuPyの簡単な解説を行います。NumPyと比較してCuPyによりどのくらい早くなるかや、利用上の注意点（メモリプール）について説明します。
ElementwiseKenrnel, ReductionKernelの使い方も解説します。
CuPyの実装のすごーくざっくーりした全体概要にも触れます。

Published in: Software
• Full Name
Comment goes here.

Are you sure you want to Yes No • Dating for everyone is here: ❶❶❶ http://bit.ly/39sFWPG ❶❶❶

Are you sure you want to  Yes  No
• Dating direct: ❶❶❶ http://bit.ly/39sFWPG ❶❶❶

Are you sure you want to  Yes  No

### CuPy解説

1. 1. CuPy解説 2015/12/19 Chainer Meetup #1@スマートニュース （株）Preferred Networks 奥田 遼介
2. 2. 自己紹介 奥田 遼介  -2014東北大学 修士  文字列処理など  2014 （株）プリファードインフラストラクチャー  2014- （株）プリファードネットワークス  映像解析系、製造業系にかかわる研究開発  ChainerやCuPyの開発 2
3. 3. 何を話すか？  CuPyの簡単な解説  Cupyでどのくらい早くなるか？  利用上の注意点  ElementwiseKenrnel, ReductionKernelの使い方解説  CuPyの実装のすごーくざっくーりした全体概要 3
4. 4. CuPyとは何か？  CUDA上で計算を行うNumPyサブセットのライブラリ  関数・メソッドのサブセットを実装  Chainer v1.5.0では 約174個の関数が実装済み  行列積などはcuBLASを利用（高速）  配列のスライス、転置、reshape 等が自由にできる  カスタムカーネルの記述も可能  elementwise, reduction  とにかく簡単にGPUが使える事を追求  Python上で簡単に多次元配列といえばNumPy  PC上で簡単にGPUといえばCUDA  CUDA ＋NumPy ＝CuPy 4
5. 5. CuPy の使い方は？  numpy の代わりに cupy を使う（だいたい動く）  CPU/GPU の両方で動く関数の書き方  chainer.cuda.get_array_module() を使うと、引数に cupy.ndarray があるかないかで numpy / cupy のどちらかを返してく れます  例えば下は NumPy と CuPy の両方で動く logsumexp の実装例  （より省メモリな実装を考えてみてください） def logsumexp(x, axis=None): xp = cuda.get_array_module(x) x_max = x.max(axis=axis) return x_max + xp.log( xp.exp(x – x_max).sum(axis=axis)) 5
6. 6. CuPyってどのくらい早くなるの？  状況によりけりですが、最大数十倍程度速くなります def test(xp): a = xp.arange(1000000).reshape(1000, -1) return a.T * 2 test(numpy) t1 = datetime.datetime.now() for i in range(1000): test(numpy) t2 = datetime.datetime.now() print(t2 -t1) test(cupy) t1 = datetime.datetime.now() for i in range(1000): test(cupy) t2 = datetime.datetime.now() print(t2 -t1) 時間[ms] 倍率 NumP y 2929 1 CuPy 585 5 6
7. 7. 5倍しかなってない！もっと早くならないの？  なります  メモリープールを有効にしましょう  cupy.cuda.set_allocator(cupy.cuda.MemoryPool().malloc)  面倒であれば「import chainer」でもOK  なぜ早くなるか？  CUDAではmalloc, freeの実行時にCPUとGPUが同期する  CuPyでは一度mallocした領域を使いまわすことで同期を回避 cupy.cuda.set_allocator(cupy.cuda.MemoryPool().malloc) test(cupy) t1 = datetime.datetime.now() for i in range(cnt): test(cupy) t2 = datetime.datetime.now() print(t2 -t1) 時間[ms] 倍率 NumPy 2929 1 CuPy 585 5 CuPy メモリプール 123 24 7
8. 8. Chainer（CuPy）が遅い・・・・？  v1.5からものすごく速くなりました！  v1.4まではCuPyのコードがPythonだったので遅かった  なので、Cythonにしました  例えば、Chainerから見るてどのくらい早くなったか？ 速度 mnis t ptb v1.4.1 1.0 1.0 v1.2 (pyCUDAの 頃) 2.3 1.6 v1.5 (cython) 2.6 1.2※ ※ GradientClippingが行われるようになってちょっと計算量が増えています 8
9. 9. おわり（その１）  ここより下のスライドはよりCuPyを活用したい人のた めの情報です  Elementwise,Reductionを作りたい人以外には不要な情 報です。 9
10. 10. Elementwiseな操作をしたい時は？  要素ごとの2乗誤差をとる関数を定義  使い方  ブロードキャストや型チェックは全自動 squared_diff = cupy.ElementwiseKernel( ‘float32 x, float32 y’, #入力 ‘float32 z’, #出力 ‘z = (x - y) * (x - y)’, #計算 ‘squared_diff’) #名前 squared_diff(cupy.arange(10), 10)) 10
11. 11. 型をジェネリックに扱いたい時は？  1文字の型名はプレースホルダーになる squared_diff = cupy.ElementwiseKernel( ‘T x, T y’, //入力 ‘T z’, //出力 ‘z = (x - y) * (x - y)’, //計算 ‘squared_diff’) //名前 11
12. 12. 配列に自由にアクセスしたい時は？  例えば、bincountがしたいときは？  「raw」をつけると配列の添え字アクセスができる for x in arr_x: bin[x] += 1 cupy.ElementwiseKernel( 'S x', 'raw U bin', 'atomicAdd(&bin[x], 1)', 'bincount_kernel') 12
13. 13. Reduceしたい時は？  例えばL2距離  使い方  「axis」や「keepdims」などのオプションも使えます l2norm_kernel = cupy.ReductionKernel( 'T x', # 入力 'T y', # 出力 'x * x', # 前処理 'a + b’, # リデュース 'y = sqrt(a)', # 後処理 '0', # 初期値 'l2norm') # 名前 x = cupy.arange(10, dtype='f').reshape(2, 5) L2norm_kernel(x, axis=1, keepdims=True) 13
14. 14. おわり（その２）  ここより下のスライドはよりCuPyを作りたい人のため の情報です  NumPyのかわりにCuPyを使いたいだけの人には完全に 不要な情報です 14
15. 15. CuPyの実装が知りたい時は？  コードを読んでください  今回はとてもざっくりと全体の概要だけ説明します 15
16. 16. CuPyの全体構造は？  大まかに3層構造 CUDA(cuBLAS, cuRNAD, cuDNN) ndarray ufunc, elementwise, reduction CUDA Python wrapper cupy.cuda cupy.core 関数群（演算、テンソル操作） cupy 16
17. 17. CUDA Python wrapperとは？  薄いラッパー  driver.pyx, runtime.pyx, cublas.pyx, curand.pyx, cudnn.pyx  C関数をPython関数にする  cupy_cuda.h, cupy_cudnn.h  CUDAが無い環境でCuPyをインストールするためのヘッダ  少し厚めのラッパー  memory.pyx GPUのポインタをくるむ  function.pyx CUDAのkernelとmoduleをくるむ  compiler.pyxcuファイルのコンパイルを支援  stream.pyx streamとeventをくるむ 17
18. 18. ndarray の実体ってどうなっているの？  Cython側の実装：cupy/core/core.pyx  CUDA側の実装：cupy/core/carray.cuh  メンバとしては以下のようなものを持っている  詳しく説明しません template <typename T, int ndim> class CArray { private: T* data_; int size_; int shape_[ndim]; int strides_[ndim]; 18
19. 19. cupy.add(x, y)を実行したら何が起こるのか？  とても複雑なことが起きます  ufunc の__call__が呼び出される  引数のオプションを解決（args, kwdargs）  引数の個数チェック  引数のdeviceをチェック  引数の型を正規化  ブロードキャストを実行  add をどの型の組み合わせで実行するかを解決  戻り値の割り当て実行  計算が高速に実行できるように引数を最適化  CUDAのカーネルコードを生成（キャッシュ付）  CUDAのカーネル呼び出しのための引数を構築  カーネル呼び出しを実行 19
20. 20. CuPyの機能が足りないと思った時は？  もう一度よく考える  NumPy/CuPyでは別の方法で同じことができる場合も多いです  複数の関数とIndexingの組み合わせで結構どうにかなります  ぜひPRを！  NumPyの機能をCuPyに移植したPRは基本マージされます  効率は特に考えなくて良いので、まずは実装してみてください 20
21. 21. おわり（まとめ）  ぜひCuPyを活用してください  Preferred Networksでは人材採用に力を入れています  フルタイム、アルバイト、インターンなどに興味のある 方はホームページからコンタクトお願いします  https://www.preferred-networks.jp/job_ja 21