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.
WASM(WebAssembly)入門
ペアリング演算やってみた
2017/9/8
光成滋生
• WASM = ブラウザで高速なアプリケーションを実行す
るためのバイトコード、ツール
• 現在開発中(のため様々なものがよく変わる)
• 一次資料(http://webassembly.org/)が重要
• 少し歴史
• その昔のIEのAc...
• デザインゴール
• 高速で、安全で、well-defined
• ハードウェア, 言語, プラットフォームに依存しない
• open
• https://webassembly.github.io/spec/
• 仮想マシン
• スタックマ...
• C/C++からWASM
• emscripten, emcc
• アセンブラ, 逆アセンブルなど各種変換
• WABT(https://github.com/WebAssembly/wabt/)
• wast2wasm, wasm2wast...
• wat(S式)をwast2wasmでwasmファイルにする
• ブラウザから見えるようにしてsquare.htmlを開く
• Firefox, Chrome, Edge(about:configで拡張JavaScript)対応
• Andr...
• square.wasmをfetchしてインスタンス化
6 / 16
square.html
<html><head><script>
fetch('square.wasm')
.then(response => response.array...
• Emscripten SDKのインストール
• main()つきCのソース
• buildしてブラウザで表示
7 / 16
Cサンプル
git clone https://github.com/juj/emsdk.git
cd emsdk
...
• ペアリング暗号ライブラリmclをWASMで動かしたい
• https://github.com/herumi/mcl/
• 要OpenSSL + GMP(多倍長演算ライブラリ)+ LLVM
• OpenSSL
• ハッシュ関数だけなので自前...
• 当初の期待
• mclはLLVMビットコードを出力
• x86/x64/arm/arm64専用コードはllcが生成(or Xbyak)
• -march=wasm32すればよいだけと思っていた
• 現時点での制限
• 64bit整数より大き...
• WASM仕様再掲
• carry演算, 64x64→128bit乗算, 128/64bit除算がない
• add/subは64bit単位で加算
• x + y < yならcarry発生として繰り上げ
10 / 16
多倍長演算部分をCで再実...
• 32x32→64, 64/32→32を使って実装
• 結構めんどい & 遅い(せっかくの64bit環境が…)
• 将来WASMがサポートすれば1命令にできる
• とりあえず出来た
• https://github.com/herumi/mc...
• CPU : Core i7-7500U 2.7GHz(Skylake)
• native : gcc 5.4.0
• emcc : clang 4.0.0(emscripten 1.37.15)
• -DMCL_USE_VINT -DMCL...
• モジュール化オプションとexportする関数を指定
• -s WASM=1 -s "MODULARIZE=1" -s
"EXPORTED_FUNCTIONS=[$(EXPORTED_MCL)]"
• EXPORTEDMCLはヘッダファイルか...
• moduleインスタンスを作るsetupWASM
• stackやheapの面倒を見てくれる
14 / 16
moduleインスタンスを作る
function setupWasm(fileName, nameSpace, setupFct)...
• mod._malloc()の返り値はexportされた関数に渡せる
• mod._free()する必要あり
• destructorのないJSではちょっと辛い
15 / 16
heapを使う
• moduleインスタンスのRuntimeを使う
• stackSave/stackRestoreでstackの保存と復元
• mod.HEAP8にstackAllocで取得した位置を利用する
• _malloc, _freeを使ってもよい
...
Upcoming SlideShare
Loading in …5
×

WASM(WebAssembly)入門 ペアリング演算やってみた

1,744 views

Published on

社内勉強会資料

Published in: Technology
  • Be the first to comment

WASM(WebAssembly)入門 ペアリング演算やってみた

  1. 1. WASM(WebAssembly)入門 ペアリング演算やってみた 2017/9/8 光成滋生
  2. 2. • WASM = ブラウザで高速なアプリケーションを実行す るためのバイトコード、ツール • 現在開発中(のため様々なものがよく変わる) • 一次資料(http://webassembly.org/)が重要 • 少し歴史 • その昔のIEのActiveX(x86) • 2000年ActionScript(Flash) • 2010年ChromeでNaCl(x86/arm) • 2013年Firefoxでasm.js(汎用), ChromeでPNaCl(汎用) • 2014年HTML5 • 2017年PNaClからWebAssemblyへ • WebGL, WebGPU(Apple), NXT(Google) • deeplearn.js https://pair-code.github.io/deeplearnjs/ • WebDNN https://mil-tokyo.github.io/webdnn/ja/ 2 / 16 概要
  3. 3. • デザインゴール • 高速で、安全で、well-defined • ハードウェア, 言語, プラットフォームに依存しない • open • https://webassembly.github.io/spec/ • 仮想マシン • スタックマシン • レジスタはi32, i64, f32, f64, 将来SIMDも • 通常の四則演算, 論理演算をサポート • ビットを数える(popcnt), clz, ctzがある • 浮動小数→整数変換(ceil, floor, trunc, nearest) • 分岐, min, max • carry演算, 64x64→128bit乗算, 128/64bit除算がない 3 / 16 WASMの仕様
  4. 4. • C/C++からWASM • emscripten, emcc • アセンブラ, 逆アセンブルなど各種変換 • WABT(https://github.com/WebAssembly/wabt/) • wast2wasm, wasm2wast • https://cdn.rawgit.com/WebAssembly/wabt/7e56ca56/demo/ wast2wasm/ (デモ) • LLVMからWASM • llc foo.ll -march=wasm32 • アセンブリコードをwastに変換(s2wasm) • ClangからWASMの直接出力? • いろいろあるが流動的なので本家を見て 4 / 16 様々なツール
  5. 5. • wat(S式)をwast2wasmでwasmファイルにする • ブラウザから見えるようにしてsquare.htmlを開く • Firefox, Chrome, Edge(about:configで拡張JavaScript)対応 • AndroidのChromeもOK 5 / 16 値を2乗するwat ;; square(i32 i) -> i32 (module (func (export "square") (param $i i32) (result i32) (i32.mul (get_local $i) (get_local $i)))) wast2wasm square.wat -o square.wasm
  6. 6. • square.wasmをfetchしてインスタンス化 6 / 16 square.html <html><head><script> fetch('square.wasm') .then(response => response.arrayBuffer()) .then(buffer => WebAssembly.compile(buffer)) .then(module => new WebAssembly.Instance(module)) .then(instance => { let square = instance.exports.square let button = document.getElementById('run') let x = 15 button.value = 'square of ' + x + ' =' button.addEventListener('click', function() { document.getElementById('result').innerText = square(x) }) }) </script></head><body> <input type="button" id="run" value="loading WebAssembly"/> <span id="result">0</span> </body></html>
  7. 7. • Emscripten SDKのインストール • main()つきCのソース • buildしてブラウザで表示 7 / 16 Cサンプル git clone https://github.com/juj/emsdk.git cd emsdk ./emsdk install sdk-incoming-64bit binaryen-master-64bit ./emsdk activate sdk-incoming-64bit binaryen-master-64bit #include <stdio.h> int add(int x, int y) { return x + y; } int main() { printf("add %d¥n", add(3, 5)); } emcc t.c -s WASM=1 -o t.html emrun --no_browser --port 8080 .
  8. 8. • ペアリング暗号ライブラリmclをWASMで動かしたい • https://github.com/herumi/mcl/ • 要OpenSSL + GMP(多倍長演算ライブラリ)+ LLVM • OpenSSL • ハッシュ関数だけなので自前のSHA1で代用して使わない • あとでSHA2にする • clock_gettime()がエラー • gettimeofdayで代用 • GMP • WASM用のがあったので試すがbuildできるが動かなかった • LLVMは 8 / 16 目標
  9. 9. • 当初の期待 • mclはLLVMビットコードを出力 • x86/x64/arm/arm64専用コードはllcが生成(or Xbyak) • -march=wasm32すればよいだけと思っていた • 現時点での制限 • 64bit整数より大きい整数を扱えない • 本来のLLVMはi256(256bit整数)などが使える • 内部で自動的に64bit x 4(32bit x 8)の演算に変換される • 32bit×32bit→64bit乗算しかない • そもそもcarry演算命令が無いのでCで書いてもそんなに変わ らないのでは(最適化コンパイラを信じれば) 9 / 16 当てが外れたLLVM for WASM Unsupported: %z = mul i128 %x, %y LLVM ERROR: Binary operator type not yet supported for integer types larger than 64 bits
  10. 10. • WASM仕様再掲 • carry演算, 64x64→128bit乗算, 128/64bit除算がない • add/subは64bit単位で加算 • x + y < yならcarry発生として繰り上げ 10 / 16 多倍長演算部分をCで再実装 template<class T> T addN(T *z, const T *x, const T *y, size_t n) { T c = 0; for (size_t i = 0; i < n; i++) { T xc = x[i] + c; if (xc < c) { z[i] = y[i]; } else { xc += y[i]; c = y[i] > xc ? 1 : 0; z[i] = xc; } } return c; }
  11. 11. • 32x32→64, 64/32→32を使って実装 • 結構めんどい & 遅い(せっかくの64bit環境が…) • 将来WASMがサポートすれば1命令にできる • とりあえず出来た • https://github.com/herumi/mcl/blob/master/include/mcl/vint. hpp • pure C++ • 四則演算と論理演算サポート • 巾乗 • mod pにおける逆元 • gcd, Legendreシンボル • 素数判定 11 / 16 64 x 64→128, 128 / 64→64
  12. 12. • CPU : Core i7-7500U 2.7GHz(Skylake) • native : gcc 5.4.0 • emcc : clang 4.0.0(emscripten 1.37.15) • -DMCL_USE_VINT -DMCL_VINT_64BIT_PORTABLE • Vint w/ 64-bit mulは64 x 64→128乗算を使うか/使わないか • 将来WASMが対応すれば切り替えられる • ので今はwastを直接書いてがんばらない • demo for Broswer • http://herumi.github.io/mcl/demo/pairing.html 12 / 16 性能 Xbyak LLVM Vint w/ 64-bit mul Vint wo/ 64-bit mul Firefox 55 Chrome 61 Edge msec 0.35 0.50 1.37 2.3 3.19 3.42 5.48
  13. 13. • モジュール化オプションとexportする関数を指定 • -s WASM=1 -s "MODULARIZE=1" -s "EXPORTED_FUNCTIONS=[$(EXPORTED_MCL)]" • EXPORTEDMCLはヘッダファイルから関数を自動抽出した • ついでにJS用プロトタイプ宣言用ファイルも生成 • int, pointerは全てnumberに(stringもあるが今回は避けた) 13 / 16 JSから呼び出す // bn.h void mclBnFr_setInt(mclBnFr *y, int64_t x); int mclBnFr_setStr(mclBnFr *x, const char *buf, size_t bufSize, int ioMode); // exported-mcl.js mclBnFr_setInt = mod.cwrap('mclBnFr_setInt', 'null', ['number', 'number', ]) _mclBnFr_setStr = mod.cwrap('mclBnFr_setStr', 'number', ['number', 'number', 'number', 'number', ])
  14. 14. • moduleインスタンスを作るsetupWASM • stackやheapの面倒を見てくれる 14 / 16 moduleインスタンスを作る function setupWasm(fileName, nameSpace, setupFct) { var mod = {} fetch(fileName) .then(response => response.arrayBuffer()) .then(buffer => new Uint8Array(buffer)) .then(binary => { mod['wasmBinary'] = binary mod['onRuntimeInitialized'] = function() { setupFct(mod, nameSpace) } Module(mod) }) return mod }
  15. 15. • mod._malloc()の返り値はexportされた関数に渡せる • mod._free()する必要あり • destructorのないJSではちょっと辛い 15 / 16 heapを使う
  16. 16. • moduleインスタンスのRuntimeを使う • stackSave/stackRestoreでstackの保存と復元 • mod.HEAP8にstackAllocで取得した位置を利用する • _malloc, _freeを使ってもよい 16 / 16 JSのstringをCのconst char*に変換 // bufはstring gen_setStr = function(func) { return function(x, buf, ioMode) { if (ioMode == null) { ioMode = 0 } var stack = mod.Runtime.stackSave() var pos = mod.Runtime.stackAlloc(buf.length) for (var i = 0; i < buf.length; i++) { mod.HEAP8[pos + i] = buf.charCodeAt(i) } r = func(x, pos, buf.length, ioMode) mod.Runtime.stackRestore(stack) } }

×