WebGPU:在瀏覽器中解鎖新型 GPU 存取權

瞭解 WebGPU 如何充分發揮 GPU 的強大威力,提高機器學習效能和圖形算繪能力。

Corentin Wallez
Corentin Wallez
François Beaufort
François Beaufort

全新 WebGPU API 可以大幅提升圖形和機器學習工作負載的效能。本文將探討 WebGPU 如何比目前的 WebGL 解決方案更加完善,並搶先一窺未來的開發成果。首先,以下簡要說明 WebGPU 開發的原因。

WebGPU 背景資訊

WebGL 在 2011 年推出。WebGL 可讓網頁應用程式充分運用 GPU,進而在網路上提供驚人體驗,包括 Google 地球、互動式音樂影片和 3D 實境解說等。WebGL 是以 1992 年首次開發的 OpenGL 系列為基礎。很久以前!而 GPU 硬體也從那時起大幅進化。

為了跟上演進過程的腳步,我們開發了一套全新品種 API,以更有效率的方式與現代 GPU 硬體互動。Direct3D 12MetalVulkan 等 API。這些新的 API 支援 GPU 程式設計的全新且嚴苛的用途,例如機器學習的爆炸,以及轉譯演算法的進展。WebGPU 是 WebGL 的後續版本,將這種新型新型 API 的 API 推向網路。

WebGPU 在瀏覽器中開啟許多新的 GPU 程式設計。這個類型更能反映現代 GPU 硬體的運作方式,同時為日後發展更進階的 GPU 功能奠定基礎。這個 API 自 2017 年起就開始在 W3C 的「GPU for the Web」群組中打造,並是由 Apple、Google、Mozilla、Microsoft 和 Intel 等眾多公司攜手合作。在經過 6 年努力的今天,我們很高興在此宣布,網路平台的新增功能現已正式推出!

WebGPU 目前已在 ChromeOS、macOS 和 Windows 上推出,也將陸續支援其他平台。非常感謝其他 Chromium 貢獻者和 Intel 幕後的貢獻。

現在,我們來看看 WebGPU 支援的幾個精彩用途。

發掘新的 GPU 工作負載以進行轉譯

您可以透過運算著色器等 WebGPU 功能,將新的演算法類別移植到 GPU 上。例如,演算法可在場景中加入更多動態細節、模擬物理現象等等!甚至還有之前只能在 JavaScript 中執行的工作負載,現在可以移至 GPU。

以下影片展示如何使用遊行立方體演算法來估算這類中繼球的表面。在影片的前 20 秒內,演算法在以 JavaScript 執行時,無法確保網頁僅以每秒 8 個影格數執行,導致動畫卡頓。為維持 JavaScript 的效能,我們需要大幅降低詳細資料層級。

我們將相同的演算法移至運算著色器,會在 20 秒後出現在影片中。此頁面現在以每秒 60 FPS 的速度順暢執行,使得效能大幅改善,而其他影響還有很多效能進步空間。此外,網頁的主要 JavaScript 迴圈已完全釋放到其他工作,確保與網頁的互動保持回應。

Metaball 示範

WebGPU 也提供過去可能不實用的複雜視覺效果。在下列範例中,根據熱門的 Babylon.js 程式庫建立,海洋表面的模擬就是在 GPU 上完全模擬。這些真實動態是由許多獨立波次互相相互結合的。但直接模擬每一波的成本會過高。

海洋示範

因此,示範模式使用名為 Fast Fourier Transform 的進階演算法。這種模式使用光譜資料執行運算更有效率,而非將所有波浪表示為複雜的定位資料。接著每個影格會使用 Fourier Transform,從光譜資料轉換成代表波形高度的位置資料。

加快機器學習推論速度

WebGPU 也有助於加速機器學習,而 WebGPU 已成為近年來大量使用 GPU 的主要用途。

廣告素材開發人員長久以來一直使用 WebGL 的算繪 API 來執行機器學習運算等非轉譯作業。不過,您需要繪製三角形的像素作為計算方法,並謹慎地在紋理中打包及拆分張量資料,而非進行一般用途的記憶體存取行為。

這張插圖顯示使用 WebGL 執行單一機器學習運算子時效率不佳的問題,包括多餘的記憶體載入、多餘運算,以及每個執行緒寫入的值很少。
透過 WebGL 執行單一機器學習運算子。

透過這種方式使用 WebGL 時,開發人員不得不遵循專為繪圖設計的 API 所期望的程式碼。如果結合缺少基本功能 (例如在運算之間共用記憶體存取權),就會導致重複工作,效能不盡理想。

運算著色器是 WebGPU 的主要新功能,可以消除這些棘手的問題。運算著色器提供更具彈性的程式設計模型,利用 GPU 的大量平行特性,而且不受轉譯作業的嚴格結構限制。

