Uỷ quyền GPU cho LiteRT

Sử dụng đơn vị xử lý đồ hoạ (GPU) để chạy các mô hình học máy (ML) có thể cải thiện đáng kể hiệu suất của mô hình và trải nghiệm người dùng của các ứng dụng hỗ trợ công nghệ học máy. LiteRT cho phép sử dụng GPU và các bộ xử lý chuyên biệt khác thông qua trình điều khiển phần cứng có tên là uỷ quyền. Cho phép sử dụng GPU với công nghệ học máy LiteRT có thể mang lại những lợi ích sau:

  • Tốc độ – GPU được xây dựng cho thông lượng cao song song tải công việc lớn. Thiết kế này làm cho chúng rất phù hợp với mạng nơron sâu, bao gồm một số lượng lớn toán tử, mỗi toán tử xử lý các tensor đầu vào có thể được xử lý song song, nên thường có độ trễ thấp hơn. Ngang bằng khả năng tốt nhất là việc chạy mô hình của bạn trên GPU có thể chạy đủ nhanh để cho phép ứng dụng theo thời gian thực mà trước đây không thể làm được.
  • Hiệu suất năng lượng – GPU thực hiện các phép tính học máy một cách rất hiệu quả và được tối ưu hoá, thường tiêu thụ ít điện năng và tạo ra ít nóng hơn so với cùng một tác vụ chạy trên CPU.

Tài liệu này cung cấp thông tin tổng quan về việc hỗ trợ GPU trong LiteRT và một số sử dụng nâng cao đối với bộ xử lý GPU. Để biết thông tin cụ thể hơn về triển khai tính năng hỗ trợ GPU trên các nền tảng cụ thể, hãy xem các hướng dẫn sau:

Hỗ trợ hoạt động GPU ML

Có một số giới hạn đối với những hoạt động học máy TensorFlow, hay hoạt động, có thể được tăng tốc bằng mã uỷ quyền GPU LiteRT. Ủy quyền hỗ trợ hoạt động sau với độ chính xác nổi 16 bit và 32 bit:

  • ADD
  • AVERAGE_POOL_2D
  • CONCATENATION
  • CONV_2D
  • DEPTHWISE_CONV_2D v1-2
  • EXP
  • FULLY_CONNECTED
  • LOGICAL_AND
  • LOGISTIC
  • LSTM v2 (Basic LSTM only)
  • MAX_POOL_2D
  • MAXIMUM
  • MINIMUM
  • MUL
  • PAD
  • PRELU
  • RELU
  • RELU6
  • RESHAPE
  • RESIZE_BILINEAR v1-3
  • SOFTMAX
  • STRIDED_SLICE
  • SUB
  • TRANSPOSE_CONV

Theo mặc định, tất cả hoạt động chỉ được hỗ trợ ở phiên bản 1. Bật tính năng lượng tử hoá support bật các phiên bản phù hợp, ví dụ: ADD phiên bản 2.

Khắc phục sự cố khi hỗ trợ GPU

Nếu một số hoạt động không được trình uỷ quyền GPU hỗ trợ, thì khung này sẽ chỉ chạy một phần biểu đồ trên GPU và phần còn lại trên CPU. Hạn mức chi phí cao cho việc đồng bộ hoá CPU/GPU, một chế độ thực thi phân tách như thế này thường dẫn đến hiệu suất chậm hơn so với khi toàn bộ mạng được chạy trên CPU. Trong trường hợp này, ứng dụng sẽ tạo cảnh báo, chẳng hạn như:

WARNING: op code #42 cannot be handled by this delegate.

Không có lệnh gọi lại cho các lỗi thuộc loại này vì đây không phải là lệnh gọi lại lỗi khi chạy. Khi kiểm thử quá trình thực thi mô hình bằng tính năng uỷ quyền GPU, bạn nên cảnh giác với những cảnh báo này. Rất nhiều cảnh báo như vậy có thể chỉ ra rằng mô hình của bạn không phù hợp nhất để sử dụng cho tính năng tăng tốc GPU và bạn có thể phải tái cấu trúc mô hình.

Mô hình mẫu

Các mô hình ví dụ sau đây được xây dựng để tận dụng tính năng tăng tốc GPU bằng LiteRT và được cung cấp để tham khảo và kiểm thử:

Tối ưu hoá cho GPU

