$30 off During Our Annual Pro Sale. View Details »

Multithreading WebAssembly by Rust

森建
November 08, 2019

Multithreading WebAssembly by Rust

Fukuoka.rs vol.6 〜LT会〜
https://fukuokars.connpass.com/event/151353/

森建

November 08, 2019
Tweet

More Decks by 森建

Other Decks in Programming

Transcript

  1. Multithreading
    WebAssembly by Rust
    fukuoka.rs vol.6
    pixiv Inc.
    petamoriken
    2019.11.8

    View Slide

  2. 2
    自己紹介まわり
    ● 主にフロントエンドエンジニア
    ● ECMAScript や WHATWG DOM を追うのが好き
    ● WebAssembly をほどほど追ってる
    ● 最近引っ越してネット回線がない状態が続いていて
    辛い
    11/20(水) 19:30~ Three.js Meetup Tokyo #0
    サテライト会場を福岡でやるのでよければどうぞ
    https://connpass.com/event/154480/
    petamoriken
    課題解決部

    View Slide

  3. 3
    WebAssembly とは
    ● アセンブリでないバイトコード
    ● 豊富な実行環境がある
    ○ モダンブラウザ Chrome / Firefox / Safari / Edge
    ○ Node.js v8 以降(AWS Lambda, BigQuery など)
    ○ Wasmer というランタイムを使えば Rust / C / Go / Ruby などで実行できる
    ● ECMAScript と似た策定プロセスを取っている

    View Slide

  4. 4
    WebAssembly W3C の策定プロセス
    ● Phase 1 Feature Proposal
    ○ 機能追加が承認される
    ● Phase 2 Proposed Spec Text Available
    ○ 最初の Spec テキストが作られる
    ● Phase 3 Implementation Phase
    ○ Spec テキストが完成し、レビューが完了する
    ● Phase 4 Standardize the Feature
    ○ 1つのツールチェイン、2つ以上の実行環境が作られ、承認される

    View Slide

  5. 5
    Phase 2 Threads
    まだ仕様が確定していないが Desktop Chrome に先行実装されている
    https://developers.google.com/web/updates/2018/10/wasm-threads

    View Slide

  6. ブラウザにおけるスレッドは SharedArrayBuffer と Web Workers API を用いる
    ● SharedArrayBuffer (Atomics API)
    ○ スレッド間で共有できる特別な ArrayBuffer(バイト列)
    ○ Atomics API を使って割り込みが起きないようにする
    ○ Spectre 脆弱性の影響で現在 Desktop Chrome のみ扱える
    ● Web Workers API
    ○ スレッドを作る DOM API
    ○ もちろん SharedArrayBuffer を共有することができる
    6
    Phase 2 Threads

    View Slide

  7. ● 先程の Chrome の記事では C で pthread を使ったコード例が載っている
    ○ Emscripten を使ってビルドする
    ○ ビルドすると Wasm とグルーコードの JavaScript が出力される
    ● Rust で似たコードを書いてビルドすればスレッドが扱えるのでは!?
    7
    Phase 2 Threads
    emcc -O2 -s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=2 -o test.js test.c

    View Slide

  8. 8
    int main(int argc, char *argv[]) {
    int fg_val = 54;
    int bg_val = 42;
    pthread_t bg_thread;
    // Create the background thread
    if (pthread_create(&bg_thread, NULL, bg_func, &bg_val)) {
    perror("Thread create failed");
    return 1;
    }
    // Calculate on the foreground thread
    fg_val = fibonacci(fg_val);
    // Wait for background thread to finish
    if (pthread_join(bg_thread, NULL)) {
    perror("Thread join failed");
    return 2;
    }
    // Show the result from background and foreground threads
    printf("Fib(42) is %d, Fib(54) is %d\n", bg_val, fg_val);
    return 0;
    }

    View Slide

  9. 9
    extern "C" {
    fn console_log(num: f64);
    }
    #[no_mangle]
    pub extern "C" fn main() {
    let normal = 54;
    let background = 42;
    let handler = std::thread::spawn(move || fibonacci(background));
    let normal = fibonacci(normal);
    let background = handler.join().expect("Unsupported Thread");
    unsafe {
    console_log(normal as f64);
    console_log(background as f64);
    }
    }

    View Slide

  10. 10

    View Slide

  11. ● std::thread::spawn を使ったコードは unreachable に変換されてしまう
    ● 調べてみると Phase 2 Threads は Atomics のみの提案だった
    ○ ブラウザの SharedArrayBuffer は扱えるが Web Workers API は扱えない
    ● Emscripten の場合 JavaScript のグルーコード内でスレッドを作っている
    https://git.io/JeVk0
    11
    Multithreading WebAssembly by Rust
    // Allow HTML module to configure the location where the 'worker.js' file will be loaded from,
    // via Module.locateFile() function. If not specified, then the default URL 'worker.js' relative
    // to the main html file is loaded.
    pthreadMainJs = locateFile(pthreadMainJs);
    var newWorkers = [];
    for (var i = 0; i < numWorkers; ++i) {
    newWorkers.push(new Worker(pthreadMainJs));
    }
    return newWorkers;

    View Slide

  12. 12
    こうだと思っていたが
    JavaScript
    WebAssembly WebAssembly
    Main Thread Background Threads
    WebAssembly

    View Slide

  13. 13
    こうだった
    JavaScript
    WebAssembly
    JavaScript
    WebAssembly
    JavaScript
    WebAssembly
    Main Thread Background Threads

    View Slide

  14. ● Rust でスレッドを扱おうと思ったら
    ○ 複数の Wasm に分割し、それぞれに対して JavaScript のグルーコードを書く
    ○ wasm-bindgen で JavaScript のグルーコードを自動生成
    ■ 公式の demo があるがうまく実行できてなさそう?
    ● 将来的には Phase 1 Interface Types によってグルーコードが不要に
    ○ wasm-bindgen で直接 DOM API を触るようになって JavaScript のグルーコードを
    生成しなくなる?
    ○ wasm32-web, wasm32-node のようにビルドターゲットが増える?
    14
    Multithreading WebAssembly by Rust

    View Slide

  15. ● WebAssembly でのマルチスレッドはまだ厳しい
    ○ そもそもまだ仕様策定中
    ○ Wasm の実行環境でスレッドを作り、その中で Wasm を実行する必要がある
    ○ ブラウザに限って言うとまだ Desktop Chrome でしか扱えない
    ● Phase 1 Interface Types が来たら世界が変わる(はず)
    ○ フロントエンド開発でグルーコードも含めて JavaScript が不要になる
    15
    まとめ

    View Slide