Utilizzo delle GPU (Graphics Processing Unit) per eseguire i modelli di machine learning (ML) può migliorare notevolmente le prestazioni del modello e l'esperienza utente delle tue applicazioni abilitate per il machine learning. Sui dispositivi iOS, puoi attivare l'utilizzo di L'esecuzione dei modelli con accelerazione GPU utilizzando un delegato. I delegati agiscono da driver hardware per LiteRT, che ti consente di eseguire il codice del tuo modello sui processori GPU.
In questa pagina viene descritto come attivare l'accelerazione GPU per i modelli LiteRT in app per iOS Per saperne di più sull'utilizzo del delegato GPU per LiteRT: incluse best practice e tecniche avanzate, consulta la GPU delegata.
Utilizza GPU con l'API Interpreter
L'interprete di LiteRT dell'API fornisce un insieme di parametri per creare applicazioni di machine learning. Le seguenti istruzioni ti guidano nell'aggiunta del supporto GPU a un'app per iOS. Questa guida presuppone che tu abbia già un'app per iOS in grado di eseguire correttamente un modello ML con LiteRT.
Modifica il podfile per includere il supporto GPU
A partire dalla release LiteRT 2.3.0, il delegato GPU è escluso
dal pod per ridurre le dimensioni binarie. Puoi includerli specificando un
per il pod TensorFlowLiteSwift
:
pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',
OPPURE
pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']
Se vuoi usare, puoi anche usare TensorFlowLiteObjC
o TensorFlowLiteC
l'Objective-C, disponibile per le versioni 2.4.0 e successive, o l'API C.
Inizializza e utilizza il delegato GPU
Puoi utilizzare il delegato GPU con LiteRT Interpreter API con una serie di funzionalità lingue diverse. Le opzioni Swift e Objective-C sono consigliate, ma puoi anche usare C++ e C. Se usi una versione di LiteRT precedente, è necessario utilizzare C. rispetto a 2.4. I seguenti esempi di codice spiegano come utilizzare il delegato con ogni di queste lingue.
Swift
import TensorFlowLite // Load model ... // Initialize LiteRT 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 (prima della 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);
Note sull'utilizzo del linguaggio dell'API GPU
- Le versioni LiteRT precedenti alla 2.4.0 possono utilizzare solo l'API C per Obiettivo-C.
- L'API C++ è disponibile solo se utilizzi bazel o crei TensorFlow Lite, in autonomia. L'API C++ non può essere utilizzata con CocoaPods.
- Quando utilizzi LiteRT con il delegato GPU con C++, recupera la GPU
delegare tramite la funzione
TFLGpuDelegateCreate()
e poi passarlaInterpreter::ModifyGraphWithDelegate()
, anziché chiamareInterpreter::AllocateTensors()
.
Creazione e test con la modalità di rilascio
Passa a una build di release con le impostazioni appropriate dell'acceleratore dell'API Metal per per ottenere prestazioni migliori e per i test finali. Questa sezione spiega come Abilita una build di release e configura l'impostazione per l'accelerazione Metal.
Per passare a una build di release:
- Modifica le impostazioni della build selezionando Prodotto > Schema > Modifica schema... e selezionando Esegui.
- Nella scheda Informazioni, cambia Configurazione build in Release e deseleziona Esegui il debug dell'eseguibile.
- Fai clic sulla scheda Opzioni e imposta Acquisizione frame GPU su Disabilitata.
e Metal API Validation su Disabled (Disabilitata).
- Assicurati di selezionare Build di sola release su architettura a 64 bit. Sottopeso Navigazione progetti > esempio_fotocamera_tflite > PROGETTO > tuo_nome_progetto > Impostazioni build imposta Build Active Architecture Only > Rilascia per Sì.
Supporto GPU avanzato
Questa sezione illustra gli utilizzi avanzati del delegato GPU per iOS, tra cui le opzioni di delega, i buffer di input e di output e l'uso di modelli quantizzati.
Delega opzioni per iOS
Il costruttore per il delegato GPU accetta un struct
di opzioni in Swift
API,
Objective-C
API,
e C
tramite Google Cloud.
Trasmettere nullptr
(API C) o nulla (API Objective-C e Swift) alla
l'inizializzatore imposta le opzioni predefinite (spiegate nella sezione
esempio sopra).
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 di input/output utilizzando l'API C++
Il calcolo sulla GPU richiede che i dati siano disponibili per la GPU. Questo spesso significa che devi eseguire una copia della memoria. Dovresti evitare di avere se possibile, i tuoi dati superano il limite di memoria di CPU/GPU, poiché questo può per una quantità di tempo significativa. Di solito, questo tipo di attraversamento è inevitabile, ma in alcuni per i casi speciali, si può omettere l'uno o l'altro.
Se l'input della rete è un'immagine già caricata nella memoria GPU (ad ad esempio una texture GPU contenente il feed della videocamera), può rimanere nella memoria GPU senza mai entrare nella memoria della CPU. Analogamente, se l'output della rete di un'immagine di cui è possibile eseguire il rendering, ad esempio uno stile immagine trasferimento operativa, puoi visualizzare il risultato direttamente sullo schermo.
Per ottenere le migliori prestazioni, LiteRT consente agli utenti di le operazioni di lettura e scrittura direttamente nel buffer hardware di TensorFlow e di bypass di copie di memoria evitabili.
Supponendo che l'input dell'immagine sia nella memoria GPU, devi prima convertirlo in un
Oggetto MTLBuffer
per metallo. Puoi associare un TfLiteTensor
a un
MTLBuffer
preparato dall'utente con TFLGpuDelegateBindMetalBufferToTensor()
personalizzata. Tieni presente che questa funzione deve essere chiamata dopo
Interpreter::ModifyGraphWithDelegate()
. Inoltre, l'output di inferenza è
per impostazione predefinita, copiati dalla memoria GPU alla memoria CPU. Puoi disattivare questa impostazione.
chiamando il numero Interpreter::SetAllowBufferHandleOutput(true)
durante
durante l'inizializzazione.
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;
Una volta disattivato il comportamento predefinito, copia l'output di inferenza dalla GPU
dalla memoria alla memoria della CPU richiede una chiamata esplicita
Interpreter::EnsureTensorDataIsReadable()
per ogni tensore di output. Questo
funziona anche per i modelli quantizzati, ma devi comunque utilizzare una
Buffer con dimensioni float32 e dati float32, perché il buffer è associato alla
buffer dequantizzato interno.
Modelli quantificati
Le librerie delegati GPU iOS supportano i modelli quantizzati per impostazione predefinita. Non devi devi apportare modifiche al codice per usare modelli quantizzati con il delegato della GPU. La la seguente sezione spiega come disattivare il supporto quantizzato per i test o a scopi sperimentali.
Disabilita il supporto dei modelli quantiizzati
Il seguente codice mostra come disattivare il supporto per i modelli quantizzati.
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);
Per ulteriori informazioni sull'esecuzione di modelli quantizzati con l'accelerazione GPU, consulta Panoramica dei delegati alle GPU.