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 のコントリビューター、特にインテルの皆さんに多大なる感謝を。

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

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

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

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

同じアルゴリズムをコンピューティング シェーダーに移した場合、日中と夜の差が顕著になります。これは、20 秒後の動画に表示されます。ページがスムーズな 60 FPS で表示されるようになったことで、パフォーマンスは劇的に向上しました。他のエフェクトについては、パフォーマンス向上の余地はまだ十分にあります。さらに、ページのメインの JavaScript ループが他のタスクに完全に解放されるため、ページとのやり取りの応答性が保たれます。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> メタボールのデモ

WebGPU により、以前は実用的ではなかった複雑な視覚効果も実現できます。次の例では、広く普及している Babylon.js ライブラリで作成された、海面を完全に GPU でシミュレートしています。現実的なダイナミクスは、多くの独立した波が互いに追加されることで作成されます。しかし、各波を直接シミュレートすると、コストがかかりすぎます。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> 海のデモ

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

ML 推論の高速化

WebGPU は、近年 GPU が主流になっている ML の高速化にも有用です。

長い間、クリエイティブ デベロッパーは WebGL のレンダリング API を再利用して、ML 計算などの非レンダリング処理を実行してきました。しかし、そのためには、計算を開始する方法として三角形のピクセルを描画し、テンソルデータを汎用的なメモリアクセスではなくテクスチャ内で慎重にパッキングおよびアンパックする必要があります。

<ph type="x-smartling-placeholder">
</ph> 冗長なメモリ読み込み、冗長な計算、スレッドごとに書き込まれる少数の値など、WebGL を使用して単一の ML 演算子を実行する際の非効率性を示す図。 <ph type="x-smartling-placeholder">
</ph> WebGL を使用した単一の ML オペレーターの実行。

この方法で WebGL を使用する場合、描画専用に設計された API に想定内のコードが適合しなくなるため、開発者が気を取られる可能性があります。計算間の共有メモリアクセスなどの基本的な機能の欠如と相まって、作業が重複し、最適なパフォーマンスが得られません。

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

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

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

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

ただし、WebGPU の目的は、GPU 機能をウェブに導入することだけではありません。

JavaScript 対応の設計

これらのユースケースを可能にする機能は、プラットフォーム固有のデスクトップ デベロッパーとモバイル デベロッパーが以前から提供してきましたが、ウェブ プラットフォームに自然になじむ方法でそれらを公開することが、私たちの課題となっていました。

WebGPU は、10 年以上にわたり WebGL で素晴らしい成果を上げているデベロッパーたちの知見を活用して開発されました。直面した問題、発生したボトルネック、提起された問題を取り込んで、すべてのフィードバックをこの新しい API に取り込むことができました。

WebGL のグローバルな状態モデルにより、堅牢でコンポーズ可能なライブラリやアプリケーションの作成が困難かつ脆弱であることが判明しました。そのため WebGPU では、開発者が GPU コマンドを送信する際に追跡する必要がある状態の量を大幅に削減できます。

WebGL アプリケーションのデバッグは手間がかかるというご意見をいただいたため、WebGPU にはより柔軟なエラー処理メカニズムが組み込まれており、パフォーマンスが低下することはありません。また、Google は、API から返されるすべてのメッセージをわかりやすく、実行可能なものにするよう徹底しています。

また、JavaScript を過剰に呼び出すことで発生するオーバーヘッドが複雑な WebGL アプリケーションのボトルネックになることもわかりました。その結果、WebGPU API ではチャットが減るため、より少ない関数呼び出しでより多くの処理を実行できます。前もって重量級の検証を行うことに重点を置き、クリティカルな描画ループをできるだけ無駄をなくします。また、レンダリング バンドルなどの新しい API も用意しています。この API を使用すると、大量の描画コマンドを事前に記録し、1 回の呼び出しで再生できます。

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

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
</ph> アート ギャラリー

ただし、WebGPU レンダラでは、スナップショット レンダリングと呼ばれる機能を利用できます。WebGPUs レンダリング バンドル上に構築されたこの機能により、同じシーンを 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 のメリットを活用できることがあります。

<ph type="x-smartling-placeholder">
</ph> Babylon.js、Construct 3、Google Earth、Google Meet、PlayCanvas、Scottfab、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 を初めて使用する場合は、入門編の Codelab「初めての WebGPU アプリ」をご覧ください。この Codelab では、名作コンウェイのライフゲームの GPU 版を作成します。この Codelab では手順を 1 つずつ説明するので、GPU 開発が初めてでも試してみることができます。

また、WebGPU サンプルも、API の実情を理解するのに適しています。伝統的な「ハロートライアングル」やさまざまな手法を紹介しながら、レンダリングとコンピューティング パイプラインを完成させます。最後に、その他のリソースをご確認ください。