2024-01-08
現代コンピューターの力を引き出す要はGPU。JavaScriptは便利ですが、GPUを扱うには向きません。GPUを扱うウェブ標準の言語といえばGLSL(OpenGL Shading Language)ですが、グラフィックに限らずAIなど汎用で使うための言語、WGSL(WebGPU Shading Language)の開発が進んでいます。順調に標準化が進めば、ブラウザ上で直接動くプログラミング言語が、JavaScript、WebAssembly、GLSLにWGSLが加わり4つになります。


「WebGPU API - Web APIs | MDN」

WGSLが使える仕様、WebGPU、まだ使えるのはPC上のChrome、Edge、Operaのみですが、Denoで動きます!(参考、Deno 1.39: The Return of WebGPU

WGSLはじめのいっぽとして、Denoのコラッツの問題を計算するサンプルプログラム「webgpu-examples/hello-compute at main · denoland/webgpu-examples」を元に簡単な足し算と、フィボナッチ数列をGPUで並列計算して、JavaScriptとの速度を比較してみました。

fn add1(n_base: u32) -> u32 { return n_base + 1u; } @group(0) @binding(0) var<storage, read_write> v_indices: array<u32>; @compute @workgroup_size(1) fn main(@builtin(global_invocation_id) global_id: vec3<u32>) { v_indices[global_id.x] = add1(v_indices[global_id.x]); }

関数定義はfn、シンプルな後付型表記が、ZenRustっぽいですね。WebGPUの前身、WebGLで使う言語、GLSLがC言語風だったので思い切ってイメチェンして様子。

こちら、フィボナッチ数列を計算するプログラムを

fn fib(n: u32) -> u32 { if (n < 2u) { return n; } return fib(n - 1) + fib(n - 2); }

と、再帰を使って実装しようとすると・・・

fib.html:1 Tint WGSL reader failure: :18:1 error: cyclic dependency found: 'fib' -> 'fib' fn fib(n: u32) -> u32 { ^^ :22:10 note: function 'fib' references function 'fib' here return fib(n - 1) + fib(n - 2); ^^^ - While validating [ShaderModuleDescriptor] - While calling [Device].CreateShaderModule([ShaderModuleDescriptor]).

と、エラーになります。CUDA Cと同様、GPU内で再帰は使えないので、ループで書き換えます。

fn fib(n: u32) -> u32 { var cur: u32 = 0u; var bk1: u32 = 0u; var bk2: u32 = 1u; for (var i: u32 = 1u; i <= n; i++) { cur = bk1 + bk2; bk2 = bk1; bk1 = cur; } return cur; }

GLSLを動かすためには、GPU向けにコンパイルしたり、メモリをGPUに転送して、実行させ、終了を待って、メモリをGPUから受け取る処理を加えて実行します。まるでマイコン開発!(参考、WebGPU.js on GitHub

今回のようなシンプルな並列計算のための諸々の処理をWebGPUクラスのcreateCalcIntToIntとしてまとめています。参考資料と合わせて辿って改造してみましょう。WebGPUを使って、ライフゲームを実装するまでのチュートリアルが良さそうでした。(参考、初めての WebGPU アプリ  |  Google Codelabs


「フィボナッチ by WGSL」
src on GitHub
タイムを計測してみたところ、65535コの100のフィボナッチ数を求める並列計算。WebGPUを使った計算速度は、10ミリ秒。CPUで直列計算した結果、11ミリ秒とほぼ互角。


「deno run --unstable fib_bench.js」

この程度の計算では差はでないようなので、フィボナッチ計算処理を無駄に1000回繰り返したところ、M1 Macbook Proにて、CPUでは7,218ミリ秒かかりましたが、WebGPU(Chrome)では、45ミリ秒と、150倍速!

Denoで直接使えるプログラミング言語は、JavaScript、TypeScript、WebAssembly、WGSLと4つ。フロントエンドでの互換性を考えるとGLSLですが、サーバーでもGPUを使った高速化ができるのは楽しいですね!

Let's enjoy to hack GPU!

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