WebGPU: ブラウザで最新の GPU へのアクセスが可能に

WebGPU が GPU の能力を活用し、機械学習のパフォーマンスとグラフィックス レンダリングを改善する仕組みについて説明します。

新しい WebGPU API により、グラフィック ワークロードと ML ワークロードのパフォーマンスが大幅に向上します。この記事では、WebGPU が現在の WebGL ソリューションと比較してどのように改善されているかについて説明し、今後の開発についても紹介します。まず、WebGPU が開発された理由について説明します。

WebGPU のコンテキスト

WebGL は 2011 年に Chrome に導入されました。WebGL では、ウェブ アプリケーションで GPU を利用できるため、Google Earth やインタラクティブなミュージック ビデオ、3D 不動産ウォークスルーなど、ウェブ上で驚きの体験を実現できます。WebGL は、1992 年に初めて開発された OpenGL ファミリーの API をベースとしています。かなり前ですね。それ以降、GPU ハードウェアは大きく進化したことが想像に難くありません。

この進化に対応するため、最新の GPU ハードウェアをより効率的に操作するための新しい API が開発されました。Direct3D 12MetalVulkan などの API。これらの新しい API は、ML の爆発的な進歩やレンダリング アルゴリズムの進歩など、GPU プログラミングの新しい要求の厳しいユースケースをサポートしてきました。WebGPU は WebGL の後継であり、この新しいクラスの最新 API の先進的な機能をウェブに提供します。

WebGPU により、ブラウザで GPU プログラミングの可能性が大きく広がります。最新の GPU ハードウェアの仕組みをより適切に反映し、将来の高度な GPU 機能の基盤を築きます。この API は 2017 年から W3C の「GPU for the Web」グループで開発されており、Apple、Google、Mozilla、Microsoft、Intel などの多くの企業が協力して開発しています。6 年にわたる開発を経て、ウェブ プラットフォームに追加される最大の機能の一つが、ついに利用可能になりました。

WebGPU は現在、ChromeOS、macOS、Windows 版 Chrome 113 で利用できます。他のプラットフォームにも近日中に対応する予定です。これを実現するために協力してくれた他の Chromium コントリビューター、特に Intel に心から感謝いたします。

次は、WebGPU によって実現される優れたユースケースをいくつか見てみましょう。

レンダリング用の新しい GPU ワークロードを活用する

コンピューティング シェーダーなどの WebGPU 機能により、新しいクラスのアルゴリズムを GPU に移植できます。たとえば、シーンにダイナミックなディテールを追加したり、物理的現象をシミュレートしたりできるアルゴリズムなどです。これまで JavaScript でしか実行できなかったワークロードも、GPU に移行できるようになりました。

次の動画は、marching cubes アルゴリズムを使用して、これらのメタボールの表面を三角測量する方法を示しています。動画の最初の 20 秒間、JavaScript で実行されているアルゴリズムは、ページが 8 FPS でしか実行されていないため、ページに追いつくことができません。その結果、アニメーションがぎくしゃくします。JavaScript でパフォーマンスを維持するには、詳細レベルを大幅に下げる必要があります。

同じアルゴリズムをコンピューティング シェーダーに移行すると、動画の 20 秒目以降に示すように、パフォーマンスが大幅に向上します。ページがスムーズな 60 FPS で表示されるようになったことで、パフォーマンスは劇的に向上しました。他の効果にはまだパフォーマンスの余地がたくさんあります。また、ページのメインの JavaScript ループが他のタスクのために完全に解放されるため、ページの操作が常に応答するようになります。

メタボールのデモ

WebGPU により、以前は実用的ではなかった複雑な視覚効果も実現できます。次の例は、一般的な Babylon.js ライブラリで作成されています。海面はすべて GPU でシミュレートされています。リアルなダイナミクスは、多くの独立した波を重ね合わせることで作成されます。ただし、各波を直接シミュレートすると費用がかかりすぎます。

海のデモ

そのため、このデモでは高速フーリエ変換と呼ばれる高度なアルゴリズムを使用しています。すべての波を複雑な位置データとして表現する代わりに、スペクトル データを使用して計算を実行します。次に、各フレームでフーリエ変換を使用して、スペクトル データから波の高さを表す位置データを変換します。

ML 推論の高速化

