⛳
Webassemblyマルチスレッドクレート:wasm-bindgen-rayonを試す
なお。。。
関連記事:
Rustが征くシリーズ過去記事
- wasmerでWebAssemblyの門を叩く: Rustが征く(2)
- JavaScriptからWebAssemblyの関数を呼び出す: Rustが征く(3)
- TypeScriptとRollupでWebassemblyを稼働させる: Rustが征く(4)
- SvelteでWebAssemblyでTypeScriptでRollupで: Rustが征く(5)
- WASMのサイズでかすぎね?: Rustが征く(6)
- Webassemblyマルチスレッド用crateを調べる: Rustが征く(7)
- WebAssemblyでSleep: Rustが征く(8)
- Web Workerでマルチスレッド(JSのみ): Rustが征く(9)
- Web Worker+WebAssemblyでマルチスレッド: Rustが征く(10)
- Web Worker+WebAssemblyのパフォーマンス計測: Rustが征く(11)
- Web Worker+WASM+Parcel+TypeScriptでマルチスレッド実行: Rustが征く(12)
------------------- ↓ 前書はここから ↓-------------------
WebWokerとWebAssemblyの挙動が大分つかめた。
次は動かないモジュールを動かし考察していく。
Webassemblyマルチスレッド用crateを調べる: Rustが征く(7)で紹介した三つのモジュール
これらをなんとか動かして考察していく。
まずはwasm-bindgen-rayonから。
コンパイル条件は
設定項目 | 設定値 |
---|---|
toolchain | nightly-2021-07-29 |
build.target | wasm32-unknown-unknown |
build.rustflags | ["-C", "target-feature=+atomics,+bulk-memory"] |
unstable.build-std | ["panic_abort", "std"] |
pasm-pack target | web |
この会ではインストールなどの説明は全部省くので、
サンプルなどを目当てに来られた方には申し訳ない。
(シリーズに加えてないのはそれが理由)
フロントエンド側はvanillaJS(素のJavaScriptのこと)で実装。
要素が増えると動かすまでに余計な手間が増えるからね。
ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪
------------------- ↓ 本題はここから ↓-------------------
プロジェクト作成
wasm-pack new wasm-rayon
cd wasm-rayon
cargo install cargo-edit wasm-pack wasm-bindgen-cli
cargo upgrade
cargo add rayon
cargo add wasm-bindgen-rayon --features "no-bundler"
ビルドの各種設定
ツールチェインの設定
rustup toolchain add nightly-2021-07-29
rustup component add rust-src --toolchain nightly-2021-07-29
printf '[toolchain]\nchannel = "nightly-2021-07-29"' | tee ./rust-toolchain.toml
rustup toolchain list
stable-x86_64-unknown-linux-gnu (default)
nightly-2021-07-29-x86_64-unknown-linux-gnu (override)
ビルドオプションの設定
./.cargo/config.toml
[build]
target = "wasm32-unknown-unknown"
[target.wasm32-unknown-unknown]
rustflags = ["-C", "target-feature=+atomics,+bulk-memory,+mutable-globals"]
[unstable]
build-std = ["panic_abort", "std"]
チェック
cargo check
wasm-pack build --release --target web -d ./dist/pkg
実装
./src/lib.rs
pub use wasm_bindgen_rayon::init_thread_pool;
use rayon::prelude::*;
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn sum_numbers(numbers: &[i32]) -> i32 {
numbers.par_iter().sum()
}
フロントエンド側の準備
./dist/js/main.mjs
import init, {initThreadPool, sum_numbers} from "/pkg/wasm_rayon.js";
(async() => {
await init();
await initThreadPool(navigator.hardwareConcurrency);
console.log(sum_numbers(new Int32Array([3,5,6])));
})()
./dist/index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>My awesome Rust, WebAssembly, and Parcel application</title>
<script type="module" src="./js/main.mjs"></script>
</head>
<body>
</body>
</html>
結果
\(^o^)/オワタ
はいはい解散
Discussion
手元の環境でも同様のエラーが出ました。
デバッグ情報と該当する関数をみたところ、原因は次のように推定されました。
Atomics.wait
を使っているいずれにせよ、wasm-bindgen-rayon の対応を待つしかないでしょう。メインスレッド上で使うこと自体、サポートされていないと考えた方が妥当かもしれません。