TensorFlow.js hoạt động trong trình duyệt và Node.js và trong cả hai nền tảng đều có nhiều cấu hình có sẵn khác nhau. Mỗi nền tảng có một tập hợp các cân nhắc riêng sẽ ảnh hưởng đến cách phát triển ứng dụng.
Trong trình duyệt, TensorFlow.js hỗ trợ các thiết bị di động cũng như thiết bị máy tính để bàn. Mỗi thiết bị có một bộ ràng buộc cụ thể, chẳng hạn như các API WebGL có sẵn, được xác định và định cấu hình tự động cho bạn.
Trong Node.js, TensorFlow.js hỗ trợ liên kết trực tiếp với API TensorFlow hoặc chạy với việc triển khai CPU vanilla chậm hơn.
Môi trường
Khi chương trình TensorFlow.js được thực thi, cấu hình cụ thể được gọi là môi trường. Môi trường bao gồm một chương trình phụ trợ toàn cầu duy nhất cũng như một bộ cờ kiểm soát các tính năng chi tiết của TensorFlow.js.
Phụ trợ
TensorFlow.js hỗ trợ nhiều chương trình phụ trợ khác nhau triển khai các phép toán và lưu trữ tensor. Tại bất kỳ thời điểm nào, chỉ có một chương trình phụ trợ được kích hoạt. Hầu hết thời gian, TensorFlow.js sẽ tự động chọn phần phụ trợ tốt nhất cho bạn dựa trên môi trường hiện tại. Tuy nhiên, đôi khi điều quan trọng là phải biết phần phụ trợ nào đang được sử dụng và cách chuyển đổi nó.
Để tìm chương trình phụ trợ nào bạn đang sử dụng:
console.log(tf.getBackend());
Nếu bạn muốn thay đổi phần phụ trợ theo cách thủ công:
tf.setBackend('cpu');
console.log(tf.getBackend());
Phần phụ trợ WebGL
Phần phụ trợ WebGL, 'webgl', hiện là phần phụ trợ mạnh mẽ nhất cho trình duyệt. Phần phụ trợ này nhanh hơn tới 100 lần so với phần phụ trợ CPU vanilla. Các tensor được lưu trữ dưới dạng kết cấu WebGL và các phép toán được triển khai trong trình đổ bóng WebGL. Dưới đây là một số điều hữu ích cần biết khi sử dụng chương trình phụ trợ này: \
Tránh chặn luồng UI
Khi một thao tác được gọi, chẳng hạn như tf.matMul(a, b), tf.Tensor thu được sẽ được trả về một cách đồng bộ, tuy nhiên, việc tính toán phép nhân ma trận có thể chưa thực sự sẵn sàng. Điều này có nghĩa là tf.Tensor được trả về chỉ là một phần xử lý tính toán. Khi bạn gọi x.data()
hoặc x.array()
, các giá trị sẽ phân giải khi quá trình tính toán thực sự hoàn tất. Điều này rất quan trọng khi sử dụng các phương thức x.data()
và x.array()
không đồng bộ thay vì các phương thức đồng bộ x.dataSync()
và x.arraySync()
để tránh chặn luồng giao diện người dùng trong khi quá trình tính toán hoàn tất.
Quản lý bộ nhớ
Một lưu ý khi sử dụng phần phụ trợ WebGL là cần phải quản lý bộ nhớ rõ ràng. WebGLTextures, nơi lưu trữ cuối cùng dữ liệu Tensor, không phải là rác tự động được trình duyệt thu thập.
Để hủy bộ nhớ của tf.Tensor
, bạn có thể sử dụng phương thức dispose()
:
const a = tf.tensor([[1, 2], [3, 4]]);
a.dispose();
Việc xâu chuỗi nhiều hoạt động lại với nhau trong một ứng dụng là điều rất phổ biến. Việc giữ tham chiếu đến tất cả các biến trung gian để loại bỏ chúng có thể làm giảm khả năng đọc mã. Để giải quyết vấn đề này, TensorFlow.js cung cấp một phương thức tf.tidy()
để dọn sạch tất cả tf.Tensor
không được hàm trả về sau khi thực thi nó, tương tự như cách các biến cục bộ được dọn sạch khi một hàm được thực thi:
const a = tf.tensor([[1, 2], [3, 4]]);
const y = tf.tidy(() => {
const result = a.square().log().neg();
return result;
});
Độ chính xác
Trên thiết bị di động, WebGL có thể chỉ hỗ trợ họa tiết dấu phẩy động 16 bit. Tuy nhiên, hầu hết các mô hình học máy đều được đào tạo với trọng số và kích hoạt dấu phẩy động 32 bit. Điều này có thể gây ra sự cố về độ chính xác khi chuyển mô hình cho thiết bị di động vì số thực 16 bit chỉ có thể biểu thị các số trong phạm vi [0.000000059605, 65504]
. Điều này có nghĩa là bạn nên cẩn thận để trọng số và kích hoạt trong mô hình của bạn không vượt quá phạm vi này. Để kiểm tra xem thiết bị có hỗ trợ họa tiết 32 bit hay không, hãy kiểm tra giá trị của tf.ENV.getBool('WEBGL_RENDER_FLOAT32_CAPABLE')
, nếu giá trị này sai thì thiết bị chỉ hỗ trợ họa tiết dấu phẩy động 16 bit. Bạn có thể sử dụng tf.ENV.getBool('WEBGL_RENDER_FLOAT32_ENABLED')
để kiểm tra xem TensorFlow.js hiện có đang sử dụng kết cấu 32 bit hay không.
Biên soạn Shader và tải lên kết cấu
TensorFlow.js thực thi các hoạt động trên GPU bằng cách chạy các chương trình đổ bóng WebGL. Các shader này được tập hợp và biên dịch một cách lười biếng khi người dùng yêu cầu thực hiện một thao tác. Quá trình biên dịch trình đổ bóng diễn ra trên CPU trên luồng chính và có thể bị chậm. TensorFlow.js sẽ tự động lưu vào bộ nhớ đệm các trình đổ bóng đã biên dịch, thực hiện lệnh gọi thứ hai đến cùng một thao tác với các tensor đầu vào và đầu ra có cùng hình dạng nhanh hơn nhiều. Thông thường, các ứng dụng TensorFlow.js sẽ sử dụng cùng một thao tác nhiều lần trong vòng đời của ứng dụng, do đó, lần thứ hai thông qua mô hình học máy sẽ nhanh hơn nhiều.
TensorFlow.js cũng lưu trữ dữ liệu tf.Tensor dưới dạng WebGLTextures. Khi tf.Tensor
được tạo, chúng tôi không tải dữ liệu lên GPU ngay lập tức mà giữ dữ liệu trên CPU cho đến khi tf.Tensor
được sử dụng trong một hoạt động. Nếu tf.Tensor
được sử dụng lần thứ hai, dữ liệu đã có trên GPU nên không mất phí tải lên. Trong một mô hình học máy điển hình, điều này có nghĩa là các trọng số được tải lên trong lần dự đoán đầu tiên thông qua mô hình và lần thứ hai truyền qua mô hình sẽ nhanh hơn nhiều.
Nếu quan tâm đến hiệu suất của dự đoán đầu tiên thông qua mô hình hoặc mã TensorFlow.js của mình, bạn nên khởi động mô hình bằng cách chuyển một Tensor đầu vào có cùng hình dạng trước khi sử dụng dữ liệu thực.
Ví dụ:
const model = await tf.loadLayersModel(modelUrl);
// Warmup the model before using real data.
const warmupResult = model.predict(tf.zeros(inputShape));
warmupResult.dataSync();
warmupResult.dispose();
// The second predict() will be much faster
const result = model.predict(userData);
Phần phụ trợ TensorFlow của Node.js
Trong phần phụ trợ của TensorFlow Node.js, 'nút', API TensorFlow C được sử dụng để tăng tốc các hoạt động. Điều này sẽ sử dụng khả năng tăng tốc phần cứng có sẵn của máy, như CUDA, nếu có.
Trong phần phụ trợ này, giống như phần phụ trợ WebGL, các thao tác trả về tf.Tensor
một cách đồng bộ. Tuy nhiên, không giống như phần phụ trợ WebGL, thao tác được hoàn thành trước khi bạn lấy lại tenxơ. Điều này có nghĩa là lệnh gọi tới tf.matMul(a, b)
sẽ chặn luồng giao diện người dùng.
Vì lý do này, nếu bạn định sử dụng điều này trong một ứng dụng sản xuất, bạn nên chạy TensorFlow.js trong các luồng công việc để không chặn luồng chính.
Để biết thêm thông tin về Node.js, hãy xem hướng dẫn này.
Phần phụ trợ WASM
TensorFlow.js cung cấp phần phụ trợ WebAssembly ( wasm
), cung cấp khả năng tăng tốc CPU và có thể được sử dụng thay thế cho phần phụ trợ CPU JavaScript cơ bản ( cpu
) và phần phụ trợ tăng tốc WebGL ( webgl
). Để sử dụng nó:
// Set the backend to WASM and wait for the module to be ready.
tf.setBackend('wasm');
tf.ready().then(() => {...});
Nếu máy chủ của bạn đang phân phối tệp .wasm
trên một đường dẫn khác hoặc tên khác, hãy sử dụng setWasmPath
trước khi bạn khởi tạo chương trình phụ trợ. Xem phần "Sử dụng Bundlers" trong README để biết thêm thông tin:
import {setWasmPath} from '@tensorflow/tfjs-backend-wasm';
setWasmPath(yourCustomPath);
tf.setBackend('wasm');
tf.ready().then(() => {...});
Tại sao lại là WASM?
WASM được giới thiệu vào năm 2015 dưới dạng định dạng nhị phân dựa trên web mới, cung cấp các chương trình được viết bằng JavaScript, C, C++, v.v. làm mục tiêu biên dịch để chạy trên web. WASM đã được Chrome, Safari, Firefox và Edge hỗ trợ kể từ năm 2017 và được 90% thiết bị trên toàn thế giới hỗ trợ.
Hiệu suất
Phần phụ trợ WASM tận dụng thư viện XNNPACK để triển khai tối ưu hóa các toán tử mạng thần kinh.
So với JavaScript : Các tệp nhị phân WASM thường nhanh hơn nhiều so với các gói JavaScript để trình duyệt tải, phân tích cú pháp và thực thi. JavaScript được nhập động và thu thập rác, điều này có thể gây ra tình trạng chậm trong thời gian chạy.
So với WebGL : WebGL nhanh hơn WASM đối với hầu hết các mô hình, nhưng đối với các mô hình nhỏ, WASM có thể hoạt động tốt hơn WebGL do chi phí cố định khi thực thi trình tạo bóng WebGL. Phần “Khi nào tôi nên sử dụng WASM” bên dưới thảo luận về phương pháp phỏng đoán để đưa ra quyết định này.
Tính di động và ổn định
WASM có số học float 32-bit di động, mang lại độ chính xác tương đương trên tất cả các thiết bị. Mặt khác, WebGL dành riêng cho phần cứng và các thiết bị khác nhau có thể có độ chính xác khác nhau (ví dụ: dự phòng cho các float 16 bit trên thiết bị iOS).
Giống như WebGL, WASM được hỗ trợ chính thức bởi tất cả các trình duyệt chính. Không giống như WebGL, WASM có thể chạy trong Node.js và được sử dụng phía máy chủ mà không cần biên dịch thư viện gốc.
Khi nào tôi nên sử dụng WASM?
Kích thước mô hình và nhu cầu tính toán
Nói chung, WASM là một lựa chọn tốt khi các model nhỏ hơn hoặc bạn quan tâm đến các thiết bị cấp thấp hơn thiếu hỗ trợ WebGL (tiện ích mở rộng OES_texture_float
) hoặc có GPU kém mạnh hơn. Biểu đồ bên dưới hiển thị thời gian suy luận (kể từ TensorFlow.js 1.5.2) trong Chrome trên MacBook Pro 2018 cho 5 kiểu máy được hỗ trợ chính thức của chúng tôi trên các chương trình phụ trợ WebGL, WASM và CPU:
Mô hình nhỏ hơn
Người mẫu | WebGL | WASM | CPU | Ký ức |
---|---|---|---|---|
BlazeFace | 22,5 mili giây | 15,6 mili giây | 315,2 mili giây | 0,4 MB |
FaceMesh | 19,3 mili giây | 19,2 mili giây | 335 mili giây | 2,8 MB |
mô hình lớn hơn
Người mẫu | WebGL | WASM | CPU | Ký ức |
---|---|---|---|---|
Tư thếNet | 42,5 mili giây | 173,9 mili giây | 1514,7 mili giây | 4,5 MB |
BodyPix | 77 mili giây | 188,4 mili giây | 2683 mili giây | 4,6 MB |
MobileNet v2 | 37 mili giây | 94 mili giây | 923,6 mili giây | 13MB |
Bảng trên cho thấy WASM nhanh hơn 10-30 lần so với chương trình phụ trợ CPU JS đơn giản trên nhiều mô hình và cạnh tranh với WebGL dành cho các mô hình nhỏ hơn như BlazeFace , nhẹ (400KB), nhưng vẫn có số lượng hoạt động khá (~140). Do các chương trình WebGL có chi phí cố định cho mỗi lần thực thi hoạt động, điều này giải thích tại sao các mô hình như BlazeFace lại nhanh hơn trên WASM.
Những kết quả này sẽ khác nhau tùy thuộc vào thiết bị của bạn. Cách tốt nhất để xác định xem WASM có phù hợp với ứng dụng của bạn hay không là thử nghiệm nó trên các chương trình phụ trợ khác nhau của chúng tôi.
Suy luận vs đào tạo
Để giải quyết trường hợp sử dụng chính là triển khai các mô hình được đào tạo trước, quá trình phát triển phụ trợ WASM sẽ ưu tiên suy luận hơn là hỗ trợ đào tạo . Xem danh sách cập nhật các hoạt động được hỗ trợ trong WASM và cho chúng tôi biết nếu mô hình của bạn có hoạt động không được hỗ trợ. Đối với các mô hình đào tạo, chúng tôi khuyên bạn nên sử dụng chương trình phụ trợ Node (TensorFlow C++) hoặc chương trình phụ trợ WebGL.
Chương trình phụ trợ CPU
Phần phụ trợ của CPU, 'cpu', là phần phụ trợ có hiệu suất kém nhất, tuy nhiên nó lại đơn giản nhất. Tất cả các hoạt động đều được triển khai bằng JavaScript nguyên bản, khiến chúng ít có khả năng song song hóa hơn. Họ cũng chặn chuỗi giao diện người dùng.
Phần phụ trợ này có thể rất hữu ích cho việc thử nghiệm hoặc trên các thiết bị không có WebGL.
Cờ
TensorFlow.js có một bộ cờ môi trường được tự động đánh giá và xác định cấu hình tốt nhất trong nền tảng hiện tại. Các cờ này chủ yếu là cờ nội bộ, nhưng một số cờ toàn cầu có thể được kiểm soát bằng API công khai.
-
tf.enableProdMode():
bật chế độ sản xuất, chế độ này sẽ loại bỏ xác thực mô hình, kiểm tra NaN và các kiểm tra tính chính xác khác để cải thiện hiệu suất. -
tf.enableDebugMode()
: bật chế độ gỡ lỗi, chế độ này sẽ ghi vào bảng điều khiển mọi thao tác được thực thi, cũng như thông tin hiệu suất thời gian chạy như dung lượng bộ nhớ và tổng thời gian thực thi kernel. Lưu ý rằng điều này sẽ làm chậm ứng dụng của bạn rất nhiều, không sử dụng điều này trong sản xuất.