WebGPU は、近年 GPU の主要な用途となっている ML の高速化にも役立ちます。

クリエイティブ デベロッパーは長い間、WebGL のレンダリング API を再利用して、機械学習の計算など、レンダリング以外のオペレーションを実行してきました。ただし、この方法では、計算を開始する方法として三角形のピクセルを描画し、より汎用的なメモリアクセスではなく、テクスチャ内のテンソルデータを慎重にパックと解凍する必要があります。

WebGL での単一の ML 演算子の実行における非効率性(冗長なメモリ読み込み、冗長な計算、スレッドあたりの書き込み値が少ないなど)を示す図。
WebGL による単一の ML 演算子の実行。

このように WebGL を使用すると、デベロッパーは描画専用に設計された API の要件にコードを無理やり合わせる必要があります。計算間での共有メモリ アクセスなどの基本機能が不足していることも相まって、作業が重複し、最適なパフォーマンスが得られません。

コンピューティング シェーダーは WebGPU の主な新機能であり、これらの問題を解消します。コンピューティング シェーダーは、より柔軟なプログラミング モデルです。レンダリング処理の厳密な構造に縛られることなく、GPU の超並列処理という特性を活用できます。

共有メモリ負荷、共有計算、メモリへの柔軟な書き込みなど、WebGPU コンピューティング シェーダーでさまざまな効率が向上します。
WebGPU コンピューティング シェーダーの効率性。

コンピューティング シェーダーを使用すると、シェーダー処理のグループ内でデータと計算結果を共有できるため、効率性が向上します。そのため、WebGL を同じ目的に使用するという以前の試みと比べて、大幅なメリットが得られる可能性があります。

これにより得られる効率性の向上の一例として、TensorFlow.js の画像拡散モデルの最初のポートは、WebGL から WebGPU に移行したときに、さまざまなハードウェアでパフォーマンスが 3 倍向上しています。テストした一部のハードウェアでは、10 秒未満で画像がレンダリングされました。これは初期段階のポーティングであるため、WebGPU と TensorFlow.js の両方でさらに改善できると考えています。2023 年のウェブ ML の最新情報をご覧ください。Google I/O セッション。

しかし、WebGPU は GPU 機能をウェブに導入するだけではありません。

JavaScript 向けに設計

このようなユースケースを実現する機能は、プラットフォーム固有の PC デベロッパーとモバイル デベロッパーが長い間利用してきました。ウェブ プラットフォームの自然な一部のようにこれらの機能を公開することが、Google の課題でした。

WebGPU は、10 年以上にわたり WebGL で優れた成果をあげているデベロッパーたちの知見を活用して開発されました。ユーザーから寄せられた問題、ボトルネック、問題をすべてこの新しい API にフィードバックしました。

WebGL のグローバル状態モデルでは、堅牢でコンポーザブルなライブラリやアプリケーションを作成することが難しく、脆弱であることがわかりました。そのため、WebGPU では、GPU コマンドを送信する際にデベロッパーが追跡する必要がある状態の量が大幅に削減されます。

WebGL アプリケーションのデバッグが面倒だという声をよく聞きます。WebGPU には、パフォーマンスを低下させない、より柔軟なエラー処理メカニズムが含まれています。また、Google は、API から返されるすべてのメッセージをわかりやすく、実行可能なものにするよう徹底しています。

また、JavaScript を多用しすぎると、複雑な WebGL アプリケーションのボトルネックになることが多々あることもわかりました。その結果、WebGPU API はチャットが少なくなり、関数呼び出しを減らしてより多くのことを実現できます。重要な描画ループはできるだけスリムに保ち、重量級の検証を事前に行うことに重点を置いています。また、レンダリング バンドルなどの新しい API も提供されています。これにより、大量の描画コマンドを事前に記録し、1 回の呼び出しで再生できます。

レンダリング バンドルのような機能がもたらす劇的な違いを示すために、Babylon.js の別のデモもご覧になれます。WebGL 2 レンダラは、すべての JavaScript 呼び出しを実行して、このアートギャラリーのシーンを 1 秒あたり約 500 回レンダリングできます。かなり良いです。

アート ギャラリー

