WebGPU: Mở khoá quyền truy cập GPU hiện đại trong trình duyệt

Tìm hiểu cách WebGPU khai thác sức mạnh của GPU để tăng hiệu suất học máy và kết xuất đồ hoạ tốt hơn.

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

API WebGPU mới giúp tăng đáng kể hiệu suất cho khối lượng công việc liên quan đến đồ hoạ và học máy. Bài viết này khám phá cách WebGPU là một sự cải tiến so với giải pháp hiện tại của WebGL, với cơ hội hé lộ về sự phát triển trong tương lai. Nhưng trước tiên, hãy cung cấp một số ngữ cảnh về lý do WebGPU được phát triển.

Ngữ cảnh trên WebGPU

WebGL ra mắt trên Chrome vào năm 2011. Bằng cách cho phép các ứng dụng web tận dụng GPU, WebGL giúp mang đến những trải nghiệm tuyệt vời trên web — từ Google Earth, đến video nhạc tương tác, đến hướng dẫn từng bước về bất động sản 3D và hơn thế nữa. WebGL dựa trên dòng API OpenGL được phát triển lần đầu vào năm 1992. Đã lâu lắm rồi! Và bạn có thể hình dung rằng phần cứng GPU đã phát triển đáng kể kể từ thời điểm đó.

Để bắt kịp sự phát triển này, một loại API mới đã được phát triển để tương tác hiệu quả hơn với phần cứng GPU hiện đại. Các API như Direct3D 12, MetalVulkan. Những API mới này hỗ trợ các trường hợp sử dụng mới và khó lập trình GPU, chẳng hạn như sự bùng nổ của công nghệ học máy và các tiến bộ trong thuật toán kết xuất hình ảnh. WebGPU là sản phẩm kế thừa cho WebGL, đưa những tiến bộ của loại API hiện đại mới này lên web.

WebGPU mở ra rất nhiều khả năng lập trình GPU mới trong trình duyệt. Điểm số này phản ánh chính xác hơn cách hoạt động của phần cứng GPU hiện đại, đồng thời đặt nền móng cho các tính năng GPU tiên tiến hơn trong tương lai. API này đã được tích hợp trong nhóm "GPU cho web" của W3C kể từ năm 2017 và là sự cộng tác giữa nhiều công ty như Apple, Google, Mozilla, Microsoft và Intel. Sau 6 năm hoạt động, chúng tôi rất vui được thông báo rằng một trong những tính năng lớn nhất mà nền tảng Web này cuối cùng cũng đã ra mắt!

WebGPU hiện có trong Chrome 113 trên ChromeOS, macOS và Windows, và sẽ sớm ra mắt trên các nền tảng khác. Rất cảm ơn những người đóng góp khác cho Chromium và đặc biệt là Intel, những người đã góp phần làm nên điều này.

Giờ hãy cùng xem qua một số trường hợp sử dụng thú vị mà WebGPU hỗ trợ.

Khai thác khối lượng công việc mới của GPU để kết xuất

Các tính năng WebGPU như trình đổ bóng điện toán cho phép chuyển các lớp thuật toán mới trên GPU. Ví dụ: các thuật toán có thể thêm nhiều chi tiết động hơn vào cảnh, mô phỏng các hiện tượng vật lý, v.v.! Thậm chí có những khối lượng công việc trước đây chỉ có thể thực hiện được trong JavaScript, giờ đây có thể được chuyển sang GPU.

Video sau đây cho thấy thuật toán khối lập phương di chuyển được dùng để tạo tam giác bề mặt của các metaball này. Trong 20 giây đầu tiên của video, thuật toán khi chạy trong JavaScript, gặp khó khăn trong việc theo kịp trang chỉ chạy ở tốc độ 8 FPS dẫn đến hoạt ảnh bị giật. Để giữ cho công cụ này hoạt động hiệu quả trong JavaScript, chúng ta cần phải giảm cấp độ chi tiết đi rất nhiều.

