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 để mang lại hiệu suất học máy nhanh hơn và kết xuất đồ hoạ tốt hơn.

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

WebGPU API mới giúp tăng hiệu suất đáng kể trong khối lượng công việc đồ hoạ và học máy. Bài viết này khám phá cách WebGPU cải thiện giải pháp WebGL hiện tại, đồng thời xem trước các hoạt động phát triển trong tương lai. Nhưng trước tiên, hãy cung cấp một số thông tin 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 mang đến trải nghiệm tuyệt vời trên web, từ Google Earth, video nhạc tương tác, đến bản hướng dẫn tham quan bất động sản 3D và nhiều nội dung khác. WebGL dựa trên gia đình API OpenGL được phát triển lần đầu tiên vào năm 1992. Lâu rồi không gặp! Bạn có thể hình dung 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. Các API mới này đã hỗ trợ các trường hợp sử dụng mới và đòi hỏi cao đối với việc lập trình GPU, chẳng hạn như sự bùng nổ của công nghệ học máy và những tiến bộ trong thuật toán kết xuất. WebGPU là phiên bản kế nhiệm của WebGL, mang đến những tiến bộ của lớp API hiện đại mới này cho Web.

WebGPU mở ra nhiều khả năng lập trình GPU mới trong trình duyệt. API này phản ánh tốt hơn cách hoạt động của phần cứng GPU hiện đại, đồng thời đặt nền tảng cho các tính năng GPU nâng cao hơn trong tương lai. API này đã được tích hợp vào nhóm "GPU cho web" của W3C 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. Và sau 6 năm nỗ lực, chúng tôi rất vui mừng được thông báo rằng một trong những tính năng bổ sung lớn nhất cho nền tảng Web đã ra mắt!

WebGPU hiện có trong Chrome 113 trên ChromeOS, macOS và Windows, các nền tảng khác sẽ sớm ra mắt. Cảm ơn rất nhiều những người đóng góp khác cho Chromium, đặc biệt là Intel đã giúp chúng tôi thực hiện được điều này.

Bây giờ, hãy cùng xem 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 GPU mới để kết xuất

Các tính năng của 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à nhiều tính năng khác! Thậm chí, có những khối lượng công việc trước đây chỉ có thể thực hiện trong JavaScript nhưng giờ đây có thể chuyển sang GPU.

Video sau đây cho thấy thuật toán marching cubes được dùng để tạo hình tam giác cho bề mặt của các quả bóng này. Trong 20 giây đầu tiên của video, khi thuật toán đang chạy trong JavaScript, thuật toán sẽ cố gắng bắt kịp trang chỉ chạy ở tốc độ 8 khung hình/giây, khiến ảnh động bị giật. Để duy trì hiệu suất trong JavaScript, chúng ta cần giảm mức độ chi tiết xuống rất nhiều.

Sự chênh lệch về đêm và ngày khi chúng ta di chuyển cùng một thuật toán sang 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ể khi trang hiện chạy ở tốc độ 60 khung hình/giây mượt mà và vẫn còn nhiều không gian 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 lượt tương tác với trang vẫn có khả năng phản hồi.

Bản minh hoạ metaballs

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

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

Đó là lý do tại sao bản minh hoạ sử dụng thuật toán nâng cao có tên là Chuyển đổi Fourier nhanh. Thay vì biểu diễn 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 hình sẽ sử dụng phép biến đổi Fourier để chuyển đổi từ dữ liệu phổ sang dữ liệu vị trí biểu thị độ cao của sóng.

Dự đoán ML nhanh hơn

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

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

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

Khi sử dụng WebGL theo cách này, các nhà phát triển phải thay đổi mã của họ sao cho phù hợp với kỳ vọng của một API chỉ dùng để vẽ. Cùng với việc thiếu các tính năng cơ bản (chẳng hạn như quyền truy cập vào bộ nhớ dùng chung) giữa các lần tính toán, điều này dẫn đến tình trạng trùng lặp công việc 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 và giúp loại bỏ những vấn đề này. Chương trình đổ bóng điện toán cung cấp một mô hình lập trình linh hoạt hơn, tận dụng bản chất song song khổng lồ của GPU mà không bị ràng buộc bởi cấu trúc nghiêm ngặt của các thao tác kết xuất.

