Cải tiến WebAssembly và WebGPU để giúp web AI hoạt động nhanh hơn, phần 1

Tìm hiểu cách các tính năng nâng cao của WebAssembly và WebGPU cải thiện hiệu suất học máy trên web.

Austin Eng
Austin Eng
Deepti Gandluri
Deepti Gandluri
François Beaufort
François Beaufort

Suy luận của AI trên web

Hẳn chúng ta đều đã nghe câu chuyện: AI đang thay đổi thế giới của chúng ta. Web cũng không phải là ngoại lệ.

Năm nay, Chrome đã bổ sung các tính năng AI tạo sinh, trong đó có tính năng tạo giao diện tuỳ chỉnh và giúp bạn viết bản nháp văn bản đầu tiên. Nhưng AI còn làm được nhiều hơn thế; AI có thể làm phong phú các ứng dụng web.

Các trang web có thể nhúng các thành phần thông minh để hỗ trợ thị giác, như chọn khuôn mặt hoặc nhận dạng cử chỉ, để phân loại âm thanh hoặc phát hiện ngôn ngữ. Năm ngoái, chúng ta đã thấy AI tạo sinh phát triển, trong đó có một số bản minh hoạ thực sự ấn tượng về các mô hình ngôn ngữ lớn trên web. Đừng quên xem bài viết AI thực tế trên thiết bị dành cho nhà phát triển web.

Hiện nay, chúng tôi cung cấp suy luận bằng AI trên web cho nhiều thiết bị. Quá trình xử lý bằng AI có thể diễn ra ngay trên chính trang web đó bằng cách tận dụng phần cứng trên thiết bị của người dùng.

Đây là biện pháp mạnh mẽ vì một số lý do:

  • Giảm chi phí: Việc chạy dự đoán trên ứng dụng của trình duyệt sẽ giúp giảm đáng kể chi phí máy chủ. Điều này có thể đặc biệt hữu ích đối với những truy vấn GenAI vì những truy vấn có thể tốn nhiều chi phí hơn so với những truy vấn thông thường.
  • Độ trễ: Đối với các ứng dụng đặc biệt nhạy cảm về độ trễ, chẳng hạn như ứng dụng âm thanh hoặc video. Việc để toàn bộ quá trình xử lý diễn ra trên thiết bị sẽ giúp giảm độ trễ.
  • Quyền riêng tư: Việc chạy ở phía máy khách cũng có khả năng mở ra một lớp ứng dụng mới yêu cầu tăng cường quyền riêng tư, trong đó dữ liệu không thể gửi đến máy chủ.

Cách các tải công việc AI chạy trên web hiện nay

Hiện nay, các nhà phát triển và nhà nghiên cứu ứng dụng xây dựng các mô hình bằng các khung, mô hình thực thi trong trình duyệt bằng một môi trường thời gian chạy như Tensorflow.js hoặc ONNX Runtime Web, còn thời gian chạy thì sử dụng API Web để thực thi.

Cuối cùng, tất cả những thời gian chạy đó sẽ chạy trên CPU thông qua JavaScript hoặc WebAssembly hoặc trên GPU thông qua WebGL hoặc WebGPU.

Sơ đồ về cách chạy các tải công việc AI trên web hiện nay

Khối lượng công việc trong công nghệ học máy

Khối lượng công việc của công nghệ học máy (ML) đẩy các tensor thông qua biểu đồ các nút tính toán. Tensor (Tensor) là các dữ liệu đầu vào và đầu ra của các nút này, thực hiện nhiều phép tính trên dữ liệu.

Việc này rất quan trọng vì:

  • Tensor là các cấu trúc dữ liệu rất lớn, thực hiện việc tính toán trên các mô hình có thể có hàng tỷ trọng số
  • Việc mở rộng quy mô và suy luận có thể dẫn đến tính song song dữ liệu. Điều này có nghĩa là các phép toán tương tự được thực hiện trên tất cả các phần tử trong tensor.
  • Công nghệ học máy không đòi hỏi độ chính xác. Có thể bạn cần một số dấu phẩy động 64 bit để đáp xuống mặt trăng, nhưng có thể bạn chỉ cần một biển số gồm 8 bit trở xuống để nhận dạng khuôn mặt.

May mắn là các nhà thiết kế chip đã thêm các tính năng giúp cho các mô hình chạy nhanh hơn, thú vị hơn và thậm chí giúp bạn chạy được các mô hình đó.

