🚀

Webassemblyマルチスレッド用crateを調べる: Rustが征く(7)

2021/09/27に公開

nightlyは当たり前

関連記事:

Rustが征くシリーズ過去記事

先に言っておくが、
ただ動かすだけでも難しい。
(nightlyビルドは当たり前、ビルドターゲット指定、クロスオリジン問題とかもある)


PHPやJavaScriptのエンジニアにとって、
生涯無縁の技術が マルチスレッド
複数のスレッドを立てて並列処理させる仕組みだ。
WebAssemblyでは可能になるとのことでずっと調査をしていた。

結論から言うとWebAssembly単独でマルチスレッドを実現するのは無理っぽい。
ブラウザのWebWorker APIを使用することになるのだが、
ちょっと微妙で実用性は疑問ではある。
とある方のスライドだが、
この図がすべてを物語っている。

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

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

https://speakerdeck.com/petamoriken/multithreading-webassembly-by-rust?slide=12

2019年のスライドだけど、
令和3年9月現在も変わっていない。
この仕組みならJSで全部やればいいという話で、
よほどAIやマイニング、2D,3D物理演算などの計算速度が必要なものを、
巧く実装しない限りメリットを得られないことがわかる。
(JS <-> WASM間のデータやりとりやファイルロードなんかも普通に遅いからね)

('ω') まぁせっかく調べたから記事化しよ

crateを調べたところ、
WebWorkerをマスクする系のものが3つあった。
そのうち一つ一つ試すと思うが、
とりあえず今回はそれをリスト化してみよう。

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪

------------------- ↓ 本題はここから ↓-------------------

マルチスレッド関連では以下のモジュールがある。

wasm-bindgen-rayon

通常の繰り返し処理を並列処理するrayonをWebAssembly対応したもの。
Google謹製のライブラリだが、
今のところ以下のエラーがでて正常動作しない。
(動いてはいるっぽいけどなぁ)

エラー全文
wasm_rayon_bg.wasm:0xde45 Uncaught (in promise) RuntimeError: Atomics.wait cannot be called in this context
    at wasm_rayon_bg.wasm:0xde45
    at wasm_rayon_bg.wasm:0xe92e
    at wasm_rayon_bg.wasm:0x9182
    at wasm_rayon_bg.wasm:0xe6cf
    at wasm_rayon_bg.wasm:0xb4da
    at wasm_rayon_bg.wasm:0x9646
    at wasm_rayon_bg.wasm:0xe62e
    at wbg_rayon_PoolBuilder.build (wasm_rayon.js:139)
    at startWorkers (workerHelpers.no-bundler.js:69)
    at async main.mjs:5

(Googleは相変わらず仕事が雑だ)

コンパイル条件は

設定項目 設定値
toolchain nightly-2021-07-29
build.target wasm32-unknown-unknown
build.rustflags ["-C", "target-feature=+atomics,+bulk-memory"]
unstable.build-std ["panic_abort", "std"]
wasm-pack target web

wasm-mt

今のところ安定して使用できるマルチスレッド実行環境。
謎技術過ぎてよくわかってない。
ビルドターゲットがno-modulesなので取り回しに注意が必要

コンパイル条件は

設定項目 設定値
toolchain nightly-2021-07-28
build.target wasm32-unknown-unknown
wasm-pack target no-modules

wasm_thread

Rust標準のstd::threadを置換するだけでマルチスレッドが実現できることをコンセプトにしたモジュール
条件が細かすぎてちょっとよーわからん。
たぶんこうかな。

コンパイル条件は

設定項目 設定値
toolchain nightly-2021-07-29
build.target wasm32-unknown-unknown
build.rustflags ["-C", "target-feature=+atomics,+bulk-memory"]
unstable.build-std ["panic_abort", "std"]
wasm-pack target no-modules

------------------- ↓ 後書はここから ↓-------------------

また、webpackなどのバンドラーとも相性が悪い。
バンドラーは基本的にファイルを一つにするのだが、
Web Workerが呼び出すJSが単独で一枚必要になる。

WebPackでは以下のプラグインを使うといいらしい
https://github.com/GoogleChromeLabs/worker-plugin

wasm-futures-executor

新しいので調べ切れてないけど、
wasm-futures-executorというのが増えていた。

内容的にはwasm-bindgen-rayonwasm_threadをリスペクトしていて、
ビルド条件も大体同じっぽい。
targetはwebなので扱いやすいかもだが、
workerファイルは別途生成するので、
バンドラーを使う場合は工夫が必要だ。

テスト的にビルドして上記2つと違いエラーはなかったので、
そのうち記事にするかもしれない。

Discussion