Đó là một sự khác biệt ngày và đêm khi chúng ta chuyển cùng một thuật toán sang một chương trình đổ bóng điện toán, xuất hiện trong video sau 20 giây. Hiệu suất cải thiện đáng kể với trang hiện đang chạy ở tốc độ 60 khung hình/giây mượt mà và vẫn còn nhiều khả năng về hiệu suất cho các hiệu ứng khác. Ngoài ra, vòng lặp JavaScript chính của trang được giải phóng hoàn toàn cho các tác vụ khác, đảm bảo rằng các tương tác với trang luôn phản hồi.

Bản minh hoạ về metaball

WebGPU cũng hỗ trợ các hiệu ứng hình ảnh phức tạp mà trước đây không thiết thực. Trong ví dụ sau đây được tạo trong thư viện Babylon.js phổ biến, bề mặt đại dương đang được mô phỏng toàn bộ trên GPU. Động lực thực tế được tạo ra từ nhiều sóng độc lập bổ sung vào nhau. Nhưng việc mô phỏng trực tiếp từng sóng sẽ rất tốn kém.

Bản minh hoạ về đại dương

Đó là lý do bản minh hoạ sử dụng một thuật toán nâng cao có tên là Chuyển đổi Fourier nhanh. Thay vì biểu thị tất cả các sóng dưới dạng dữ liệu vị trí phức tạp, phương pháp này sử dụng dữ liệu quang phổ hiệu quả hơn nhiều để thực hiện các phép tính. Sau đó, mỗi khung sử dụng Biến đổi Fourier để chuyển đổi từ dữ liệu quang phổ sang dữ liệu vị trí biểu thị chiều cao của sóng.

Suy luận bằng công nghệ học máy nhanh hơn

WebGPU cũng rất hữu ích trong việc tăng tốc độ của công nghệ học máy, vốn đã trở thành một công cụ chính của GPU trong những năm gần đây.

Trong thời gian dài, các nhà phát triển sáng tạo đã sử dụng lại API kết xuất của WebGL để thực hiện các hoạt động không kết xuất như các phép tính theo mô hình học máy. Tuy nhiên, việc này đòi hỏi bạn phải vẽ các pixel của tam giác để bắt đầu tính toán và đóng gói và giải nén cẩn thận dữ liệu tensor trong kết cấu thay vì các quyền truy cập bộ nhớ cho mục đích chung.

Hình minh hoạ sự kém hiệu quả trong quá trình thực thi một toán tử ML bằng WebGL, bao gồm cả việc tải bộ nhớ dư thừa, tính toán dư thừa và ít giá trị được ghi cho mỗi luồng.
Thực thi một toán tử học máy bằng WebGL.

Việc sử dụng WebGL theo cách này yêu cầu các nhà phát triển phải tuân thủ một cách khó khăn mã của họ so với kỳ vọng của một API được thiết kế chỉ dành cho việc vẽ. Cùng với việc thiếu các tính năng cơ bản như quyền truy cập bộ nhớ dùng chung giữa các phép tính, điều này khiến công việc bị trùng lặp và hiệu suất dưới mức tối ưu.

Chương trình đổ bóng điện toán là tính năng mới chính của WebGPU nên sẽ loại bỏ những vấn đề này. Chương trình đổ bóng điện toán cung cấp mô hình lập trình linh hoạt hơn, tận dụng tính chất siêu song song của GPU mà không bị hạn chế bởi cấu trúc nghiêm ngặt của hoạt động kết xuất.

Nhiều mức tăng hiệu suất trong chương trình đổ bóng điện toán WebGPU, bao gồm tải bộ nhớ dùng chung, tính toán dùng chung và ghi linh hoạt vào bộ nhớ.
Hiệu quả của chương trình đổ bóng điện toán WebGPU.

Chương trình đổ bóng điện toán mang lại nhiều cơ hội hơn để chia sẻ dữ liệu và kết quả tính toán trong các nhóm hoạt động của chương trình đổ bóng nhằm đạt được hiệu quả cao hơn. Điều này có thể mang lại kết quả đáng kể so với những lần thử sử dụng WebGL cho cùng một mục đích trước đây.

