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.
GPUをJavaで使う話
(来れたので)
2015/10/16 きしだ なおき
自己紹介
●
最近、化物語を見ました。
今日の話
●
GPU速そう
●
Cめんどい
●
Javaでやりたい
●
ディープラーニング書いてみた
●
高速化してみた
CPU
●
高機能・高性能・高粒度
●
OSが実行できる
●
演算器はコアあたり10個程度
– 一チップに100個程度
●
明示的にメモリを制御できない
– いかにキャッシュに載せるか
●
= いかにメモリをまとめて扱うか
GPU
●
GPU
– ちょうたくさんコアがある
– 同じ処理を行う
– 行列計算に向いてる
● GTX 970
– 1664コア!
– 衝動買い!
GPUの構成
●
いくつかのコアでグループを作る
– 同時に同じ命令を実行する
– グループだけからアクセスできるメモリをもつ
●
コアのグループが多数ある
●
コアのグループあたり数個の演算器
– 数千から数万の演算器
– グループ内では同じ...
GPUの製品
● NVIDIA
– GeForce
– Tesla
● GPGPU専用
● AMD
– Radeon
● Intel
– Intel HD Graphics
● CPUチップに内蔵されたGPU
GPGPU
● General Purpose computing on GPU
● GPUで汎用計算
● シミュレーションとか速い
● 最近のスーパーコンピュータはGPUがたくさん載って
る
GPGPU環境
● CUDA
– NVIDIA製品用
● DirectX
– Windows専用
● OpenCL
– OpenGLとか作った団体(Khronos Group)が策定
– さまざまなデバイスで使える
– FPGAでも使えたりする
JavaでGPU
●
Aparapi
– JavaコードをOpenCLに変換
●
OpenCLを呼び出す
– OpenCL:並列計算フレームワーク
●
AMD始め、IntelやNVIDIAなどが参加
– JOCL(jogamp.org)
– J...
Aparapi
●
A PARalell API
●
実行時にJavaコードをOpenCLに変換
●
https://code.google.com/p/aparapi/
Aparapiコード
public class AparapiKernel extends Kernel{
float[] inputA;
float[] inputB;
float[] output;
@Override
public voi...
バグがある・・・
• 三項演算子のカッコが反映されない
– (修正してプルリクなげてとりこまれてます)
• CPUとの結果と比較するテストを用意したほうがいい
– けど、丸めの違いを考慮するの面倒
void proc(int fxy) {
fl...
JOCL(jogamp.org)
●
OpenCLを薄くラップ
●
https://jogamp.org/jocl/www/
JOCLのコード
String KERNEL_CODE =
"kernel void add(global const float* inputA,"
+ " global const float* inputB,"
+ " global fl...
比較
●
Aparapi
– めちゃ楽
– GPUの性能出しにくい
●
JOCL
– ちょっと面倒
– GPUの性能出しやすい
Sumatra
●
Java VMに組み込むことを目標
●
実装難しそう
●
コード書くのもわかりにくそう
●
性能出しにくそう
●
Java VMに組み込むほどメリットなさそう
– 性能欲しい人はOpenCL使うよね
と思ったら
●
「Sumatra is not in active development for
now.(2015/5/1) 」
http://mail.openjdk.java.net/pipermail/sumatra-dev/2015...
ところでディープラーニング
実装してみました
ディープラーニング
●
階層の深いニューラルネット
●
最近、人工知能っていわれてるのは、ほぼこれ
Aparapiを使う
●
15枚/分→75枚/分
●
1400万枚の画像処理が650日→130日!
DoubleではなくFloatを使う
●
ディープラーニングに精度は不要
●
精度が半分になれば並列度があげれる
●
データの転送量が減る
●
75枚/分→95枚/分
●
1400万枚の画像処理が130日→102日!
JOCLを使う
●
95枚/分→298枚/分
●
1400万枚の画像処理が102日→34日!
GPUローカルメモリを使う
●
298枚/分→300枚/分
●
1400万枚の画像処理が34日→33日
違う処理を並列に行う
●
畳み込み層の逆伝播処理
– 重み更新
– 誤差伝播
– バイアス更新
if(n < deltaCount){
// 誤差伝播
}else if (n < deltaCount + filterCount){
// 重み...
条件分岐の注意
●
ひとつのグループにif/else両方走ると
if→elseの順に両方の処理が走る
●
ひとつのグループではどちらかになるように調
整が必要
●
32個単位くらい
画面表示をはぶく
●
画面表示のためにGPU→CPU間転送が行われて
いた
●
300枚/分→320枚/分
●
1400万枚の画像処理が34日→30日
結果
●
機械学習
– まだ学習できてません・・・
●
オレ学習
– GPUのプログラミングが学習できました。
まとめ
●
GPUで高速化たのしい
●
世の中ね、顔かお金かなのよ
Upcoming SlideShare
Loading in …5
×

GPUをJavaで使う話(Java Casual Talks #1)

6,389 views

Published on

GPUとは何か、GPUをJavaで使うにはどうするか

Published in: Software
  • Be the first to comment

GPUをJavaで使う話(Java Casual Talks #1)

  1. 1. GPUをJavaで使う話 (来れたので) 2015/10/16 きしだ なおき
  2. 2. 自己紹介 ● 最近、化物語を見ました。
  3. 3. 今日の話 ● GPU速そう ● Cめんどい ● Javaでやりたい ● ディープラーニング書いてみた ● 高速化してみた
  4. 4. CPU ● 高機能・高性能・高粒度 ● OSが実行できる ● 演算器はコアあたり10個程度 – 一チップに100個程度 ● 明示的にメモリを制御できない – いかにキャッシュに載せるか ● = いかにメモリをまとめて扱うか
  5. 5. GPU ● GPU – ちょうたくさんコアがある – 同じ処理を行う – 行列計算に向いてる ● GTX 970 – 1664コア! – 衝動買い!
  6. 6. GPUの構成 ● いくつかのコアでグループを作る – 同時に同じ命令を実行する – グループだけからアクセスできるメモリをもつ ● コアのグループが多数ある ● コアのグループあたり数個の演算器 – 数千から数万の演算器 – グループ内では同じ演算が行われる ● とってもSIMD
  7. 7. GPUの製品 ● NVIDIA – GeForce – Tesla ● GPGPU専用 ● AMD – Radeon ● Intel – Intel HD Graphics ● CPUチップに内蔵されたGPU
  8. 8. GPGPU ● General Purpose computing on GPU ● GPUで汎用計算 ● シミュレーションとか速い ● 最近のスーパーコンピュータはGPUがたくさん載って る
  9. 9. GPGPU環境 ● CUDA – NVIDIA製品用 ● DirectX – Windows専用 ● OpenCL – OpenGLとか作った団体(Khronos Group)が策定 – さまざまなデバイスで使える – FPGAでも使えたりする
  10. 10. JavaでGPU ● Aparapi – JavaコードをOpenCLに変換 ● OpenCLを呼び出す – OpenCL:並列計算フレームワーク ● AMD始め、IntelやNVIDIAなどが参加 – JOCL(jogamp.org) – JOCL(jocl.org) – JavaCL ● Project Sumatra – Stream処理を自動的にGPUで行う – Java VMに組み込む
  11. 11. Aparapi ● A PARalell API ● 実行時にJavaコードをOpenCLに変換 ● https://code.google.com/p/aparapi/
  12. 12. Aparapiコード public class AparapiKernel extends Kernel{ float[] inputA; float[] inputB; float[] output; @Override public void run() { int gid = getGlobalId(); output[gid] = inputA[gid] * inputB[gid]; } public static void main(String[] args) { AparapiKernel kernel = new AparapiKernel(); int elementCount = 1_444_477; kernel.inputA = new float[elementCount]; kernel.inputB = new float[elementCount]; kernel.output = new float[elementCount]; fillBuffer(kernel.inputA); fillBuffer(kernel.inputB); kernel.execute(elementCount); } }
  13. 13. バグがある・・・ • 三項演算子のカッコが反映されない – (修正してプルリクなげてとりこまれてます) • CPUとの結果と比較するテストを用意したほうがいい – けど、丸めの違いを考慮するの面倒 void proc(int fxy) { float d = (result[fxy] >= 0 ? 1 : 0) * delta[fxy]; tempBiasDelta[fxy] = learningRate * d; } void kishida_cnn_kernels_ConvolutionBackwordBiasKernel__proc(This *this, int fxy){ float d = (float)(this->result[fxy]>=0.0f)?1:0 * this->delta[fxy]; this->tempBiasDelta[fxy] = this->learningRate * d; return; } ↓
  14. 14. JOCL(jogamp.org) ● OpenCLを薄くラップ ● https://jogamp.org/jocl/www/
  15. 15. JOCLのコード String KERNEL_CODE = "kernel void add(global const float* inputA," + " global const float* inputB," + " global float* output," + " uint numElements){" + " size_t gid = get_global_id(0);" + " if(gid >= numElements){" + " return;" + " }" + " output[gid] = inputA[gid] + inputB[gid];" + "}"; CLContext ctx = CLContext.create(); CLDevice device = ctx.getMaxFlopsDevice(); CLCommandQueue queue = device.createCommandQueue(); CLProgram program = ctx.createProgram(KERNEL_CODE).build(); int elementCount = 1_444_477; int localWorkSize = Math.min(device.getMaxWorkGroupSize(), 256); int globalWorkSize = ((elementCount + localWorkSize - 1) / localWorkSize) * localWorkSize; CLBuffer<FloatBuffer> clBufferA = ctx.createFloatBuffer( elementCount, CLMemory.Mem.READ_ONLY); CLBuffer<FloatBuffer> clBufferB = ctx.createFloatBuffer( elementCount, CLMemory.Mem.READ_ONLY); CLBuffer<FloatBuffer> clBufferC = ctx.createFloatBuffer( elementCount, CLMemory.Mem.READ_WRITE); fillBuffer(clBufferA.getBuffer()); fillBuffer(clBufferB.getBuffer()); CLKernel kernel = program.createCLKernel("add"); kernel .putArgs(clBufferA, clBufferB, clBufferC) .putArg(elementCount); queue.putWriteBuffer(clBufferA, false) .putWriteBuffer(clBufferB, false) .put1DRangeKernel(kernel, 0, globalWorkSize, localWorkSize) .putReadBuffer(clBufferC, true);
  16. 16. 比較 ● Aparapi – めちゃ楽 – GPUの性能出しにくい ● JOCL – ちょっと面倒 – GPUの性能出しやすい
  17. 17. Sumatra ● Java VMに組み込むことを目標 ● 実装難しそう ● コード書くのもわかりにくそう ● 性能出しにくそう ● Java VMに組み込むほどメリットなさそう – 性能欲しい人はOpenCL使うよね
  18. 18. と思ったら ● 「Sumatra is not in active development for now.(2015/5/1) 」 http://mail.openjdk.java.net/pipermail/sumatra-dev/2015- May/000310.html
  19. 19. ところでディープラーニング 実装してみました
  20. 20. ディープラーニング ● 階層の深いニューラルネット ● 最近、人工知能っていわれてるのは、ほぼこれ
  21. 21. Aparapiを使う ● 15枚/分→75枚/分 ● 1400万枚の画像処理が650日→130日!
  22. 22. DoubleではなくFloatを使う ● ディープラーニングに精度は不要 ● 精度が半分になれば並列度があげれる ● データの転送量が減る ● 75枚/分→95枚/分 ● 1400万枚の画像処理が130日→102日!
  23. 23. JOCLを使う ● 95枚/分→298枚/分 ● 1400万枚の画像処理が102日→34日!
  24. 24. GPUローカルメモリを使う ● 298枚/分→300枚/分 ● 1400万枚の画像処理が34日→33日
  25. 25. 違う処理を並列に行う ● 畳み込み層の逆伝播処理 – 重み更新 – 誤差伝播 – バイアス更新 if(n < deltaCount){ // 誤差伝播 }else if (n < deltaCount + filterCount){ // 重み更新 }else if (n < deltaCount + filterCount + biasCount){ // バイアス更新 }
  26. 26. 条件分岐の注意 ● ひとつのグループにif/else両方走ると if→elseの順に両方の処理が走る ● ひとつのグループではどちらかになるように調 整が必要 ● 32個単位くらい
  27. 27. 画面表示をはぶく ● 画面表示のためにGPU→CPU間転送が行われて いた ● 300枚/分→320枚/分 ● 1400万枚の画像処理が34日→30日
  28. 28. 結果 ● 機械学習 – まだ学習できてません・・・ ● オレ学習 – GPUのプログラミングが学習できました。
  29. 29. まとめ ● GPUで高速化たのしい ● 世の中ね、顔かお金かなのよ

×