Đại biểu tăng tốc GPU cho iOS

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Sử dụng đơn vị xử lý đồ họa (GPU) để chạy các mô hình máy học (ML) của bạn 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ợ ML của bạn. Trên thiết bị iOS, bạn có thể cho phép sử dụng tính năng thực thi được tăng tốc GPU đối với các mô hình của mình bằng cách sử dụng một đại diện . Các đại biểu đóng vai trò là trình điều khiển phần cứng cho TensorFlow Lite, cho phép bạn chạy mã mô hình của mình trên bộ xử lý GPU.

Trang này mô tả cách bật tăng tốc GPU cho các mô hình TensorFlow Lite trong ứng dụng iOS. Để biết thêm thông tin về cách sử dụng GPU ủy quyền cho TensorFlow Lite, bao gồm các phương pháp hay nhất và kỹ thuật nâng cao, hãy xem trang ủy quyền GPU .

Sử dụng GPU với API phiên dịch

API thông dịch TensorFlow Lite cung cấp một tập hợp các API mục đích chung để xây dựng ứng dụng học máy. Các hướng dẫn sau hướng dẫn bạn thêm hỗ trợ GPU vào ứng dụng iOS. Hướng dẫn này giả định rằng bạn đã có một ứng dụng iOS có thể thực thi thành công mô hình ML với TensorFlow Lite.

Sửa đổi Podfile để bao gồm hỗ trợ GPU

Bắt đầu với bản phát hành TensorFlow Lite 2.3.0, đại biểu GPU bị loại trừ khỏi nhóm để giảm kích thước nhị phân. Bạn có thể bao gồm chúng bằng cách chỉ định một subspec cho nhóm TensorFlowLiteSwift :

pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',

HOẶC

pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']

Bạn cũng có thể sử dụng TensorFlowLiteObjC hoặc TensorFlowLiteC nếu bạn muốn sử dụng Objective-C, có sẵn cho các phiên bản 2.4.0 trở lên hoặc C API.

Khởi tạo và sử dụng đại biểu GPU

Bạn có thể sử dụng đại biểu GPU với API thông dịch TensorFlow Lite với một số ngôn ngữ lập trình. Swift và Objective-C được khuyến nghị, nhưng bạn cũng có thể sử dụng C ++ và C. Bắt buộc phải sử dụng C nếu bạn đang sử dụng phiên bản TensorFlow Lite cũ hơn 2.4. Các ví dụ mã sau đây phác thảo cách sử dụng ủy quyền với mỗi ngôn ngữ này.

Nhanh

import TensorFlowLite

// Load model ...

// Initialize TensorFlow Lite interpreter with the GPU delegate.
let delegate = MetalDelegate()
if let interpreter = try Interpreter(modelPath: modelPath,
                                      delegates: [delegate]) {
  // Run inference ...
}
      

Objective-C

// Import module when using CocoaPods with module support
@import TFLTensorFlowLite;

// Or import following headers manually
#import "tensorflow/lite/objc/apis/TFLMetalDelegate.h"
#import "tensorflow/lite/objc/apis/TFLTensorFlowLite.h"

// Initialize GPU delegate
TFLMetalDelegate* metalDelegate = [[TFLMetalDelegate alloc] init];

// Initialize interpreter with model path and GPU delegate
TFLInterpreterOptions* options = [[TFLInterpreterOptions alloc] init];
NSError* error = nil;
TFLInterpreter* interpreter = [[TFLInterpreter alloc]
                                initWithModelPath:modelPath
                                          options:options
                                        delegates:@[ metalDelegate ]
                                            error:&error];
if (error != nil) { /* Error handling... */ }

if (![interpreter allocateTensorsWithError:&error]) { /* Error handling... */ }
if (error != nil) { /* Error handling... */ }

// Run inference ...
      

C ++

// Set up interpreter.
auto model = FlatBufferModel::BuildFromFile(model_path);
if (!model) return false;
tflite::ops::builtin::BuiltinOpResolver op_resolver;
std::unique_ptr<Interpreter> interpreter;
InterpreterBuilder(*model, op_resolver)(&interpreter);

// Prepare GPU delegate.
auto* delegate = TFLGpuDelegateCreate(/*default options=*/nullptr);
if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;

// Run inference.
WriteToInputTensor(interpreter->typed_input_tensor<float>(0));
if (interpreter->Invoke() != kTfLiteOk) return false;
ReadFromOutputTensor(interpreter->typed_output_tensor<float>(0));

// Clean up.
TFLGpuDelegateDelete(delegate);
      

C (trước 2.4.0)

#include "tensorflow/lite/c/c_api.h"
#include "tensorflow/lite/delegates/gpu/metal_delegate.h"

// Initialize model
TfLiteModel* model = TfLiteModelCreateFromFile(model_path);

