Menggunakan unit pemrosesan grafis (GPU) untuk menjalankan model machine learning (ML) dapat meningkatkan performa model dan pengalaman pengguna aplikasi Anda secara signifikan pada aplikasi berkemampuan ML. Di perangkat iOS, Anda dapat mengaktifkan penggunaan eksekusi model yang dipercepat GPU menggunakan delegasi. Delegasi bertindak sebagai driver hardware untuk TensorFlow Lite, sehingga Anda dapat menjalankan kode model pada prosesor GPU.
Halaman ini menjelaskan cara mengaktifkan akselerasi GPU untuk model TensorFlow Lite di aplikasi iOS. Untuk mengetahui informasi selengkapnya tentang penggunaan delegasi GPU untuk TensorFlow Lite, termasuk praktik terbaik dan teknik lanjutan, lihat halaman Delegasi GPU.
Menggunakan GPU dengan Interpreter API
Interpreter API TensorFlow Lite menyediakan sekumpulan API tujuan umum untuk mem-build aplikasi machine learning. Petunjuk berikut akan memandu Anda dalam menambahkan dukungan GPU ke aplikasi iOS. Panduan ini mengasumsikan bahwa Anda sudah memiliki aplikasi iOS yang dapat menjalankan model ML dengan TensorFlow Lite.
Ubah Podfile untuk menyertakan dukungan GPU
Mulai rilis TensorFlow Lite 2.3.0, delegasi GPU dikecualikan dari pod untuk mengurangi ukuran biner. Anda dapat menyertakannya dengan menentukan subspesifikasi untuk pod TensorFlowLiteSwift
:
pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',
ATAU
pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']
Anda juga dapat menggunakan TensorFlowLiteObjC
atau TensorFlowLiteC
jika ingin menggunakan Objective-C, yang tersedia untuk versi 2.4.0 dan yang lebih tinggi, atau C API.
Melakukan inisialisasi dan menggunakan delegasi GPU
Anda dapat menggunakan delegasi GPU dengan Interpreter API TensorFlow Lite dengan sejumlah bahasa pemrograman. Swift dan Objective-C direkomendasikan, tetapi Anda juga dapat menggunakan C++ dan C. Penggunaan C diperlukan jika Anda menggunakan versi TensorFlow Lite yang lebih lama dari 2.4. Contoh kode berikut menguraikan cara menggunakan delegasi dengan setiap bahasa ini.
Swift
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 (sebelum 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);
Catatan penggunaan bahasa GPU API
- Versi TensorFlow Lite sebelum 2.4.0 hanya dapat menggunakan C API untuk Objective-C.
- C++ API hanya tersedia saat Anda menggunakan bazel atau mem-build TensorFlow Lite sendiri. C++ API tidak dapat digunakan dengan CocoaPods.
- Saat menggunakan TensorFlow Lite dengan delegasi GPU dengan C++, dapatkan delegasi GPU melalui fungsi
TFLGpuDelegateCreate()
, lalu teruskan keInterpreter::ModifyGraphWithDelegate()
, bukan memanggilInterpreter::AllocateTensors()
.
Membangun dan menguji dengan mode rilis
Beralihlah ke build rilis dengan setelan akselerator Metal API yang sesuai untuk mendapatkan performa yang lebih baik dan untuk pengujian akhir. Bagian ini menjelaskan cara mengaktifkan build rilis dan mengonfigurasi setelan untuk akselerasi Metal.
Untuk beralih ke build rilis:
- Edit setelan build dengan memilih Product > Scheme > Edit Scheme... lalu memilih Run.
- Pada tab Info, ubah Build Configuration menjadi Release, lalu hapus centang Debug executable.
- Klik tab Options, lalu ubah GPU Frame Capture ke Disabled
dan Metal API Validation ke Disabled.
- Pastikan untuk memilih Build khusus rilis pada arsitektur 64-bit. Di bagian Project navigator > tflite_camera_example > PROJECT > your_project_name > Build Settings tetapkan Build Active Architecture Only > Release ke Yes.
Dukungan GPU lanjutan
Bagian ini membahas penggunaan lanjutan delegasi GPU untuk iOS, termasuk opsi delegasi, buffer input dan output, serta penggunaan model terkuantisasi.
Opsi Delegasi untuk iOS
Konstruktor untuk delegasi GPU menerima opsi struct
di Swift API, Objective-C API, dan C API.
Meneruskan nullptr
(C API) atau tidak sama sekali (Objective-C dan Swift API) ke penginisialisasi akan menetapkan opsi default (yang dijelaskan dalam contoh Penggunaan Dasar di atas).
Swift
// 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);
Buffer Input/Output menggunakan C++ API
Komputasi di GPU mengharuskan data tersedia untuk GPU. Persyaratan ini sering kali berarti Anda harus melakukan penyalinan memori. Sebaiknya jangan data Anda melewati batas memori CPU/GPU jika memungkinkan, karena hal ini dapat memakan banyak waktu. Biasanya, persimpangan seperti itu tidak dapat dihindari, tetapi dalam beberapa kasus khusus, salah satunya dapat dihilangkan.
Jika input jaringan adalah gambar yang sudah dimuat di memori GPU (misalnya, tekstur GPU yang berisi feed kamera), input tersebut dapat tetap berada di memori GPU tanpa pernah memasuki memori CPU. Demikian pula, jika output jaringan berupa gambar yang dapat dirender, seperti operasi transfer gaya gambar, Anda dapat langsung menampilkan hasilnya di layar.
Untuk mencapai performa terbaik, TensorFlow Lite memungkinkan pengguna untuk langsung membaca dari dan menulis ke buffer hardware TensorFlow dan mengabaikan salinan memori yang dapat dihindari.
Dengan asumsi input gambar berada dalam memori GPU, Anda harus terlebih dahulu mengonversinya menjadi
objek MTLBuffer
untuk Metal. Anda dapat mengaitkan TfLiteTensor
ke
MTLBuffer
yang disiapkan pengguna dengan fungsi
TFLGpuDelegateBindMetalBufferToTensor()
. Perhatikan bahwa fungsi ini harus dipanggil setelah Interpreter::ModifyGraphWithDelegate()
. Selain itu, output inferensi,
secara default, disalin dari memori GPU ke memori CPU. Anda dapat menonaktifkan perilaku ini
dengan memanggil Interpreter::SetAllowBufferHandleOutput(true)
selama
inisialisasi.
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;
Setelah perilaku default dinonaktifkan, penyalinan output inferensi dari memori
GPU ke memori CPU memerlukan panggilan eksplisit ke
Interpreter::EnsureTensorDataIsReadable()
untuk setiap tensor output. Pendekatan
ini juga berfungsi untuk model terkuantisasi, tetapi Anda masih perlu menggunakan
buffer berukuran float32 dengan data float32, karena buffer terikat dengan
buffer de-kuantisasi internal.
Model terkuantisasi
Library delegasi GPU iOS mendukung model terkuantisasi secara default. Anda tidak perlu membuat perubahan kode untuk menggunakan model terkuantisasi dengan delegasi GPU. Bagian berikut menjelaskan cara menonaktifkan dukungan terkuantisasi untuk tujuan pengujian atau eksperimental.
Menonaktifkan dukungan model terkuantisasi
Kode berikut menunjukkan cara menonaktifkan dukungan untuk model terkuantisasi.
Swift
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);
Untuk mengetahui informasi selengkapnya tentang menjalankan model terkuantisasi dengan akselerasi GPU, lihat ringkasan delegasi GPU.