ただし、WebGPU レンダラでは、スナップショット レンダリングと呼ばれる機能が有効になっています。WebGPU のレンダリング バンドルの上に構築されたこの機能により、同じシーンを 10 倍以上速く送信できます。これによりオーバーヘッドが大幅に削減され、WebGPU はより複雑なシーンをレンダリングできるようになりました。また、アプリケーションは JavaScript でより多くのことを並行して行うことができるようになりました。

最新のグラフィック API は複雑で、シンプルさを犠牲にして極端な最適化の機会を追求しているという評判があります。一方、WebGPU はクロスプラットフォームの互換性に重点を置いており、リソースの同期など、従来は難しかったトピックをほとんどの場合自動的に処理します。

これにより、WebGPU の学習と使用が容易になります。画像や動画の読み込みなどにはウェブ プラットフォームの既存の機能を使用します。また、非同期オペレーションには Promise などのよく知られた JavaScript パターンを利用します。これにより、必要なボイラプレートコードの量を最小限に抑えることができます。50 行未満のコードを記述するだけで、最初の三角形を画面に表示できます。

<canvas id="canvas" width="512" height="512"></canvas>
<script type="module">
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();

  const context = canvas.getContext("webgpu");
  const format = navigator.gpu.getPreferredCanvasFormat();
  context.configure({ device, format });

  const code = `
    @vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
      @builtin(position) vec4f {
       const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
       return vec4f(pos[i], 0, 1);
    }
    @fragment fn fragmentMain() -> @location(0) vec4f {
      return vec4f(1, 0, 0, 1);
    }`;
  const shaderModule = device.createShaderModule({ code });
  const pipeline = device.createRenderPipeline({
    layout: "auto",
    vertex: {
      module: shaderModule,
      entryPoint: "vertexMain",
    },
    fragment: {
      module: shaderModule,
      entryPoint: "fragmentMain",
      targets: [{ format }],
    },
  });
  const commandEncoder = device.createCommandEncoder();
  const colorAttachments = [
    {
      view: context.getCurrentTexture().createView(),
      loadOp: "clear",
      storeOp: "store",
    },
  ];
  const passEncoder = commandEncoder.beginRenderPass({ colorAttachments });
  passEncoder.setPipeline(pipeline);
  passEncoder.draw(3);
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
</script>

まとめ

WebGPU がウェブ プラットフォームにもたらす新しい可能性に期待しています。WebGPU の新しいユースケースがどのように広がっていくのか、楽しみです。

WebGL を中心に、ライブラリとフレームワークの活気あるエコシステムが構築されています。このエコシステムは、WebGPU を積極的に採用しています。WebGPU のサポートは進行中であるか、多くの一般的な JavaScript WebGL ライブラリですでに完了しています。場合によっては、1 つのフラグを変更するだけで WebGPU のメリットを活用できることがあります。

Babylon.js、Construct 3、Google Earth、Google Meet、PlayCanvas、Sketchfab、Three.JS、TensorFlow.js、Unity。
WebGPU ポートが完成しているか進行中のものがあるフレームワーク、アプリケーション、ライブラリ。

今回の Chrome 113 での最初のリリースは、ほんの始まりにすぎません。初回リリースは Windows、ChromeOS、MacOS ですが、将来的には Android や Linux など、残りのプラットフォームでも WebGPU を提供する予定です。

WebGPU のリリースに向けて取り組んでいるのは Chrome チームだけではありません。Firefox と WebKit でも実装が進行中です。

また、ハードウェアで利用可能になったときに公開できる新機能が W3C ですでに設計されています。たとえば、Chrome では、機械学習のパフォーマンスをさらに向上させるため、まもなくシェーダーでの 16 ビット浮動小数点数をサポートし、DP4a クラス命令を有効にすることを計画しています。

WebGPU は、投資すれば驚異的なパフォーマンスを発揮する包括的な API です。今回は、WebGPU のメリットについて概要のみ説明しました。WebGPU を使い始めるにあたっては、入門用 Codelab「初めての WebGPU アプリ」をご覧ください。この Codelab では、古典的なコンウェイのライフゲームの GPU バージョンを作成します。この Codelab では、GPU 開発を初めて行う場合でも試すことができる、手順を順を追って説明します。

また、WebGPU サンプルも、API の実情を理解するのに適しています。従来の「Hello Triangle」から、より完全なレンダリング パイプラインとコンピューティング パイプラインまで、さまざまなテクニックが示されています。その他のリソースもご覧ください。