どんな話?
- ハードウェアが変わっていく
- Javaも変わらないとね
こんな経験ない?
- サーバが遅いから速いCPUが載ったマシンに買い換えたい
- サーバを増やしたい
- サーバが遅いからデータベースにキャッシュ
処理を上げるためには
- 並列度を上げる
- より近いところにデータを置く
ムーアの法則
- 18ヶ月くらいでトランジスタの数が倍
- 寸法半減
ムーアの法則の終焉
" 物理的に配置できない(ナノミリレベル) * 電子が漏洩する(配線の間) * 歩留まりが上がらない 製造コストが増える
微細化が進んでも今までと違う
- コストが下がらない
- 消費電力と高速化は両立できない
データセントリックシステム
- データの移動に電力 時間が食われている
- ストレージ→メインメモリ→キャッシュメモリ
- Hadoopなど
- データの移動を減らす
- データの近くでデータをうつす
コンピュータの種類
- ノイマン型
- 非ノイマン型
ノイマン型
- メモリから命令を呼び出して命令にしたがった回路で処理
- CPU
- GPU
- 所謂プロセッサ
- メモリ→データ読み込み→回路
- 回路の構成がシンプル
CPU
- 高性能 高機能 高粒度
- 割り込みとか権限制御とか
- OSが実行できる
- OSが実行できることがCPUの基準
- 演算器自体が足し算と引き算
- コアあたり10個程度の演算器
- 明示的にメモリを制御出来ない
- いかにキャッシュを載せるか
- いかにメモリをまとめて扱うか
- そのデータがどこに置かれるか意識しない
GPU
- ちょうたくさんコアがある
- 同じ処理 行列計算に向いてる
- GTX 970
- 1664コア(つよそう)
GPUの構成
- コアごとにグループ
- 同時に同じ命令を実行
- グループだけからアクセスできるメモリをもつ
- コアのグループが多数ある
- コアあたり数個の演算器
- プロセッサ全体としては演算器が数千数万ある
https://ja.wikipedia.org/wiki/%E6%BC%94%E7%AE%97%E8%A3%85%E7%BD%AE
非ノイマン型アーキテクチャ
" ノイマン型ではないコンピュータ全体(ノイマン型でなければなんでもいい) * FPGA * ニューラルネット型 * 量子コンピュータ * ニューラルや量子はプログラム可能ではないので、FPGAがメインになろう
FPGA
- Field Programmable Gate Array
回路の入出力の組み合わせ
- 論理素子(AND/OR)をいっぱいならべると難しい
- 入力と出力が1対1で決まるので入力と出力のパターンを決めれば回路が決まるのでは?というコンセプトで、平たく言えばメモリ
- LUT(LookUp Table)
論理ブロック
- Logical Element
- 論理ブロックが格子状に配置
乗算回路とメモリ
- 蒸散やメモリを論理ブロックで実現すると効率悪いので専用の乗算回路やメモリ(SRAM)が乗ってる
その構成
- メモリが帯状に並んでいる
FPGAなら
- 命令を読み込む必要がなく、回路をやりたい処理の通り並べることができる
- メモリを読み込んで解釈するというレイテンシが生まれない!
- 処理の回路に直接データを流すことができる
利点
- 命令を読む必要がない
- 低レイテンシ
- 細かな並列化
Javaでやってみる
- CPU Streamでやると簡単
- GPU Aparapi OpenCL(JOCL) Project Sumatraなどを使う
Aparapi
- A PARarell API
JOCL
- OpenCLを薄くラップしてるライブラリ(書くのはちょっと面倒)
- Aparapiのコードをコピペしたりできる
比較
- Aparapi
- 楽
- GPUの性能出しづらい
- JOCL
- ちょっと面倒
- GPUの性能出しやすい
DeepLearningやってみたけど
- 階層の深いニューラルネット
- 最近人工知能と言われているのはほぼこれ
Aparapiを使うと
- 15枚/分→90枚/分
- 1400万枚の画像処理が600日→100日!(それでも長い)
JOCLを使う
- 90 枚/分→298枚/分
- 1400万枚の画像処理が100日→34日!
- Aparapiのほうが、データと処理のやりとりの回数がJOCLより多いから
GPUローカルメモリ
- 298 枚/分→300枚/分
- 1400万枚の画像処理が34日→33日!
- プロだと1週間で終わるらしい
GPUの結果
- 90 枚/分→300枚/分
- 1400万枚の画像処理が100日→33日!
- 77日分の無駄が発生してる
FPGAでやったら?
- GPUの半分のスループット
- 1/10の消費電力
- 電力あたりの性能は3倍
Sumatra
- Java VMに組み込むことが目標だけど
- 実装 コード 性能などに難がある
- メリットが少なそう
- と思ったら開発止まってた
JavaでFPGA
- Synthesijer
http://www.sigemb.jp/ESS/2014/files/IPSJ-ESS2014003-1.pdf
http://synthesijer.github.io/web/
- HDLを書かない方法になると思われる
Javaでもいろいろできる でも今のままで足りるの?→足りない
- オブジェクトのメモリ効率が悪い
- アーキテクチャに対応した値が使えない
- いろいろな型をコンピュータ自体が持ってる
- 高性能データ構造がメモリにやさしくない
- List Mapに数字を入れようとするとラップオブジェクトに値を入れないといけない
- 配列がハードウェアにやさしくない
- 多次元配列(配列の配列ができてそれは配列なのか?)
- 読み込み専用(メモリキャッシュをJavaで使おうとするとでかいデータが使えない)
Close To the Metal
https://en.wikipedia.org/wiki/Close_to_Metal
" ハードウェアに近づく
そこでUnsafe
- 並列化プリミティブ(compareAndSwap*)
- シリアライズ(メモリ上のオブジェクトをそのままStreamに流す)
- メモリ管理(アロケート)
- JVM外でのやりとり
Unsafeを利用している製品
- Cassandra Ehcache HBase Scala Springなどなど
- ミドルウェア 現行製品ではだいたい使っている
Unsafeの廃止
- Java 9でメンテ停止
- Java $N-1で完全置き換え Deprecate(非推奨)
- Java $Nで廃止
- Java 10 or 11で廃止 5年後くらいだろうか
- で、どうするの?
Unsafeの代替
- JEP 193 Variable Handles(Java 9)
- JEP 187 Serialization
- ProjectPanama ProjectValhalla Arrays2.0
- ProjectPanama JEP191FFI
Valhallaへの道
- Value Type
- Specialization
Value Type
- ユーザ定義基本型
- Codes like a class
- 配列 = ヘッダ + 参照
Pointクラスの配列の効率化
- 自力解析など
ValueType版Point
- value class Pointみたいな定義
- Nullを持たないプリミティブ
- 参照型ではなく値がそのまま格納されるので幸せになれるかも
Specialization
これを実現したい
ArrayList<int>
Java 8の美しくないクラス
- StreamとIntStream 捨てたい
OptionalとOptionalInt 捨てたい
IntStream extends Stream
OptionalInt extends Optional みたいな書き方をしたい
ValutType対応
- それぞれのValueTypeにあわせたコレクションを作るのは無理
- 効率のいいものを自前で実装しようとするとValueTypeは難しい
- Genericなクラスを作る
- プリミティブが入れられない
- Specialize可能なクラスを作れるようにする
Name Mangling
- 名前就職
- Javaの入れ子クラス Hoge$Foo
- Specializedなクラス Box${T=I} JVM上でIntを扱う記号
条件付きメソッド
- Intだけ扱うメソッドとか欲しい
https://docs.oracle.com/javase/specs/
Foo<?> ワイルドカードをどうするか
any ref
- Foo
intでもObjectでも - Foo<?>
可視性
- Foo
- ソース上は同じクラス
- 実際はspecializeされた別クラス
- privateメソッドが呼べない(VMが拒否ってしまう)
- JavaVM助けてくれ
配列
- Objectとintは違う
- Arrays2.0さん助けて!
問題点
- Foo
とFoo は共通の基底クラスを持たない別のクラス - Specializedなクラスをいつ生成するか
- classDynamicはVM実装が複雑
- JavaVM助けて
JavaVMをどうするか
- aload/iload/lload
- astore/istore/lstore
- areturn/ireturn/lreturn
int long double float全てに足してロード ストア 演算などの命令がある
バイトコードの統一
- 型を持ったまま汎用の公文
新しい型が自然に拡張できる
vload vstore vaddなど
- vload :I vaload :Dみたいな書き方
Arrays2.0
- 配列をインターフェイスに!
- バイトコードレベルのSpecializationが不要になる…という夢を見た
- そういう構想が2015夏に言われてた
http://openjdk.java.net/projects/valhalla/
- 構想が形になっていない?
- valhallaやっても金にならない?
プログラミングがハードウェア寄りになっていくので
Unsafe
- Valhalla
- Panama
まとめ
- コンピュータが変わる
- Javaも変わる
- あんたはどうだい?