可在 WebGPU 運算著色器中大幅提升效率,包括共用記憶體負載、共用運算以及靈活寫入記憶體。
WebGPU 運算著色器的效率。

運算著色器讓有更多機會在著色器群組中分享資料和計算結果,進而提升效率。這可能會導致先前嘗試針對相同用途使用 WebGL 的次數大幅增加。

舉例來說,從 WebGL 轉移到 WebGPU 後,在 TensorFlow.js 中,圖像擴散模型的初始通訊埠顯示出各種硬體的效能提升了 3 倍。在某些硬體上,測試圖片的比例不到 10 秒。由於這是早期的通訊埠,我們認為 WebGPU 和 TensorFlow.js 還有更多改善空間!歡迎查看「2023 年 Web ML 最新消息」Google I/O 大會講座。

然而 WebGPU 不僅僅是將 GPU 功能帶到網路上而已。

優先針對 JavaScript 設計

適用於特定平台的功能已推出一陣子,專供電腦版和行動版開發人員使用,而我們想讓開發人員能以類似網路平台的習慣的方式呈現這些功能。

WebGPU 是開發 WebGPU 之後,至今受惠於 10 多年的開發人員所打造的工具,我們得以找出他們遇到的問題、發現的瓶頸,以及他們提出的問題,並將所有意見回饋彙整到這個新的 API。

WebGL 的全域狀態模型使得建立強大可組合的程式庫和應用程式相當困難與脆弱。因此 WebGPU 會大幅減少開發人員傳送 GPU 指令時需要追蹤的狀態量。

我們瞭解對 WebGL 應用程式偵錯是件痛苦的事,因此 WebGPU 採用更有彈性的錯誤處理機制,不會阻礙您的效能。我們已著手確保從 API 傳回的每則訊息都容易理解且可採取行動

我們也發現,常常需要發出過多 JavaScript 呼叫,是複雜 WebGL 應用程式的瓶頸。因此,WebGPU API 的聊天性較低,因此您可以減少函式呼叫,完成更多工作。我們的重點是預先執行密集驗證,盡可能讓關鍵繪製迴圈保持精簡。此外,我們也提供 Render Bundle 等新 API,讓您預先錄製大量繪圖指令,並透過單一呼叫重播這些指令。

若想瞭解算繪套裝組合等功能帶來的顯著差異,請觀看這部 Babylon.js 的示範影片。他們的 WebGL 2 轉譯器可以執行所有 JavaScript 呼叫,以每秒約 500 次算繪這個藝廊場景。還不錯!

畫廊

然而,WebGPU 轉譯器會啟用呼叫快照轉譯功能。這項功能以 WebGPU 轉譯套件為基礎,在同一個場景的提交速度超過 10 倍。此方式大幅減少負擔,讓 WebGPU 轉譯較複雜的場景,同時讓應用程式平行執行更多工作。

現代圖像 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。許多熱門 JavaScript WebGL 程式庫都在處理中或已正式支援 WebGPU,在某些情況下,想發揮 WebGPU 的優勢,可能就像變更單一標記一樣簡單!

Babylon.js、Build 3、Google 地球、Google Meet、PlayCanvas、Sketchfab、Three.JS、TensorFlow.js 和 Unity。
含有完成或持續性 WebGPU 通訊埠的架構、應用程式和程式庫。

此外,這是 Chrome 113 版的第一個版本。雖然我們推出的初始版本適用於 Windows、ChromeOS 和 MacOS,但我們計劃不久後將 WebGPU 導入其他平台,例如 Android 和 Linux。

而且 Chrome 團隊並非只有致力推出 WebGPU 的團隊。我們也正在開發 Firefox 和 WebKit 的應用程式。

此外,我們已在 W3C 設計新功能,可於硬體提供時公開。例如:在 Chrome 中,我們計劃在著色器中啟用 16 位元浮點數DP4a 操作說明類別,進一步提升機器學習效能。

WebGPU 是精密的 API,值得您投入心力開發更多產品,進而擁有優異的效能。目前我們只能概略介紹其優點。如果您想開始使用 WebGPU,請參閱我們的入門程式碼研究室,也就是您的第一個 WebGPU 應用程式。在本程式碼研究室中,您將建構經典的 Conway 的生命遊戲產業版本 (GPU 版本)。本程式碼研究室會逐步引導您完成整個程序,因此就算您是第一次進行 GPU 開發,也可以試用。

WebGPU 範例也很適合用來瞭解 API。範圍從傳統的「哈三角形」以更完整的轉譯和運算管道,示範各種技術。最後,請參閱我們的其他資源