// Initialize interpreter with GPU delegate
TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
TfLiteDelegate* delegate = TFLGPUDelegateCreate(nil);  // default config
TfLiteInterpreterOptionsAddDelegate(options, metal_delegate);
TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
TfLiteInterpreterOptionsDelete(options);

TfLiteInterpreterAllocateTensors(interpreter);

NSMutableData *input_data = [NSMutableData dataWithLength:input_size * sizeof(float)];
NSMutableData *output_data = [NSMutableData dataWithLength:output_size * sizeof(float)];
TfLiteTensor* input = TfLiteInterpreterGetInputTensor(interpreter, 0);
const TfLiteTensor* output = TfLiteInterpreterGetOutputTensor(interpreter, 0);

// Run inference
TfLiteTensorCopyFromBuffer(input, inputData.bytes, inputData.length);
TfLiteInterpreterInvoke(interpreter);
TfLiteTensorCopyToBuffer(output, outputData.mutableBytes, outputData.length);

// Clean up
TfLiteInterpreterDelete(interpreter);
TFLGpuDelegateDelete(metal_delegate);
TfLiteModelDelete(model);
      

Ghi chú sử dụng ngôn ngữ API GPU

  • Các phiên bản TensorFlow Lite trước 2.4.0 chỉ có thể sử dụng API C cho Objective-C.
  • API C ++ chỉ khả dụng khi bạn đang sử dụng bazel hoặc tự xây dựng TensorFlow Lite. Không thể sử dụng API C ++ với CocoaPods.
  • Khi sử dụng TensorFlow Lite với đại biểu GPU với C ++, hãy lấy đại biểu GPU qua hàm TFLGpuDelegateCreate() và sau đó chuyển nó đến Interpreter::ModifyGraphWithDelegate() , thay vì gọi Interpreter::AllocateTensors() .

Xây dựng và thử nghiệm với chế độ phát hành

Thay đổi sang bản phát hành có cài đặt bộ tăng tốc API Metal thích hợp để có được hiệu suất tốt hơn và để thử nghiệm lần cuối. Phần này giải thích cách bật một bản phát hành và cài đặt cấu hình để tăng tốc Metal.

Để thay đổi sang bản phát hành:

  1. Chỉnh sửa cài đặt bản dựng bằng cách chọn Sản phẩm> Lược đồ> Chỉnh sửa Lược đồ ... và sau đó chọn Chạy .
  2. Trên tab Thông tin , thay đổi Cấu hình bản dựng thành Bản phát hành và bỏ chọn Gỡ lỗi thực thi .thiết lập bản phát hành
  3. Nhấp vào tab Tùy chọn và thay đổi tính năng Chụp khung hình GPU thành hiệu hóa và Xác thực API kim loại thành hiệu hóa.
    thiết lập các tùy chọn kim loại
  4. Đảm bảo chọn các bản dựng chỉ Phát hành trên kiến ​​trúc 64-bit. Trong Project điều hướng> tflite_camera_example> PROJECT> your_project_name> Build Settings, đặt Build Active Architecture Only> Release thành Yes .thiết lập các tùy chọn phát hành

Hỗ trợ GPU nâng cao

Phần này bao gồm các cách sử dụng nâng cao của đại biểu GPU cho iOS, bao gồm các tùy chọn đại biểu, bộ đệm đầu vào và đầu ra và sử dụng các mô hình lượng tử hóa.

Tùy chọn ủy quyền cho iOS

Hàm tạo cho đại biểu GPU chấp nhận một struct tùy chọn trong API Swift, API Objective-CAPI C. nullptr (API C) hoặc không có gì (Objective-C và Swift API) vào trình khởi tạo sẽ đặt các tùy chọn mặc định (được giải thích trong ví dụ về Cách sử dụng cơ bản ở trên).

Nhanh

// THIS:
var options = MetalDelegate.Options()
options.isPrecisionLossAllowed = false
options.waitType = .passive
options.isQuantizationEnabled = true
let delegate = MetalDelegate(options: options)

// IS THE SAME AS THIS:
let delegate = MetalDelegate()
      

Objective-C

// THIS:
TFLMetalDelegateOptions* options = [[TFLMetalDelegateOptions alloc] init];
options.precisionLossAllowed = false;
options.waitType = TFLMetalDelegateThreadWaitTypePassive;
options.quantizationEnabled = true;

TFLMetalDelegate* delegate = [[TFLMetalDelegate alloc] initWithOptions:options];

// IS THE SAME AS THIS:
TFLMetalDelegate* delegate = [[TFLMetalDelegate alloc] init];
      

C

// THIS:
const TFLGpuDelegateOptions options = {
  .allow_precision_loss = false,
  .wait_type = TFLGpuDelegateWaitType::TFLGpuDelegateWaitTypePassive,
  .enable_quantization = true,
};

TfLiteDelegate* delegate = TFLGpuDelegateCreate(options);

// IS THE SAME AS THIS:
TfLiteDelegate* delegate = TFLGpuDelegateCreate(nullptr);
      