Trong khi đó, ở nhóm WebAssembly và WebGPU, chúng tôi đang nỗ lực để giới thiệu những tính năng mới đó cho nhà phát triển web. Nếu là nhà phát triển ứng dụng web, bạn sẽ ít có khả năng thường xuyên sử dụng các dữ liệu gốc cấp thấp này. Chúng tôi dự kiến rằng chuỗi công cụ hoặc khung bạn đang sử dụng sẽ hỗ trợ các tính năng và tiện ích mới, do đó bạn có thể hưởng lợi mà không cần thay đổi cơ sở hạ tầng của mình. Nhưng nếu bạn thực sự muốn tinh chỉnh ứng dụng theo cách thủ công để có hiệu suất thì các tính năng này có liên quan đến công việc của bạn.

WebAssembly

WebAssembly (Wasm) là một định dạng mã byte nhỏ gọn, hiệu quả mà thời gian chạy có thể hiểu và thực thi được. API này được thiết kế để tận dụng các tính năng phần cứng cơ bản để có thể thực thi ở tốc độ gần như gốc. Mã được xác thực và thực thi trong một môi trường hộp cát, đảm bảo an toàn cho bộ nhớ.

Thông tin mô-đun Wasm được biểu thị bằng mã hoá nhị phân dày đặc. So với định dạng dựa trên văn bản, điều đó nghĩa là giải mã nhanh hơn, tải nhanh hơn và giảm mức sử dụng bộ nhớ. Công cụ này linh động vì nó không đưa ra giả định về kiến trúc cơ bản vốn không phổ biến đối với các kiến trúc hiện đại.

Quy cách WebAssembly mang tính lặp lại và được xử lý trong một nhóm cộng đồng W3C mở.

Định dạng nhị phân không đưa ra giả định nào về môi trường lưu trữ, vì vậy, định dạng này cũng được thiết kế để hoạt động tốt trong các mục nhúng không thuộc web.

Ứng dụng của bạn có thể được biên dịch một lần và chạy ở mọi nơi: máy tính để bàn, máy tính xách tay, điện thoại hoặc bất kỳ thiết bị nào khác có trình duyệt. Hãy xem bài viết Viết một lần, chạy ở bất cứ đâu cuối cùng đã nhận ra với WebAssembly để tìm hiểu thêm về điều này.

Hình minh hoạ một chiếc máy tính xách tay, máy tính bảng và điện thoại

Hầu hết ứng dụng chính thức chạy dự đoán bằng AI trên web đều sử dụng WebAssembly, cho cả mục đích điện toán CPU và giao tiếp với điện toán dùng cho mục đích đặc biệt. Trên các ứng dụng gốc, bạn có thể truy cập vào cả điện toán dùng cho mục đích chung và mục đích đặc biệt, vì ứng dụng có thể truy cập vào các chức năng của thiết bị.

Trên web, để đảm bảo khả năng di chuyển và bảo mật, chúng tôi đánh giá cẩn thận tập hợp dữ liệu gốc nào được hiển thị. Điều này giúp cân bằng khả năng truy cập web với hiệu suất tối đa do phần cứng mang lại.

WebAssembly là một bản tóm tắt di động của CPU, vì vậy, tất cả dự đoán Wasm đều được chạy trên CPU. Mặc dù đây không phải là lựa chọn mang lại hiệu suất cao nhất, nhưng CPU được cung cấp rộng rãi và hoạt động được trên hầu hết các tải công việc, trên hầu hết thiết bị.

Đối với các khối lượng công việc nhỏ, chẳng hạn như khối lượng công việc dạng văn bản hoặc âm thanh, GPU sẽ gây tốn kém. Gần đây, Wasm là lựa chọn đúng đắn sau một số ví dụ minh hoạ gần đây:

Bạn có thể khám phá nhiều thông tin khác trong bản minh hoạ nguồn mở, chẳng hạn như: whisper-tiny, llama.cppGemma2B chạy trong trình duyệt.

Tiếp cận toàn diện các ứng dụng

Bạn nên chọn dữ liệu gốc dựa trên mô hình học máy cụ thể, cơ sở hạ tầng ứng dụng và trải nghiệm tổng thể mà người dùng dự kiến khi sử dụng ứng dụng

