Java OpenCLの入門書: JavaでGPGPUの世界へ
価格: ¥0
本書が想定する読者は、C/C++で半年程度の開発経験(学校、職場問わず)のあるJava開発者です。
JavaのビルドについてはMavenの使用経験があることを想定します。
※誤植、改善点、追加内容等がある場合は随時更新していきます。Amazonの「コンテンツと端末の管理」ページで本の自動更新機能を有効にしてください。2017年5月24日更新、誤植・表現の改善を近日行う予定です。
目的
OpenCLのJavaバインディングライブラリ、JOCL(Java OpenCL)を紹介します。
内容
Javaを用いてOpenCLの基本的な概念及び基本API(JOCLとC99規格準拠のカーネルプログラミング言語)の解説をしますが、データ並列プログラミングで頻繁に使われるコードパターンも合わせて解説します。
解説する範囲は以下の4つのパターンです。
・還元パターン(Reduction、基数整列アルゴリズムを用いて解説)
・行列転置(Transposition、FFTアルゴリズムを用いて解説)
・バンクコンフリクト対策(ヒストグラム計算を用いて解説)
・ソーティングネットワーク(バイトニックアルゴリズムを用いて解説)
高速フーリエ変換は画像処理への適用のため2次元アルゴリズムの解説をしています。2次元に適用するため行列の転置も合わせて解説します。
GPGPUを使った基数整列(Radix Sort)は整列アルゴリズムの中でも最速とされており幅広く活用されているアルゴリズムです。Prefix-Sumの算出のために、Reductionパターンを解説します。
ヒストグラムの計算ではキャッシュ(SLM)を使うために、データ構造をスレッドセーフにするための設計手法を解説します。
バイトニック整列(Bitonic Sort)はRadix Sort程ではありませんが、GPUを使うことで高速整列を行えます。ソーティングネットワークの基本的なアルゴリズムを提示します。
OpenCL関数やコマンドのリファレンス(JOCLではなくOpenCL 1.2)もありますので、開発時の参考として使用もできます。
必要知識と対象読者
本書の読者はC/C++でコーディングをしたことがあるJavaエンジニア(業務で使う主言語はCでなくともよい)と想定します。
ビルドについてはMavenを使います。pom.xmlの編集程度の知識は必要となります。Javaの経験としては、半年以上の業務経験があることが前提です。
原則として数学の知識は不要ですが、例外として高速フーリエ変換の章では工学部・理学部2〜3年次程度の数学知識を前提とします。ビット演算を頻繁に使うため、ビット演算の知識も必須です。
開発環境
(低価格またはゼロコストで)身近なIntelの内蔵GPUを使ってGPGPUを学べるようにするため、本書ではIntel Core I5の内蔵HD Graphicsを検証に使います。
IntelのCore i3, i5, i7に附属してくる内蔵iGPU(HD Graphics/Iris Pro)を使ったGPGPUのプログラミングを通じて、OpenCLに慣れて頂きます。
外付・内臓を含めたGPU製品でIntelは約7割の市場シェアを持ち、非サーバーCPUのほぼ全てにiGPUが付属しています。現行システムに外付GPU(dGPU)を導入できないJava開発者がIntelのiGPUの使用を検討するきっかけになるものと考えます。
OSは「Max OS X 10.11.4」(一部10.9.5)を使います。
検証環境には以下3つのソフトウェアがインストールされているものとします。
* JDK1.8
* Maven2
* gcc(又はclang)とmake(※JNI/JNAサンプルを動作させる場合に限り必要)
makeとgccをWindows(Windows 8以前)で使うにはMinGW(64ビット版はMinGW-w64)を導入する必要があります。
Java/Pythonバインディングを使ったOpenCLの応用例
* データサイエンティストが考案した機械学習・最適化・特徴抽出のアルゴリズムをJava等の既存の分散基盤に移して並列分散環境でのGPGPUで処理
* データの暗号化
* 基数整列
* 車載カメラや画像投稿サイトからくるフィード・ビデオフレームを高速フーリエ変換を使ってリサイズ・フィルター、圧縮をして加工処理
* 画像・音声データのエンコード/デコードをして機械学習エンジンへ回送するシステム基盤
といった応用例が考えられます。
目次
I. OpenCLアーキテクチャー
1. OpenCLの概要
2. APIとアーキテクチャ
II. Java OpenCLランタイムAPI
3. OpenCL開発環境
4. JNI(Java Native Interface)
4.1. JNIの開発環境
4.1.1. JDK(Mac OS X)
4.2. ビルド
4.2.1. javah
4.2.2. JNIバイナリのビルド
Linux
Windows
4.3. ハローワールド
4.4. 型の対応
4.4.1. JNI引数の例
5. JNA(Java Native Access)
5.1. Maven2
5.2. 検証環境の構成
5.2.1. Maven (HomeBrew)
5.3. 関数のマッピング
5.4. Java・Cとネイティブ型の対応
5.5. ハローワールド
5.6. ビルド
6. JOCL
6.1. java.nio.Buffer
6.2. Pointerオブジェクト
7. HelloWorldプログラム
7.1. HelloWorldプログラムの環境設定
7.2. カーネル・ソースファイル(.cl)の読み込み
7.3. HelloWorld(タスク並列プログラミング)
7.3.1. 出力
7.4. HelloWorld(データ並列プログラミング)
7.4.1. エラー表示関数
8. OpenCLホストAPI
9. OpenCLランタイム
III. カーネルプログラミング
IV. Java OpenCL実装
11. ヒストグラム
11.1. アルゴリズムのパラメータ
11.2. 共有ローカルメモリ
11.3. ストライドとメモリアクセス
11.4. ストライドとBank Conflict
11.5. Stride型のアルゴリズム
11.6. バンクコンフリクトを緩和する実装例
11.7. アトミック型のアルゴリズム
12. 高速フーリエ変換(Fast Fourier Transform)
12.1. 使用する数学のまとめ
12.2. フーリエ変換(Fourier Transform)の定義
12.3. 離散フーリエ変換(Discrete Fourier Transform)
12.4. 高速フーリエ変換(Fast Fourier Transform)
12.4.1. Cooley-Tukey型アルゴリズム
12.4.2. Bit Reversal
12.5. 実装例(CPU)
12.6. 実装例(GPU)
13. 2次元高速フーリエ変換
13.1. 画像
13.2. 2次元への適用アルゴリズム
13.3. PNG画像の高域フィルターをCPUで実装
13.3.1. 高域フィルターの出力
13.4. 実装例(GPGPU)
13.5. 2次元カーネルの実装
13.5.1. 全体の流れ
13.6. GPGPUへの修正点(メモリストライド・Bank Conflict対策)
13.7. FFT-2Dで画像処理
14. Bitonic Sort(バイトニックソート)
14.1. バイトニック配列の構築
14.2. バイトニックマージ
14.3. バイトニックソートのOpenCL実装例
14.4. カーネルの実装(bitonic split)
14.5. カーネルの実装(bitonic merge)
15. 基数整列
15.1. ヒストグラム
15.2. Bucket Scan
15.3. Reduction(還元)
15.3.1. 結合性
15.3.2. 交換性
15.4. Prefix Sumへの適用
15.5. up-sweep(掃き上げ)
15.6. down-sweep(掃き下げ)
15.7. 並び替え(Rank)
15.8. 実装例(CPU)
15.8.1. ヒストグラム
15.8.2. Prefix-Sum
15.8.3. 並び替え
15.9. 実装例(GPU)
15.9.1. Up-sweep(GPU)
15.9.2. down-sweep
15.9.3. 並び替え(rearrange)
15.9.4. マルチキュー実装(CPU+GPU)
V. 付録
A. OpenCL対応デバイス一覧表
B. OpenCL 1.2 API Reference