Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.                     Upcoming SlideShare
Loading in …5
×

# CuPy解説

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

• Full Name
Comment goes here.

Are you sure you want to Yes No
Your message goes here • Login to see the comments

### 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