Ví dụ: trong tính năng phát hiện mốc khuôn mặt của MediaPipe, suy luận CPU và suy luận GPU là tương đương (chạy trên thiết bị Apple M1), nhưng có những mô hình mà phương sai có thể cao hơn đáng kể.

Đối với tải công việc về công nghệ học máy, chúng tôi cân nhắc góc nhìn tổng quan về ứng dụng, đồng thời lắng nghe ý kiến của các tác giả khung và đối tác ứng dụng để phát triển và vận chuyển các tính năng nâng cao được yêu cầu nhiều nhất. Các sự kiện này thường được chia thành 3 danh mục:

  • Hiển thị các tiện ích CPU quan trọng đối với hiệu suất
  • Cho phép chạy các mô hình lớn hơn
  • Cho phép tương tác liền mạch với các API Web khác

Điện toán nhanh hơn

Như hiện tại, quy cách của WebAssembly chỉ bao gồm một bộ hướng dẫn nhất định mà chúng tôi hiển thị trên web. Tuy nhiên, phần cứng tiếp tục bổ sung các hướng dẫn mới hơn để tăng khoảng cách giữa hiệu suất gốc và hiệu suất của WebAssembly.

Xin lưu ý rằng các mô hình học máy không phải lúc nào cũng yêu cầu độ chính xác cao. SIMD đơn giản hơn là một đề xuất giúp giảm một số yêu cầu nghiêm ngặt, không xác định, giúp tạo mã nhanh hơn cho một số thao tác vectơ (là điểm nóng về hiệu suất). Hơn nữa, SIMD thư giãn giới thiệu sản phẩm chấm mới và các hướng dẫn FMA giúp tăng tốc khối lượng công việc hiện tại từ 1,5 đến 3 lần. Tính năng này được tích hợp trong Chrome 114.

Định dạng dấu phẩy động có độ bán chính xác sử dụng 16 bit cho IEEE FP16 thay vì 32 bit dùng cho các giá trị có độ chính xác đơn. So với các giá trị độ chính xác đơn, việc sử dụng giá trị độ bán chính xác, giảm yêu cầu bộ nhớ có một số ưu điểm, từ đó cho phép huấn luyện và triển khai mạng nơron lớn hơn, giảm băng thông bộ nhớ. Độ chính xác giảm giúp tăng tốc độ truyền dữ liệu và các phép toán.

Mô hình lớn hơn

Các con trỏ vào bộ nhớ tuyến tính Wasm được biểu thị dưới dạng số nguyên 32 bit. Điều này dẫn đến hai hệ quả: kích thước vùng nhớ khối xếp bị giới hạn ở mức 4GB (khi máy tính có dung lượng RAM vật lý lớn hơn nhiều) và mã xử lý ứng dụng nhắm đến Wasm phải tương thích với kích thước con trỏ 32 bit (có kích thước như vậy).

Đặc biệt là với các mô hình lớn như chúng tôi hiện có, việc tải các mô hình này vào WebAssembly có thể bị hạn chế. Đề xuất Memory64 giúp loại bỏ các hạn chế này để bộ nhớ tuyến tính có dung lượng lớn hơn 4 GB và phù hợp với không gian địa chỉ của các nền tảng gốc.

Chúng tôi đã triển khai toàn diện trong Chrome và dự kiến sẽ triển khai vào cuối năm nay. Hiện tại, bạn có thể chạy thử nghiệm với cờ chrome://flags/#enable-experimental-webassembly-features và gửi ý kiến phản hồi cho chúng tôi.

Khả năng tương tác web hiệu quả hơn

WebAssembly có thể là điểm truy cập cho mục đích tính toán đặc biệt trên web.

WebAssembly có thể được sử dụng để đưa ứng dụng GPU lên web. Tức là cùng một ứng dụng C++ có thể chạy trên thiết bị cũng có thể chạy trên web với một số sửa đổi nhỏ.

Emscripten (chuỗi công cụ biên dịch Wasm) đã có các mối liên kết cho WebGPU. Đó là điểm truy cập cho suy luận AI trên web, vì vậy điều quan trọng là Wasm có thể tương tác liền mạch với phần còn lại của nền tảng web. Chúng tôi đang làm việc với một số đề xuất khác nhau trong lĩnh vực này.

Tích hợp JavaScript hứa hẹn (JSPI)

