2026年 02月 16日

ONNX Runtime Web の `ort.env.wasm.proxy` と `numThreads` は軽い推論では効果が薄そう

軽量なモデルの推論だと ONNX Runtime Web のマルチスレッド化の恩恵は受けれないという理解してるけど、どうするのが正解か考えている。

ort.env.wasm.proxy で Worker 化しても Session が1つだと1コアしか使えないよな、と思ってなんかいろいろ複雑なこと考えていたけど、ふと思うと単に Session 複数にすれば一番重いところはオフロードしてできるのか? → これはできなそう。プロキシ用のワーカーはグローバルに1つしか作られないっぽい。numThreads に応じてそこからさらに分岐するっぽいが

ということで、基本的に ort.env.wasm.proxynumThreads は重い推論の分散化だから軽量なモデルの大量推論にはあまり有効ではなく、そういうことをするなら自力で複数 Worker + Session 分離の仕組みを作らなければならない。

リアルタイム推論での複数同時推論の設計の方向性

リアルタイム前提のモデルの場合、推論時間はリアルタイム性に対して十分余裕があるぐらい軽量に作ってあるはず (100ms分の推論が10msで終わるというような)。これを複数同時にCPUコアを活用して行いたい。

この場合 90ms 分が余裕時間なので、以下のようなのが理想の状態

  • ワーカー数 m: できるだけ少なく〜最大でコア数 (2〜4)
    • onnx の session の数になる = モデルのコピーが m 個分必要 = メモリ必要量の増加
  • 処理数 n: 1つのワーカーに複数のストリーム(推論リクエスト)をコンカレントに(多重に) 流し込む。
    • ジッターを考えるとどのぐらいが適切かわからないが 100ms 分が 10ms で終わるなら5つ(50ms = 50%) ぐらい詰めこんでもいいか?

ort の session の初期化は結構重いので、ワーカー数はあまり増やすと初期化のコストが全然無視できない。なので1つのワーカーでできるだけ多くのことをしたい。そして session 自体はステートレスなので別々の推論ストリームを流しても大丈夫 (モデルの入力としてステートを渡すのが普通なので)

ワーカー数でパラレルにしつつ、リアルタイム余裕分をコンカレントに実行させる。

memo

let proxyWorker: Worker はモジュールレベルで定義されて使いまわされている

numThreads SetGlobalIntraOpNumThreads(numThreads) numThreads は Intra-Op (演算内のオペレーション) の並列化

Python だと inter_op_num_threads があるようだ Web にはないっぽい。

interOpNumThreads 自体はあった。This setting is available only in ONNXRuntime (Node.js binding and react-native). なので Web では使えない。