2026-01-26
Wasm SIMD命令がおもしろかったので、もうちょっと実用的なキーワード検索に挑戦。

ブログ検索で使うことを想定し、下記のようなコードをWasm SIMD化してみます。

export class FindIndexes { static async create() { return new FindIndexes(); } setTexts(texts, cap = 1000) { this.texts = texts; this.cap = cap; } findIndexes(key) { const res = []; for (let i = 0; i < this.texts.length; i++) { if (this.texts[i].includes(key)) res.push(i); } return res; } }

1つの文字列化したブログ一覧などから、特定キーワードを含む記事のインデックスを配列で返します。

Wasm SIMD版がこちら「find_all.wat」ですが、6059件内の検索で5.32ms、JavaScript版の1.97msより遅い!あまり、Wasm SIMDが活かせない課題だったようです。

このままただの失敗ではおしいので、マルチスレッド化してみました。Workerをその環境で使える並列化数 navigator.hardwareConcurrency - 1 だけ生成し、並行して検索する、FindIndexes_threads.ts でテストしてみましたが、6000件程度ではオーバーヘッドの方が大きいようで、並列化での高速化は微妙。


「code4fukui/find-simd」

ソースはこちら。

特性に合った課題の設定が大事です。

links
- Wasm SIMDで立っているビットの数を数えるライブラリ、popcount-simd

2026-01-25
Wasm(WebAssembly)にも、CPUの並列計算命令SIMD(シムド、Single Instruction, Multiple Data)に対応した、Wasm SIMDがあり、標準的な環境で使えるようになっています。

テストも兼ねて、8bitを16コ束ねた128bitで処理できる命令のひとつ、ビットの数を数えるSIMD命令 i8x16.popcnt を使って、任意のデータから立っているビットの数を返すライブラリを作ってJavaScript実装と速度比較してみました。


100byteから10億byteまでのランダムなデータを使ったビットカウントを比較したグラフです。横軸はデータ量、縦軸は計算時間ですが、SIMDでJS版の約4倍速いという結果になりました。

10kbyteでもSIMD0.1秒に対して、JS0.4秒とオーバーヘッドも少ないので使いやすいです。


「code4fukui/popcount-simd」

WebAssemblyによるカウントプログラム popcnt16.wat と、JavaScriptによる実装。比較してみるのもおもしろいです。

const POPCNT8 = (() => { const t = new Uint8Array(256); for (let i = 0; i < 256; i++) { let x = i, c = 0; while (x) { x &= x - 1; c++; } t[i] = c; } return t; })(); export const popcount = (data) => { let sum = 0; const t = POPCNT8; for (let i = 0; i < data.length; i++) { sum += t[data[i]]; } return sum; };

WebAssembly(WASM)は、IchigoJam web でも活躍しています!

クリエイティブ・コモンズ・ライセンス
本ブログの記事や写真は「Creative Commons — CC BY 4.0」の下に提供します。記事内で紹介するプログラムや作品は、それぞれに記載されたライセンスを参照ください。
CC BY / @taisukef / アイコン画像 / プロフィール画像 / 「一日一創」画像 / RSS