Một ví dụ về khả năng tăng hiệu quả mà điều này có thể mang lại, cổng ban đầu của mô hình khuếch tán hình ảnh trong TensorFlow.js cho thấy hiệu suất tăng gấp 3 lần trên nhiều phần cứng khi chuyển từ WebGL sang WebGPU. Trên một số phần cứng đã được kiểm tra, hình ảnh kết xuất trong vòng chưa đầy 10 giây. Vì đây là cổng mới, nên chúng tôi tin rằng cả WebGPU và TensorFlow.js sẽ còn có thể cải tiến hơn nữa! Hãy xem bài viết Những điểm mới của công nghệ học máy trên web trong năm 2023 Phiên hội thảo tại Google I/O.

Tuy nhiên, WebGPU không chỉ đơn thuần là mang các tính năng GPU lên web.

Ưu tiên thiết kế cho JavaScript

Các tính năng hỗ trợ những trường hợp sử dụng này đã được cung cấp cho các nhà phát triển dành cho thiết bị di động và máy tính để bàn theo nền tảng cụ thể được một thời gian. Tuy nhiên, chúng tôi gặp khó khăn trong việc đưa các tính năng này vào theo cách giống như một phần tự nhiên của nền tảng web.

WebGPU được phát triển với lợi ích của chế độ xem từ hơn một thập kỷ qua các nhà phát triển làm việc tuyệt vời với WebGL. Chúng tôi có thể xem xét những vấn đề họ gặp phải, nút thắt cổ chai cũng như những vấn đề họ nêu và chuyển tất cả phản hồi đó vào API mới này.

Chúng tôi nhận thấy rằng mô hình trạng thái toàn cầu của WebGL đã khiến việc tạo thư viện và ứng dụng mạnh mẽ, có khả năng kết hợp trở nên khó khăn và dễ dàng. Vì vậy, WebGPU giảm đáng kể trạng thái mà nhà phát triển cần theo dõi trong khi gửi các lệnh GPU.

Chúng tôi biết rằng việc gỡ lỗi ứng dụng WebGL rất khó khăn, vì vậy WebGPU có các cơ chế xử lý lỗi linh hoạt hơn mà không ảnh hưởng đến hiệu suất. Đồng thời, chúng tôi đã nỗ lực hết mình để đảm bảo rằng mọi thông báo bạn nhận được từ API đều dễ hiểu và dễ áp dụng.

Chúng tôi cũng thấy rằng thường xuyên, chi phí thực hiện quá nhiều lệnh gọi JavaScript là nút thắt cổ chai cho các ứng dụng WebGL phức tạp. Do đó, API WebGPU ít nhắn tin hơn, vì vậy bạn có thể hoàn thành nhiều việc hơn với ít lệnh gọi hàm hơn. Chúng tôi tập trung vào việc xác thực hạng nặng từ đầu, đảm bảo vòng lặp vẽ quan trọng tinh gọn nhất có thể. Ngoài ra, chúng tôi còn cung cấp các API mới như Gói kết xuất, cho phép bạn ghi lại trước số lượng lớn các lệnh vẽ và phát lại các lệnh đó bằng một lệnh gọi duy nhất.

Để minh hoạ sự khác biệt đáng kể mà một tính năng như gói kết xuất có thể tạo ra, đây là một bản minh hoạ khác từ Babylon.js. Trình kết xuất WebGL 2 của họ có thể thực thi tất cả các lệnh gọi JavaScript để kết xuất cảnh phòng trưng bày nghệ thuật này khoảng 500 lần một giây. Điều này khá tốt!

Phòng tranh

Tuy nhiên, trình kết xuất WebGPU của họ kích hoạt một tính năng gọi là Kết xuất ảnh chụp nhanh. Được xây dựng dựa trên các gói kết xuất WebGPU, tính năng này cho phép gửi cùng một cảnh nhanh hơn gấp 10 lần. Mức hao tổn này giảm đáng kể cho phép WebGPU hiển thị các cảnh phức tạp hơn, trong khi cũng cho phép các ứng dụng thực hiện nhiều thao tác hơn với JavaScript song song.