Bộ đệm đầu vào / đầu ra sử dụng C ++ API

Tính toán trên GPU yêu cầu dữ liệu có sẵn cho GPU. Yêu cầu này thường có nghĩa là bạn phải thực hiện sao chép bộ nhớ. Bạn nên tránh để dữ liệu của mình vượt qua ranh giới bộ nhớ CPU / GPU nếu có thể, vì điều này có thể chiếm một lượng thời gian đáng kể. Thông thường, việc băng qua đường như vậy là không thể tránh khỏi, nhưng trong một số trường hợp đặc biệt, có thể bỏ qua cái này hoặc cái kia.

Nếu đầu vào của mạng là hình ảnh đã được tải trong bộ nhớ GPU (ví dụ: kết cấu GPU chứa nguồn cấp dữ liệu máy ảnh) thì nó có thể ở trong bộ nhớ GPU mà không cần nhập vào bộ nhớ CPU. Tương tự, nếu đầu ra của mạng ở dạng hình ảnh có thể kết xuất, chẳng hạn như thao tác chuyển kiểu hình ảnh , bạn có thể hiển thị trực tiếp kết quả trên màn hình.

Để đạt được hiệu suất tốt nhất, TensorFlow Lite giúp người dùng có thể đọc và ghi trực tiếp vào bộ đệm phần cứng TensorFlow và bỏ qua các bản sao bộ nhớ có thể tránh được.

Giả sử đầu vào hình ảnh nằm trong bộ nhớ GPU, trước tiên bạn phải chuyển đổi nó thành đối tượng MTLBuffer cho Metal. Bạn có thể liên kết TfLiteTensor với MTLBuffer do người dùng chuẩn bị bằng hàm MTLBuffer TFLGpuDelegateBindMetalBufferToTensor() . Lưu ý rằng hàm này phải được gọi sau Interpreter::ModifyGraphWithDelegate() . Ngoài ra, theo mặc định, đầu ra suy luận được sao chép từ bộ nhớ GPU sang bộ nhớ CPU. Bạn có thể tắt hành vi này bằng cách gọi Interpreter::SetAllowBufferHandleOutput(true) trong quá trình khởi tạo.

C ++

#include "tensorflow/lite/delegates/gpu/metal_delegate.h"
#include "tensorflow/lite/delegates/gpu/metal_delegate_internal.h"

// ...

// Prepare GPU delegate.
auto* delegate = TFLGpuDelegateCreate(nullptr);

if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;

interpreter->SetAllowBufferHandleOutput(true);  // disable default gpu->cpu copy
if (!TFLGpuDelegateBindMetalBufferToTensor(
        delegate, interpreter->inputs()[0], user_provided_input_buffer)) {
  return false;
}
if (!TFLGpuDelegateBindMetalBufferToTensor(
        delegate, interpreter->outputs()[0], user_provided_output_buffer)) {
  return false;
}

// Run inference.
if (interpreter->Invoke() != kTfLiteOk) return false;
      

Khi hành vi mặc định bị tắt, việc sao chép đầu ra suy luận từ bộ nhớ GPU sang bộ nhớ CPU yêu cầu một lệnh gọi rõ ràng tới Interpreter::EnsureTensorDataIsReadable() cho mỗi tensor đầu ra. Cách tiếp cận này cũng hoạt động đối với các mô hình lượng tử hóa, nhưng bạn vẫn cần sử dụng bộ đệm có kích thước float32 với dữ liệu float32 , vì bộ đệm được liên kết với bộ đệm đã được lượng tử hóa bên trong.

Các mô hình lượng tử hóa

Các thư viện đại biểu GPU iOS hỗ trợ các mô hình lượng tử hóa theo mặc định . Bạn không cần phải thực hiện bất kỳ thay đổi mã nào để sử dụng các mô hình lượng tử hóa với GPU ủy quyền. Phần sau giải thích cách tắt hỗ trợ lượng tử hóa cho mục đích thử nghiệm hoặc thử nghiệm.

Tắt hỗ trợ mô hình lượng tử hóa

Đoạn mã sau đây cho thấy cách tắt hỗ trợ cho các mô hình lượng tử hóa.

Nhanh

    var options = MetalDelegate.Options()
    options.isQuantizationEnabled = false
    let delegate = MetalDelegate(options: options)
      

Objective-C

    TFLMetalDelegateOptions* options = [[TFLMetalDelegateOptions alloc] init];
    options.quantizationEnabled = false;
      

C

    TFLGpuDelegateOptions options = TFLGpuDelegateOptionsDefault();
    options.enable_quantization = false;

    TfLiteDelegate* delegate = TFLGpuDelegateCreate(options);
      

Để biết thêm thông tin về cách chạy các mô hình lượng tử hóa với khả năng tăng tốc GPU, hãy xem tổng quan về GPU dành cho đại biểu .