Các kỹ thuật sau đây có thể giúp bạn đạt được hiệu suất tốt hơn khi chạy mô hình trên phần cứng GPU bằng cách sử dụng uỷ quyền GPU LiteRT:

  • Định hình lại các thao tác – Một số thao tác diễn ra nhanh trên CPU có thể có cho GPU trên thiết bị di động. Việc định hình lại hoạt động đặc biệt tốn kém khi chạy, bao gồm BATCH_TO_SPACE, SPACE_TO_BATCH, SPACE_TO_DEPTH, v.v. Bạn nên tìm hiểu kỹ việc sử dụng tính năng đổi hình dạng các toán tử và xem xét rằng những thao tác đó có thể chỉ được áp dụng để khám phá dữ liệu hoặc để lặp lại mô hình ban đầu. Việc loại bỏ những đường liên kết này có thể ảnh hưởng đáng kể cải thiện hiệu suất.

  • Kênh dữ liệu hình ảnh – Trên GPU, dữ liệu tensor được chia thành 4 kênh, và nên một phép tính trên tensor có hình dạng [B,H,W,5] thực hiện về giống trên tensor có hình [B,H,W,8], nhưng tệ hơn đáng kể so với [B,H,W,4]. Nếu phần cứng máy ảnh bạn đang sử dụng hỗ trợ khung hình ảnh trong RGBA, cấp dữ liệu đầu vào 4 kênh đó nhanh hơn đáng kể vì nó tránh bản sao bộ nhớ từ RGB 3 kênh sang RGBX 4 kênh.

  • Mô hình được tối ưu hoá cho thiết bị di động – Để có hiệu suất tốt nhất, bạn nên cân nhắc huấn luyện lại thuật toán phân loại bằng kiến trúc mạng được tối ưu hoá cho thiết bị di động. Hoạt động tối ưu hoá cho tính năng dự đoán trên thiết bị có thể làm giảm đáng kể độ trễ và tiêu thụ điện năng bằng cách tận dụng các tính năng phần cứng dành cho thiết bị di động.

Hỗ trợ GPU nâng cao

Bạn có thể sử dụng các kỹ thuật bổ sung, nâng cao với quá trình xử lý GPU để cho phép hiệu suất tốt hơn cho các mô hình của mình, kể cả việc lượng tử hoá và chuyển đổi tuần tự. Các phần sau đây sẽ mô tả chi tiết hơn về những kỹ thuật này.

Sử dụng mô hình lượng tử hoá

Phần này giải thích cách uỷ quyền GPU tăng tốc các mô hình lượng tử hoá 8 bit, bao gồm:

Để tối ưu hoá hiệu suất, hãy sử dụng các mô hình có cả đầu vào dấu phẩy động và tensor đầu ra.

Cơ chế này hoạt động như thế nào?

Vì phần phụ trợ GPU chỉ hỗ trợ thực thi dấu phẩy động, nên chúng tôi sẽ chạy hàm lượng tử hoá bằng cách cung cấp cho nó "khung hiển thị dấu phẩy động" của mô hình gốc. Vào lúc cấp cao, thì quy trình này gồm các bước sau:

  • Tensor không đổi (chẳng hạn như trọng số/độ lệch) được khử lượng tử một lần vào Bộ nhớ GPU. Thao tác này xảy ra khi bạn bật tính năng uỷ quyền cho LiteRT.

  • Đầu vào và đầu ra cho chương trình GPU, nếu được lượng tử hoá 8 bit, là khử lượng tử và lượng tử hoá (tương ứng) cho mỗi suy luận. Toán tử này được thực hiện trên CPU bằng cách sử dụng nhân tối ưu hoá của LiteRT.

  • Trình mô phỏng lượng tử hoá được chèn vào giữa các thao tác để bắt chước quy trình lượng tử hoá hành vi. Phương pháp này cần thiết cho các mô hình mà hoạt động dự kiến sẽ kích hoạt tuân theo các giới hạn đã học trong quá trình lượng tử.

Để biết thông tin về cách bật tính năng này bằng uỷ quyền GPU, hãy xem sau:

Giảm thời gian khởi chạy bằng tính năng chuyển đổi tuần tự

Tính năng uỷ quyền GPU cho phép bạn tải từ mã nhân hệ điều hành được biên dịch trước và dữ liệu mô hình được chuyển đổi tuần tự và lưu trên ổ đĩa từ các lần chạy trước. Phương pháp này giúp tránh biên dịch lại và có thể giảm tới 90% thời gian khởi động. Cải tiến này đạt được bằng cách trao đổi dung lượng ổ đĩa để tiết kiệm thời gian. Bạn có thể bật tính năng này với một vài lựa chọn cấu hình, như minh hoạ trong các mã ví dụ sau đây:

C++

    TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
    options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION;
    options.serialization_dir = kTmpDir;
    options.model_token = kModelToken;

    auto* delegate = TfLiteGpuDelegateV2Create(options);
    if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;
      

Java

    GpuDelegate delegate = new GpuDelegate(
      new GpuDelegate.Options().setSerializationParams(
        /* serializationDir= */ serializationDir,
        /* modelToken= */ modelToken));

    Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
      

Khi sử dụng tính năng chuyển đổi tuần tự, hãy đảm bảo mã của bạn tuân thủ quy tắc triển khai:

  • Lưu trữ dữ liệu chuyển đổi tuần tự trong một thư mục mà các thiết bị khác không thể truy cập của chúng tôi. Trên thiết bị Android, hãy sử dụng getCodeCacheDir() trỏ tới một vị trí riêng tư đối với ứng dụng hiện tại.
  • Mã thông báo kiểu máy phải là mã duy nhất cho thiết bị của kiểu máy cụ thể. Bạn có thể tính toán mã thông báo mô hình bằng cách tạo vân tay số từ dữ liệu của mô hình sử dụng các thư viện như farmhash::Fingerprint64.