Nhiều mức tăng hiệu quả trong chương trình đổ bóng điện toán WebGPU, bao gồm cả 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 chương trình đổ bóng hoạt động để mang lại hiệu quả tốt hơn. Điều này có thể mang lại những lợi ích đáng kể so với những lần sử dụng WebGL trước đó.

Ví dụ về lợi ích hiệu quả mà việc 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 thử, hình ảnh được kết xuất trong vòng chưa đến 10 giây. Vì đây là một cảng sớm, nên chúng tôi tin rằng cả WebGPU và TensorFlow.js còn có thể cải tiến nhiều hơn nữa! Hãy xem bài viết Tính năng mới của công nghệ học máy trên web trong năm 2023? Phiên Google I/O.

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

Được thiết kế dành 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 riêng cho nền tảng máy tính và thiết bị di động trong một thời gian. Tuy nhiên, chúng tôi vẫn gặp khó khăn trong việc cung cấp các tính năng này theo cách tự nhiên trên nền tảng web.

WebGPU được phát triển dựa trên kinh nghiệm của hơn một thập kỷ các nhà phát triển làm việc tuyệt vời với WebGL. Chúng tôi đã có thể nắm bắt được những vấn đề mà họ gặp phải, những nút thắt cổ chai mà họ gặp phải và những vấn đề mà họ nêu ra, đồng thời chuyển tất cả ý kiến 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ễ vỡ. Vì vậy, WebGPU giúp giảm đáng kể lượng trạng thái mà nhà phát triển cần theo dõi trong khi gửi lệnh GPU.

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

Chúng tôi cũng nhận thấy rằng thường xuyên chi phí phát sinh khi thực hiện quá nhiều lệnh gọi JavaScript là nút thắt cổ chai đối với các ứng dụng WebGL phức tạp. Do đó, API WebGPU ít giao tiếp 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 thực hiện trước việc xác thực các phần tử nặng, giữ cho vòng lặp vẽ quan trọng tinh gọn nhất có thể. Ngoài ra, chúng tôi 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 một số lượng lớn 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ể mang lại, sau đây là một bản minh hoạ khác của 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ỗi giây. Khá là cao!

Phòng tranh

Tuy nhiên, trình kết xuất WebGPU của họ cho phép một tính năng mà họ gọi là Kết xuất tổng quan 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. Điều này giúp giảm đáng kể mức hao tổn, cho phép WebGPU kết xuất các cảnh phức tạp hơn, đồng thời cho phép các ứng dụng thực hiện nhiều việc hơn với JavaScript song song.

API đồ hoạ hiện đại nổi tiếng về sự phức tạp, tính đơn giản trong giao dịch mang đến 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, tự động xử lý các chủ đề khó khăn theo truyền thống 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ễ học và dễ sử dụng. API này dựa vào 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 nổi tiếng như Promises cho các thao tác không đồng bộ. Điều này giúp giảm thiểu số lượng mã nguyên mẫu cần thiết. Bạn có thể tạo 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

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

Hệ sinh thái thư viện và khung sinh động đã được xây dựng dựa trên WebGL và cùng hệ sinh thái đó cũng háo hức muốn được sử dụng WebGPU. Hỗ trợ WebGPU đang được tiến hành hoặc đã hoàn tất trong nhiều thư viện WebGL Javascript phổ biến. 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ư thay đổi một cờ!

Babylon.js, Construct 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js và Unity.
Khung, ứng dụng và thư viện có cổng WebGPU đã hoàn tất hoặc đang diễn ra.

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

Không chỉ nhóm Chrome đang nỗ lực ra mắt WebGPU. Quá trình triển khai cũng đang diễn ra trong Firefox và WebKit.

Ngoài ra, các tính năng mới đang được thiết kế tại W3C và có thể được hiển thị 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 mở rộng giúp mang lại hiệu suất đáng kinh ngạc nếu bạn đầu tư vào API này. Hôm nay, chúng ta chỉ có thể đề cập đến những lợi ích của giải pháp này ở mức độ cao, nhưng nếu bạn muốn bắt đầu với WebGPU, hãy tìm hiểu 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 phiên bản GPU của Game of Life cổ điển của Conway. Lớp học lập trình này sẽ hướng dẫn bạn từng bước trong quy trình này để bạn có thể thử ngay cả khi đây là lần đầu tiên bạn phát triển GPU.

Mẫu WebGPU cũng là một nơi phù hợp để bạn làm quen với API này. Các trò chơi này trải dài từ " Tam giác xin chào" truyền thống cho đến quy trình kết xuất và tính toán 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.