Các ứng dụng C và C++ điển hình (cũng như nhiều ngôn ngữ khác) thường được viết dựa trên API đồng bộ. Điều này có nghĩa là ứng dụng sẽ ngừng thực thi cho đến khi hoàn tất thao tác. Các ứng dụng chặn như vậy thường trực quan hơn khi ghi so với các ứng dụng nhận biết không đồng bộ.

Khi các thao tác tiêu tốn nhiều tài nguyên chặn luồng chính, chúng có thể chặn I/O và người dùng có thể thấy hiện tượng giật. Không có sự không phù hợp giữa mô hình lập trình đồng bộ của các ứng dụng gốc và mô hình web không đồng bộ. Điều này đặc biệt khó khăn đối với các ứng dụng cũ, vốn sẽ tốn kém khi chuyển đổi. Emscripten cung cấp cách thực hiện việc này bằng tính năng Không đồng bộ hoá, nhưng đây không phải lúc nào cũng là lựa chọn tốt nhất – kích thước mã lớn hơn và không hiệu quả.

Ví dụ sau đây là tính toán fibonacci, sử dụng thêm hàm hứa hẹn JavaScript.

long promiseFib(long x) {
 if (x == 0)
   return 0;
 if (x == 1)
   return 1;
 return promiseAdd(promiseFib(x - 1), promiseFib(x - 2));
}
// promise an addition
EM_ASYNC_JS(long, promiseAdd, (long x, long y), {
  return Promise.resolve(x+y);
});
emcc -O3 fib.c -o b.html -s ASYNCIFY=2

Trong ví dụ này, hãy chú ý những điều sau:

  • Macro EM_ASYNC_JS tạo tất cả mã kết nối cần thiết để chúng ta có thể sử dụng bước phối hợp đầu tiên để truy cập vào kết quả hứa hẹn, giống như cách thực hiện đối với hàm thông thường.
  • Tuỳ chọn dòng lệnh đặc biệt, -s ASYNCIFY=2. Thao tác này sẽ gọi tuỳ chọn để tạo mã sử dụng coroutine để giao diện với lệnh nhập JavaScript trả về hứa hẹn.

Để biết thêm về API JavaScript, cách sử dụng và lợi ích của công cụ này, hãy đọc bài viết Giới thiệu API WebAssembly JavaScript Promise Integration trên phiên bản 8.dev. Tìm hiểu về bản dùng thử theo nguyên gốc hiện tại.

Kiểm soát bộ nhớ

Nhà phát triển có rất ít quyền kiểm soát đối với bộ nhớ Wasm; mô-đun sở hữu bộ nhớ riêng của mình. Bất kỳ API nào cần truy cập vào bộ nhớ này đều phải sao chép vào hoặc sao chép ra và mức sử dụng này thực sự có thể tăng lên. Ví dụ: một ứng dụng đồ hoạ có thể cần sao chép vào rồi sao chép ra cho mỗi khung hình.

Đề xuất Kiểm soát bộ nhớ nhằm cung cấp khả năng kiểm soát chi tiết hơn đối với bộ nhớ tuyến tính Wasm và giảm số lượng bản sao trên quy trình ứng dụng. Đề xuất này đang trong Giai đoạn 1. Chúng tôi đang tạo nguyên mẫu trong V8 (công cụ JavaScript của Chrome) để cung cấp thông tin cho sự phát triển của tiêu chuẩn này.

Quyết định phần phụ trợ phù hợp với bạn

Mặc dù CPU có mặt ở khắp mọi nơi, nhưng không phải lúc nào cũng là lựa chọn tốt nhất. Tính năng điện toán dùng cho mục đích đặc biệt trên GPU hoặc trình tăng tốc có thể mang lại hiệu suất lớn hơn, đặc biệt đối với các kiểu máy lớn hơn và trên các thiết bị cao cấp. Điều này đúng với cả ứng dụng gốc và ứng dụng web.

Phần phụ trợ mà bạn chọn phụ thuộc vào ứng dụng, khung hoặc chuỗi công cụ, cũng như các yếu tố khác ảnh hưởng đến hiệu suất. Tuy nhiên, chúng tôi vẫn đang tiếp tục đầu tư vào các đề xuất cho phép Wasm cốt lõi hoạt động tốt với phần còn lại của nền tảng web, và cụ thể hơn là với WebGPU.

Đọc tiếp Phần 2