API đồ hoạ hiện đại nổi tiếng với sự phức tạp, đánh đổi sự đơn giản để có được các cơ hội tối ưu hoá cực kỳ lớn. Mặt khác, WebGPU tập trung vào khả năng tương thích giữa nhiều nền tảng, xử lý các chủ đề truyền thống khó khăn như đồng bộ hoá tài nguyên trong hầu hết các trường hợp.

Điều này có tác dụng phụ là WebGPU dễ tìm hiểu và sử dụng. Nó dựa trên các tính năng hiện có của nền tảng web cho những việc như tải hình ảnh và video, đồng thời dựa vào các mẫu JavaScript phổ biến như Promise cho các hoạt động không đồng bộ. Điều này giúp giữ cho số lượng mã nguyên mẫu cần thiết ở mức tối thiểu. Bạn có thể hiển thị hình tam giác đầu tiên trên màn hình trong chưa đầy 50 dòng mã.

<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>

Kết luận

Thật thú vị khi được chứng kiến tất cả những khả năng mới mà WebGPU mang đến cho nền tảng web, và chúng tôi rất mong được thấy tất cả những trường hợp sử dụng mới, thú vị mà các bạn sẽ tìm thấy cho WebGPU!

Một hệ sinh thái thư viện và khung mạnh mẽ đã được xây dựng dựa trên WebGL và hệ sinh thái tương tự cũng mong muốn sử dụng WebGPU. Hỗ trợ cho WebGPU đang được tiến hành hoặc đã hoàn tất trong nhiều thư viện JavaScript WebGL phổ biến và trong một số trường hợp, việc tận dụng các lợi ích của WebGPU có thể đơn giản như việc thay đổi một cờ!

Babylon.js, Build 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js và Unity.
Các khung, ứng dụng và thư viện có các cổng WebGPU đã kết thúc hoặc đang hoạt động.

bản phát hành đầu tiên trong Chrome 113 này chỉ là sự khởi đầu. Mặc dù bản phát hành đầu tiên của chúng tôi là dành cho Windows, ChromeOS và MacOS, nhưng chúng tôi dự định sẽ cung cấp WebGPU cho các nền tảng còn lại (như Android và Linux) trong tương lai gần.

Và không chỉ nhóm Chrome đang nỗ lực làm việc nhằm khởi chạy WebGPU. Quá trình triển khai cũng đang diễn ra trên Firefox và WebKit.

Ngoài ra, các tính năng mới đang được thiết kế tại W3C có thể được công bố khi có sẵn trong phần cứng. Ví dụ: Trong Chrome, chúng tôi dự định sẽ sớm hỗ trợ các số có dấu phẩy động 16 bit trong chương trình đổ bónglớp hướng dẫn DP4a để cải thiện hiệu suất của công nghệ học máy hơn nữa.

WebGPU là một API chuyên sâu mở ra hiệu suất đáng kinh ngạc nếu bạn đầu tư vào API đó. Hôm nay, chúng ta chỉ có thể nói chung về các lợi ích của WebGPU, nhưng nếu bạn muốn bắt đầu sử dụng WebGPU, hãy tham khảo Lớp học lập trình giới thiệu của chúng tôi, ứng dụng WebGPU đầu tiên của bạn. Trong lớp học lập trình này, bạn sẽ xây dựng một phiên bản GPU của trò chơi Conway phiên bản cũ. Trong lớp học lập trình này, bạn sẽ được hướng dẫn từng bước để có thể thử ngay cả khi đây là lần đầu tiên bạn phát triển GPU.

Bạn cũng nên tham khảo các mẫu WebGPU để tìm hiểu về API. Các mô hình này đa dạng từ " tam giác xin chào" truyền thống đến các quy trình tính toán và kết xuất hình ảnh hoàn chỉnh hơn, thể hiện nhiều kỹ thuật. Cuối cùng, hãy tham khảo các tài nguyên khác của chúng tôi.