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

瞭解 WebGPU 如何發揮 GPU 的強大力量,提升機器學習效能,並改善圖像算繪品質。

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

全新 WebGPU API 可以大幅提升圖形和機器學習工作負載的效能。本文將探討 WebGPU 如何改善目前的 WebGL 解決方案,並搶先一窺未來的發展。不過,我們先來談談 WebGPU 的開發背景。

WebGPU 背景資訊

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

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

WebGPU 可在瀏覽器中開啟許多新的 GPU 程式設計可能性。這項更新更能反映現代 GPU 硬體的運作方式,同時也為日後更進階的 GPU 功能奠定基礎。自 2017 年起,這個 API 就已在 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 上模擬海洋表面。這些真實動態是由許多獨立波次互相相互結合的。但直接模擬每個波形的成本太高。

海洋示範

因此,本示範使用了名為「快速傅立葉轉換」的進階演算法。這項功能不會將所有波浪都表示為複雜的位置資料,而是使用光譜資料,這類資料可更有效率地執行運算。接著,每個影格都會使用傅立葉變換,將光譜資料轉換為代表波浪高度的位置資料。

加快機器學習推論速度

WebGPU 也能用於加快機器學習的速度,這也是近年來 GPU 的主要用途。

長久以來,創意開發人員一直將 WebGL 的轉譯 API 重新用於執行非轉譯作業,例如機器學習運算。不過,這需要繪製三角形的像素,以便啟動運算,並在紋理中仔細地打包和解包張量資料,而不是使用更通用的記憶體存取方式。

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

以這種方式使用 WebGL 會讓開發人員必須尷尬地讓程式碼符合 API 的預期,而該 API 只設計用於繪圖。加上缺乏基本功能 (例如在運算之間共用記憶體存取),導致重複工作和效能不佳。

運算著色器是 WebGPU 的主要新功能,可解決這些問題。運算著色器提供更具彈性的程式設計模式,可充分利用 GPU 的大量平行特性,同時不受算繪作業嚴格結構的限制。

WebGPU 運算著色器的各種效率提升,包括共用記憶體載入、共用運算,以及靈活的記憶體寫入。
WebGPU 運算著色器效率。

運算著色器可讓您在不同著色器工作群組之間共用資料和運算結果,提高效率。這可能會導致先前嘗試針對相同用途使用 WebGL 的次數大幅增加。

舉例來說,在 TensorFlow.js 中,圖片擴散模型的初始匯出版本從 WebGL 移至 WebGPU 後,在各種硬體上顯示 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 的通訊量較少,您可以透過較少的函式呼叫完成更多工作。我們會著重於事先執行重量驗證,盡可能讓關鍵繪圖迴圈保持精簡。我們也提供新的 API,例如算繪套件,可讓您預先記錄大量繪圖指令,並透過單一呼叫重播這些指令。

為了展示轉譯組件等功能所帶來的巨大差異,這裡提供另一個 Babylon.js 的示範。他們的 WebGL 2 轉譯器可以執行所有 JavaScript 呼叫,以每秒約 500 次算繪這個藝廊場景。這很不錯!

藝廊

然而,WebGPU 轉譯器會啟用呼叫快照轉譯功能。這項功能以 WebGPU 算繪套件為基礎,可讓相同場景的提交速度提高 10 倍以上。這項功能大幅減少了額外負擔,讓 WebGPU 能夠算繪更複雜的場景,同時讓應用程式可並行執行更多 JavaScript 作業。

現代圖形 API 以複雜度聞名,為了極致最佳化,犧牲了簡易性。另一方面,WebGPU 著重於跨平台相容性,可處理傳統上較為困難的主題,例如在大多數情況下自動同步處理資源。

這也帶來了一個好處,就是 WebGPU 很容易學習和使用。它會依賴網路平台的現有功能,處理圖片和影片載入作業,並採用知名的 JavaScript 模式,例如用於非同步作業的 Promise。這有助於盡量減少所需的樣板程式碼數量。您可以透過不到 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、Construct 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,可以參考我們的入門程式碼研究室,也就是您的第一個 WebGPU 應用程式。在本程式碼研究室中,您將建立一個 GPU 版本的經典 Conway 生命遊戲。本程式碼研究室會逐步引導您完成整個程序,因此就算您是第一次進行 GPU 開發,也可以試用。

WebGPU 範例也是體驗 API 的好地方。從傳統的「hello triangle」到更完整的轉譯和運算管道,展示各種技術。最後,請查看其他資源