GPU-Delegierung für TensorFlow Lite

Die Verwendung von GPUs (Graphics Processing Units) zur Ausführung Ihrer Modelle für maschinelles Lernen (ML) kann die Leistung Ihres Modells und die Nutzerfreundlichkeit Ihrer ML-fähigen Anwendungen erheblich verbessern. TensorFlow Lite ermöglicht die Verwendung von GPUs und anderen spezialisierten Prozessoren über den Hardwaretreiber, der als Delegate bezeichnet wird. Die Aktivierung der Verwendung von GPUs mit Ihren TensorFlow Lite-ML-Anwendungen bietet folgende Vorteile:

  • Geschwindigkeit: GPUs sind auf einen hohen Durchsatz an massiv parallelen Arbeitslasten ausgelegt. Durch dieses Design eignen sie sich besonders für tiefe neuronale Netze, die aus einer großen Anzahl von Operatoren bestehen, die jeweils mit Eingabetensoren arbeiten, die parallel verarbeitet werden können, was in der Regel zu einer geringeren Latenz führt. Im besten Szenario wird das Modell auf einer GPU möglicherweise schnell genug ausgeführt, um Echtzeitanwendungen zu ermöglichen, die zuvor nicht möglich waren.
  • Energieeffizienz: GPUs führen ML-Berechnungen sehr effizient und optimiert aus. Sie verbrauchen in der Regel weniger Strom und erzeugen weniger Wärme als die gleiche Aufgabe, die auf CPUs ausgeführt wird.

Dieses Dokument bietet eine Übersicht über die GPU-Unterstützung in TensorFlow Lite und einige erweiterte Verwendungen von GPU-Prozessoren. Weitere Informationen zum Implementieren der GPU-Unterstützung auf bestimmten Plattformen finden Sie in den folgenden Anleitungen:

Unterstützung für GPU-ML-Vorgänge

Es gibt einige Einschränkungen dafür, welche TensorFlow-ML-Vorgänge oder Vorgänge durch den GPU-Delegaten von TensorFlow Lite beschleunigt werden können. Der Delegate unterstützt die folgenden Vorgänge mit 16-Bit- und 32-Bit-Gleitkommazahl:

  • 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

Standardmäßig werden alle Vorgänge nur ab Version 1 unterstützt. Wenn Sie die Quantisierungsunterstützung aktivieren, werden die entsprechenden Versionen aktiviert, z. B. ADD v2.

Fehlerbehebung beim GPU-Support

Wenn einige der Vorgänge nicht vom GPU-Delegaten unterstützt werden, führt das Framework nur einen Teil des Graphen auf der GPU und den verbleibenden Teil auf der CPU aus. Aufgrund der hohen Kosten für die CPU/GPU-Synchronisierung führt ein geteilter Ausführungsmodus wie dieser häufig zu einer langsameren Leistung, als wenn das gesamte Netzwerk allein mit der CPU ausgeführt wird. In diesem Fall generiert die Anwendung eine Warnung wie die folgende:

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

Für Fehler dieses Typs gibt es keinen Callback, da es sich nicht um einen tatsächlichen Laufzeitfehler handelt. Wenn Sie die Ausführung Ihres Modells mit dem GPU-Delegaten testen, sollten Sie auf diese Warnungen aufmerksam sein. Eine hohe Anzahl dieser Warnungen kann darauf hindeuten, dass Ihr Modell nicht für die GPU-Beschleunigung geeignet ist und möglicherweise eine Refaktorierung des Modells erfordert.

Beispielmodelle

Die folgenden Beispielmodelle wurden entwickelt, um die Vorteile der GPU-Beschleunigung mit TensorFlow Lite zu nutzen. Sie werden als Referenz und zum Testen bereitgestellt:

Für GPUs optimieren

