HSP JIT
実行時情報による最適化無し(--no-opt)はhsp3cnv+コンパイル相当の内容で、バイトコードのデコードとディスパッチ、オペランドスタックの操作などを最適化出来て数割の高速化。
プログラム実行中に変数型が変わらないと仮定(--skip-type-check)し、配列のインデックスチェックを省く(--no-range-check)とaobenchやレイトレのようなひたすら計算をするプログラムでは10倍の高速化出来た。
課題
WebGL+HGIMG4
hsp3dish.jsでHGIMG4対応した。
普通のhsp3dishは一部OpenGL2.x系のAPIを使っているのでEmscriptenでLEGACY_GL_EMULATIONが必要だけど、
HGIMG4はGamePlay3DはOpenGL ES2ターゲットでFULL_ES2で十分なのでブラウザ実行ではむしろこっちのほうが素直かもしれない。
今年の振り返り
囲碁AI
コンピュータ囲碁モンテカルロ法の理論と実践読みつつ、OCamlでモンテカルロ木探索なの書いた。
マルチプロセッサで検証したくてAWS使い始めたり。棋譜からのパターン学習のあたりで力尽きてGNU Goに勝ち越せてない。
OCamlは書きやすいっていう利点はあるけど、スレッド使えない、C++やJava比で遅いってあたりであんまり向いてないタスクかもしれない。
ispcでなんとかなるかと思ったけど一番高速化したいあたりとC/C++だとだるいあたりがかぶってていまいち。
TypeScript
会社でSPA作ったりDefinitelyTypedやTypEcsにパッチ送ったり。
家でもHSP関係の小物に使ったり、DTにパッチ送ったり。
js_of_ocaml的嬉しさはあんまりないけど、ツラミもあんまりないので、しばらくはWeb系開発はTSでいいやと思ってる。
HSP
AltJS勉強会の発表駆動開発でEmscriptenでウェブブラウザ対応を書いて、先日公開されたHSP3.4にマージされた。
ここ数年コンテストどうしようかと思うけど作るのに半日以上かかるものをHSPで書く気力があんまりなくて毎回見送ってる。
ここ数日HGIMG4をウェブ版に入れられないか実験中。
OCaml
前述の囲碁書いたり、ocamlcのasm.jsバックエンドの実験したり。
asm.jsターゲットだとjs_of_ocamlが回避した面倒さをもろに被る割にはアウトパフォームできるかは対象次第の様子。リンカなどの周辺領域はEmscriptenの資産使えるだろうという目論見が外れてGC実装でつまずいてる。
Jetson TK1
セットアップしてサンプル動かしたあたりで単純に絶対性能ならその辺のPC使うほうが楽っていうのがあって放置状態。
HSP3Dish.js
OpenHSPのhsp3dishをemscripten対応した。
http://peppermint.jp/products/hsp/hsp3dish.html
Firefox・Chrome・IEとも最新バージョンでは実行速度問題なさげ。
IE11だとWebGL対応状況の関係でblock3はボール見えないくらい。
hspcmp.dll相当の機能も動いてるんで、全部オンラインでプログラミングってのも出来そう。
http://peppermint.jp/products/hsp/hspcmp2.html
公式のサンプルは動いたんで、実環境な実行テスト用に誰かdishアプリ下さい。
js_of_ocamlとenchant.js
TypeScriptとenchant.jsの相性悪いという話があったけどjs_of_ocamlも辛い。
enchant.Class.createをうまく扱う方法が思いつかない。
継承使わずに分厚いラッパー用意するほうがいいのかも。
open Js module Enchant = struct let enchant = Unsafe.variable "enchant" let init modules = let ms = jsnew array_empty() in modules |> Array.iter (fun m -> ignore @@ ms##push(string m)); ignore @@ Unsafe.fun_call (Unsafe.variable "enchant") [|Unsafe.inject ms|]; () let new_game w h = let game = Unsafe.variable "Game" in jsnew game (w, h) let game_assets game key = let g = Obj.magic game in Unsafe.get (g##assets) (string key) end module E = Enchant let _ = E.init [||]; Dom_html.window##onload <- Dom_html.handler (fun _ -> let game = E.new_game 320 320 in game##enemy_speed_ <- 1; game##preload(string "chara1.png", string "map0.png"); let bear_class = E.enchant##_Class##create (E.enchant##_Sprite, Unsafe.obj [| "initialize", Unsafe.inject @@ wrap_meth_callback (fun this x y -> E.enchant##_Sprite##call(this, 32, 32); this##x <- x; this##y <- y; this##image <- E.game_assets game "chara1.png"; this##frame <- 5; game##rootScene##addChild(this) ) |]) in let enemy_class = E.enchant##_Class##create (bear_class, Unsafe.obj [| "initialize", Unsafe.inject @@ wrap_meth_callback (fun this x y -> bear_class##call(this, x, y); this##addEventListener (string "enterframe", wrap_meth_callback (fun this () -> this##x <- this##x + game##enemy_speed_; let frame = (this##age /. 5.0 |> floor |> int_of_float) mod 4 in this##frame <- [|0; 1; 0; 2 |].(frame) + 5))) |]) in game##onload <- wrap_callback (fun() -> game##rootScene##addEventListener (string "enterframe", wrap_meth_callback (fun this () -> if this##age mod 20 = 0 then let _ = jsnew enemy_class (0, Random.int 320) in () ))); game##start (); _false )
OCamlからIntel SPMD Program Compilerを使う
せっかく最新のCPUではコア複数あるんだからOCamlからも活用したい。
ispcではGPGPUのようなイメージで独自言語のコードを専用コンパイラでコンパイルしたものを普通のC/C++のコードから呼び出して使う。だったらocamlからもctypes.foreign経由で素直に使えるんじゃなかろうかということで実験。
$ ispc -O2 --arch=x86-64 --target=sse2,sse4-x2,avx sort.ispc -o objs/sort_ispc.o -h objs/sort_ispc.h
let s = let open Ctypes in foreign "sort_ispc" (int32_t @-> ptr uint32_t @-> ptr uint32_t @-> int32_t @-> returning void) let sort_ispc' n code order ntasks = let n' = Int32.of_int n in let code' = C.Array.start code in let order' = C.Array.start order in let ntasks' = Int32.of_int ntasks in s n' code' order' ntasks'
$ time ./sort 10000000 [sort ispc]: [110528.213] million cycles [sort ispc + tasks]: [73224.223] million cycles [sort serial]: [847924.817] million cycles (7.67x speedup from ISPC, 11.58x speedup from ISPC + tasks) ./sort 10000000 579.76s user 5.71s system 112% cpu 8:41.84 total
10000000要素のソートがArray.sort比で1スレッドは7.67x、4スレッドは11.58x早い。オーバーヘッドがあるらしく1万要素程度だと逆に遅いので使いどころを選びそうではあるが一応使えそう。