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

瞭解 WebGPU 如何發揮 GPU 的強大效能,加快機器學習效能和圖形算繪能力。

François Beaufort
François Beaufort

全新的 WebGPU API 大幅提升圖形和機器學習工作負載的效能。本文將介紹 WebGPU 如何改進目前的 WebGL 解決方案,並讓您預先瞭解未來發展。首先,讓我們提供一些背景資訊,說明 WebGPU 的開發原因。

WebGPU 的相關資訊

WebGL 在 2011 年於 Chrome 中推出。WebGL 可讓網頁應用程式利用 GPU,在網路上提供驚人體驗,包括 Google 地球、互動式音樂影片和 3D 房地產逐步操作說明等。WebGL 是以 1992 年首次開發的 OpenGL API 系列為基礎。很久以前!如您所知,GPU 硬體已大幅演進。

為因應此次發展,我們開發了全新的 API 系列,可提高與新型 GPU 硬體互動的效率。Direct3D 12MetalVulkan 等 API。這些新的 API 支援 GPU 程式設計的全新需求和需求量,例如機器學習爆炸和轉譯演算法的進展。WebGPU 是 WebGL 的後續案例,將這種新型 API 的進展帶到網路世界。

WebGPU 在瀏覽器中開啟了許多 GPU 程式設計的全新方式。這項技術能更準確地反映現代 GPU 硬體的運作方式,並為未來發展奠定更先進 GPU 功能的基礎。這個 API 自 2017 年起便一直在 W3C 的「Web GPU for the Web」組織中發展,是 Apple、Google、Mozilla、Microsoft 和 Intel 等許多公司之間的合作。經過 6 年的工作期後,我們很高興在此宣布,網路平台的新增功能之一已正式推出!

WebGPU 目前適用於 ChromeOS、macOS 和 Windows 上的 Chrome 113,其他平台也即將推出。非常感謝其他 Chromium 貢獻者和 Intel 的協助。

接下來,來看看 WebGPU 有哪些出色的用途。

解鎖新的 GPU 工作負載以進行轉譯

Compute 著色器等 WebGPU 功能,可讓您在 GPU 上移植新的演算法類別。舉例來說,演算法可以在場景中加入更多動態細節、模擬物理現象等。有些工作負載先前只能透過 JavaScript 執行,現在也能夠轉移至 GPU。

以下影片展示運用遊行方塊演算法將這些隱球表面形成的。在影片的前 20 秒,以 JavaScript 執行時,演算法會難以跟上網頁速度,因為網頁僅以 8 FPS 執行時,會造成卡頓的動畫出現不順的情形。為了在 JavaScript 中維持良好效能,我們必須大幅降低細節層級。

當我們將相同的演算法移至運算著色器 (20 秒後) 就會發生在夜間和日間的差異。網頁現在以流暢的每秒 60 個影格數執行,因此效能大幅提升,其他效果仍然需要大量效能調整空間。此外,網頁的主要 JavaScript 迴圈還完全可供其他工作使用,以確保與網頁的互動能保持回應。

中繼球示範

WebGPU 也能實現以往不實用的複雜視覺效果。在以下範例中,這是在熱門的 Babylon.js 程式庫建立,它會在 GPU 上完全模擬海洋表面。實際變化則由許多獨立波紋組成。但直接模擬每個波浪會太高昂貴。

海洋示範

因此,這個示範會使用名為 Fast Fourier Transform 的進階演算法。這個模式會使用光譜資料執行運算,而非將所有波表示為複雜的位置資料。接著,每個框架使用 Fourier Transform 轉換光譜資料,轉換為代表波高度的位置資料。

加快機器學習推論速度

WebGPU 也有助於加快機器學習速度,而這項技術在近年來是 GPU 的主要用途。

長久以來,廣告素材開發人員持續重新運用 WebGL 的算繪 API 來執行機器學習運算這類非算繪作業。然而,這需要繪製三角形的像素來啟動計算,並且謹慎地封裝與解除紋理中的張量資料,而不是較一般用途的記憶體存取。

插圖:使用 WebGL 執行單一機器學習運算子執行時效率不彰的問題,包括多餘的記憶體載入、多餘的運算和每個執行緒寫入的少數值。
透過 WebGL 執行單一機器學習運算子。

如果想以這種方式使用 WebGL,就必須讓開發人員不為合乎僅有繪圖專用 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 後,便採用了十多年來採用 WebGL 技術打造出色的開發人員,開創了絕佳的成果。我們得以解決這些問題和遇到的瓶頸,以及他們提出的問題,並將這些意見回饋統整到這個新的 API。

我們發現 WebGL 的全球狀態模型使得建立強大且易於使用的可組合項程式庫和應用程式。因此,WebGPU 大幅減少了開發人員在傳送 GPU 指令時需要追蹤的狀態量。

據我們所知,對 WebGL 應用程式進行偵錯會很麻煩,因此 WebGPU 提供更多彈性的錯誤處理機制,並不會影響您的效能。此外,我們也設法確保您從 API 傳回的每則訊息都能易於理解與操作

我們也注意到,執行過多 JavaScript 呼叫的負擔經常是複雜的 WebGL 應用程式的瓶頸。因此,WebGPU API 較不易聊天,因此您可以減少函式呼叫來完成更多工作。我們會著重於提前執行繁重驗證,並盡可能保持關鍵繪圖迴圈。此外,我們還提供 Render Bundle 等新 API,可讓您預先記錄大量繪圖指令,並在單一呼叫中重播這些指令。

為了示範算繪套裝組合等功能可帶來哪些重大差異,以下是另一個由 Babylon.js 提供的示範。他們的 WebGL 2 轉譯器可以執行所有 JavaScript 呼叫,每秒算繪這個藝廊場景 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 程式庫中完成支援。在某些情況下,善用 WebGPU 的好處可能就像變更單一旗標一樣簡單!

Babylon.js、建築 3、Google 地球、Google Meet、PlayCanvas、Sketchfab、Three.JS、TensorFlow.js 和 Unity。
含有已完成或正在進行 WebGPU 通訊埠的架構、應用程式和程式庫。

而這個 Chrome 113 版的第一個版本只是起步。雖然初始版本適用於 Windows、ChromeOS 和 MacOS,但我們計劃在不久後將 WebGPU 提供給 Android 和 Linux 等其他平台。

這不只是負責啟動 WebGPU 的 Chrome 團隊。Firefox 和 WebKit 也仍在逐步導入功能。

此外,W3C 設計了新功能,可在硬體中公開。舉例來說,我們預計在 Chrome 中支援在著色器中支援 16 位元浮點數DP4a 類別的操作說明,以進一步提升機器學習效能。

WebGPU 是廣泛的 API,只要投注資源就能大幅提升效能。目前我們只能大致瞭解這項服務的優點,但如果您想開始使用 WebGPU,請參閱入門程式碼研究室:您的第一個 WebGPU 應用程式。在本程式碼研究室中,您將建構 GPU 版本的經典 Conway 的《Game of Life》。本程式碼研究室將逐步引導您完成整個程序,因此即使您是第一次進行 GPU 開發作業,也可以試試看。

WebGPU 範例也是瞭解 API 的好方法。這些標準從傳統的「Hello 三角形」開始,到更完整的轉譯和運算管道,可展現出各式各樣的技術。最後,您也可以參閱其他資源