Die folgenden Techniken können Ihnen dabei helfen, eine bessere Leistung zu erzielen, wenn Sie Modelle mit dem GPU-Delegaten von TensorFlow Lite auf GPU-Hardware ausführen:

  • Umformung von Vorgängen: Einige Vorgänge, die auf einer CPU schnell ausgeführt werden, können zu hohen Kosten für die GPU auf Mobilgeräten führen. Umformungsvorgänge wie BATCH_TO_SPACE, SPACE_TO_BATCH, SPACE_TO_DEPTH usw. sind besonders kostenintensiv. Sie sollten die Verwendung von Umformungsvorgängen genau untersuchen und berücksichtigen, dass diese möglicherweise nur zum Erkunden von Daten oder für erste Iterationen Ihres Modells verwendet wurden. Wenn Sie diese entfernen, kann dies die Leistung erheblich verbessern.

  • Bilddatenkanäle: Auf der GPU werden Tensordaten in vier Kanäle unterteilt. Daher wird eine Berechnung mit einem Tensor mit der Form [B,H,W,5] bei einem Tensor der Form [B,H,W,8] ungefähr gleich durchgeführt, jedoch erheblich schlechter als [B,H,W,4]. Wenn die verwendete Kamera-Hardware Bildframes im RGBA-Format unterstützt, ist die Einspeisung dieser 4-Kanal-Eingabe deutlich schneller, da keine Speicherkopien von 3-Kanal-RGB zu 4-Kanal-RGBX vorgenommen werden müssen.

  • Für Mobilgeräte optimierte Modelle: Für eine optimale Leistung sollten Sie den Klassifikator mit einer für Mobilgeräte optimierten Netzwerkarchitektur neu trainieren. Die Optimierung der On-Device-Inferenz kann die Latenz und den Stromverbrauch erheblich reduzieren, indem die Funktionen der mobilen Hardware genutzt werden.

Erweiterte GPU-Unterstützung

Sie können zusätzliche, erweiterte Verfahren mit GPU-Verarbeitung verwenden, um eine noch bessere Leistung Ihrer Modelle zu erzielen, einschließlich Quantisierung und Serialisierung. In den folgenden Abschnitten werden diese Techniken ausführlicher beschrieben.

Quantisierte Modelle verwenden

In diesem Abschnitt wird erläutert, wie der GPU-Delegate 8-Bit-quantisierte Modelle beschleunigt, einschließlich der folgenden:

Verwenden Sie zur Optimierung der Leistung Modelle, die sowohl Gleitkomma-Eingabe- als auch -Ausgabetensoren haben.

In diesem Artikel finden Sie ausführliche Informationen dazu.

Da das GPU-Back-End nur die Ausführung in Gleitkommazahlen unterstützt, führen wir quantisierte Modelle aus, indem wir ihnen eine Gleitkommaansicht des ursprünglichen Modells geben. Auf übergeordneter Ebene sind folgende Schritte erforderlich:

  • Konstantentensoren (z. B. Gewichtungen/Verzerrungen) werden einmal im GPU-Speicher dequantisiert. Dieser Vorgang erfolgt, wenn der Bevollmächtigte für TensorFlow Lite aktiviert ist.

  • Eingaben und Ausgaben an das GPU-Programm werden, wenn sie mit 8 Bit quantisiert sind, für jede Inferenz dequantisiert und quantisiert. Dieser Vorgang wird auf der CPU mit den optimierten Kerneln von TensorFlow Lite ausgeführt.

  • Quantisierungssimulatoren werden zwischen Vorgängen eingefügt, um das quantisierte Verhalten zu imitieren. Dieser Ansatz ist für Modelle erforderlich, bei denen die Aktivierungen den während der Quantisierung erlernten Grenzen folgen.

Informationen zum Aktivieren dieses Features mit dem GPU-Delegaten finden Sie hier:

Initialisierungszeit durch Serialisierung reduzieren

Mit dem GPU Delegate-Feature können Sie aus vorkompilierten Kernel-Code und Modelldaten, die aus früheren Ausführungen serialisiert und auf dem Laufwerk gespeichert werden, laden. Bei diesem Ansatz wird eine Neukompilierung vermieden und die Startzeit um bis zu 90 % verkürzt. Diese Verbesserung wird erreicht, indem der Speicherplatz ausgetauscht wird, um Zeit zu sparen. Sie können diese Funktion mit einigen Konfigurationsoptionen aktivieren, wie in den folgenden Codebeispielen gezeigt:

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);
      

Wenn Sie die Serialisierungsfunktion verwenden, achten Sie darauf, dass Ihr Code diesen Implementierungsregeln entspricht:

  • Speichern Sie die Serialisierungsdaten in einem Verzeichnis, auf das andere Anwendungen nicht zugreifen können. Verwenden Sie auf Android-Geräten getCodeCacheDir(), das auf einen Standort verweist, der für die aktuelle App privat ist.
  • Das Modelltoken muss für das Gerät des jeweiligen Modells eindeutig sein. Zum Berechnen eines Modelltokens wird mithilfe von Bibliotheken wie farmhash::Fingerprint64 ein Fingerabdruck aus den Modelldaten generiert.