API-Treiber für neuronale Netzwerke

Diese Seite bietet einen Überblick über die Implementierung eines Neural Networks API (NNAPI)-Treibers. Weitere Einzelheiten finden Sie in der Dokumentation in den HAL - Definitionsdateien gefunden hardware/interfaces/neuralnetworks . Eine Probe Treiberimplementierung ist in frameworks/ml/nn/driver/sample .

Weitere Informationen über die API Neuronale Netze, siehe Neuronale Netze API .

Neuronale Netze HAL

Die neuronale Netzwerke (NN) HAL definiert eine Abstraktion der verschiedenen Geräte, wie beispielsweise Grafikverarbeitungseinheiten (GPUs) und digitaler Signalprozessoren (DSPs), die (beispielsweise ein Telefon oder Tablette) in einem Produkt ist. Die Treiber für diese Geräte müssen der NN HAL entsprechen. Die Schnittstelle wird in den HAL - Definitionsdateien in bestimmten hardware/interfaces/neuralnetworks .

Der allgemeine Ablauf der Schnittstelle zwischen dem Framework und einem Treiber ist in Abbildung 1 dargestellt.

Fluss neuronaler Netze

Abbildung 1. Neural Networks Strömungs

Initialisierung

Bei der Initialisierung fragt der Rahmen die Treiber für seine Fähigkeiten mit IDevice::getCapabilities_1_3 . Die @1.3::Capabilities Struktur umfasst alle Datentypen und stellt nicht relaxiertem Leistung unter Verwendung eines Vektors.

Um zu bestimmen, wie Berechnungen den verfügbaren Geräten zugewiesen werden, verwendet das Framework die Fähigkeiten, um zu verstehen, wie schnell und wie energieeffizient jeder Treiber eine Ausführung durchführen kann. Um diese Informationen bereitzustellen, muss der Treiber standardisierte Leistungszahlen basierend auf der Ausführung von Referenz-Workloads bereitstellen.

Um die Werte zu bestimmen , dass der Fahrer zurückkehrt in Antwort auf IDevice::getCapabilities_1_3 , verwenden , um die Benchmark NNAPI app die Leistung für die entsprechenden Datentypen zu messen. Die MobileNet v1 und v2, asr_float und tts_float Modelle zur Messung der Leistung für 32-Bit Fließkommawerte empfohlen werden und die MobileNet v1 und v2 quantisiert Modelle werden empfohlen für 8-Bit - Werte quantisiert. Weitere Informationen finden Sie Android Machine Learning Test Suite .

In Android 9 und die unteren, das Capabilities umfasst Struktur Treiberleistungsinformationen nur für Punkt und quantisiert Tensoren Schwimm- und umfasst keine skalare Datentypen.

Im Rahmen der Initialisierung kann der Rahmen mehr Informationen abfragen, mit IDevice::getType , IDevice::getVersionString , IDevice:getSupportedExtensions und IDevice::getNumberOfCacheFilesNeeded .

Zwischen Produktneustarts erwartet das Framework, dass alle in diesem Abschnitt beschriebenen Abfragen immer dieselben Werte für einen bestimmten Treiber melden. Andernfalls kann eine App, die diesen Treiber verwendet, eine verringerte Leistung oder ein falsches Verhalten aufweisen.

Zusammenstellung

Das Framework bestimmt, welche Geräte verwendet werden sollen, wenn es eine Anfrage von einer App erhält. In Android 10 können Apps die Geräte erkennen und angeben, von denen das Framework auswählt. Weitere Informationen finden Sie Device Discovery und Zuordnung .

Bei Modell Kompilierung sendet der Rahmen um das Modell zu jedem Kandidaten - Treiber durch den Aufruf IDevice::getSupportedOperations_1_3 . Jeder Treiber gibt ein Array von booleschen Werten zurück, die angeben, welche Operationen des Modells unterstützt werden. Ein Treiber kann aus verschiedenen Gründen feststellen, dass er einen bestimmten Vorgang nicht unterstützen kann. Zum Beispiel:

  • Der Treiber unterstützt den Datentyp nicht.
  • Der Treiber unterstützt nur Operationen mit bestimmten Eingabeparametern. Ein Treiber kann beispielsweise 3x3- und 5x5-, aber keine 7x7-Faltungsoperationen unterstützen.
  • Der Treiber hat Speicherbeschränkungen, die ihn daran hindern, große Graphen oder Eingaben zu verarbeiten.

Während der Kompilierung der Eingangs-, Ausgangs- und interne Operanden des Modells, wie beschrieben in OperandLifeTime können unbekannte Dimensionen oder Rang haben. Weitere Informationen finden Sie Ausgangsform .

Der Rahmen weist jeden ausgewählten Treiber herzustellen , die eine Teilmenge des Modells auszuführen durch den Aufruf IDevice::prepareModel_1_3 . Jeder Treiber kompiliert dann seine Untermenge. Beispielsweise könnte ein Fahrer Code generieren oder eine neu geordnete Kopie der Gewichte erstellen. Da zwischen der Kompilierung des Modells und der Ausführung von Anforderungen eine beträchtliche Zeit vergehen kann, sollten während der Kompilierung keine Ressourcen wie große Teile des Gerätespeichers zugewiesen werden.

Bei Erfolg gibt der Fahrer ein @1.3::IPreparedModel Griff. Wenn der Treiber beim Vorbereiten seiner Teilmenge des Modells einen Fehlercode zurückgibt, führt das Framework das gesamte Modell auf der CPU aus.

Um die Kompilierungszeit beim Starten einer App zu verkürzen, kann ein Treiber Kompilierungsartefakte zwischenspeichern. Weitere Informationen finden Sie Compilation Caching .

Ausführung

Wenn eine App den Rahmen stellt eine Anforderung auszuführen, ruft das Framework die IPreparedModel::executeSynchronously_1_3 HAL - Methode standardmäßig eine synchrone Ausführung auf einem vorbereiteten Modell durchzuführen. Eine Anforderung kann auch asynchron mit der ausgeführt wird execute_1_3 Methode, die executeFenced Methode (siehe Eingezäunt Ausführung ) oder ausgeführt unter Verwendung einer Burst - Ausführung .

Synchrone Ausführungsaufrufe verbessern die Leistung und reduzieren den Threading-Overhead im Vergleich zu asynchronen Aufrufen, da die Steuerung erst nach Abschluss der Ausführung an den App-Prozess zurückgegeben wird. Dies bedeutet, dass der Treiber keinen separaten Mechanismus benötigt, um den App-Prozess zu benachrichtigen, dass eine Ausführung abgeschlossen ist.

Mit dem asynchronen execute_1_3 Verfahren kehrt die Steuerung zu dem App - Prozess nach der Ausführung begonnen hat, und der Fahrer muss den Rahmen benachrichtigen , wenn die Ausführung abgeschlossen ist, mit dem @1.3::IExecutionCallback .

Die Request Parameter an die Methode übergeben auszuführen listet die Eingangs- und Ausgangsoperanden für die Ausführung verwendet. Der Speicher, in dem die Operandendaten gespeichert werden, muss die Reihenfolge der Hauptreihenfolge verwenden, wobei die erste Dimension am langsamsten iteriert und am Ende einer Reihe keine Auffüllungen aufweisen. Weitere Informationen über die Arten von Operanden siehe Operanden .

Für NN HAL 1.2 oder höher Fahrer, wenn eine Anforderung abgeschlossen ist, den Fehlerzustand, Ausgangsform und Timing - Informationen werden an den Rahmen zurückgeführt . Während der Ausführung können Ausgabe- oder interne Operanden des Modells eine oder mehrere unbekannte Dimensionen oder einen unbekannten Rang haben. Wenn mindestens ein Ausgabeoperand eine unbekannte Dimension oder einen unbekannten Rang hat, muss der Treiber Ausgabeinformationen mit dynamischer Größe zurückgeben.

Bei Treibern mit NN HAL 1.1 oder niedriger wird nur der Fehlerstatus zurückgegeben, wenn eine Anforderung abgeschlossen ist. Die Dimensionen für Eingabe- und Ausgabeoperanden müssen vollständig angegeben werden, damit die Ausführung erfolgreich abgeschlossen werden kann. Interne Operanden können eine oder mehrere unbekannte Dimensionen haben, sie müssen jedoch einen angegebenen Rang haben.

Bei Benutzeranforderungen, die sich über mehrere Treiber erstrecken, ist das Framework dafür verantwortlich, Zwischenspeicher zu reservieren und die Aufrufe an jeden Treiber zu sequenzieren.

Mehrere Anforderungen können parallel auf derselben eingeleitet werden @1.3::IPreparedModel . Der Treiber kann Anforderungen parallel ausführen oder die Ausführungen serialisieren.

Das Framework kann einen Treiber auffordern, mehr als ein vorbereitetes Modell zu behalten. Beispielsweise vorzubereiten Modell m1 , bereiten m2 , Anfrage auszuführen r1 auf m1 , führen r2 auf m2 , führen r3 auf m1 , führen r4 auf m2 , Freisetzung (beschrieben in Cleanup ) m1 , und die Freigabe m2 .

Um eine langsame Erstausführung zu vermeiden, die zu einer schlechten Benutzererfahrung führen könnte (z. B. ein Stottern des ersten Frames), sollte der Treiber die meisten Initialisierungen in der Kompilierungsphase durchführen. Die Initialisierung bei der ersten Ausführung sollte auf Aktionen beschränkt werden, die sich bei früher Ausführung negativ auf den Systemzustand auswirken, wie z. B. das Reservieren großer temporärer Puffer oder das Erhöhen der Taktrate eines Geräts. Treiber, die nur eine begrenzte Anzahl gleichzeitiger Modelle vorbereiten können, müssen möglicherweise ihre Initialisierung bei der ersten Ausführung durchführen.

In Android 10 oder höher kann der Client in Fällen, in denen mehrere Ausführungen mit demselben vorbereiteten Modell in schneller Folge ausgeführt werden, ein Ausführungsburst-Objekt verwenden, um zwischen App- und Treiberprozessen zu kommunizieren. Weitere Informationen finden Sie Exekutionen und Fast Message Queues Burst .

Um die Leistung für mehrere Ausführungen in schneller Folge zu verbessern, kann der Treiber temporäre Puffer beibehalten oder die Taktraten erhöhen. Es wird empfohlen, einen Watchdog-Thread zu erstellen, um Ressourcen freizugeben, wenn nach einem festgelegten Zeitraum keine neuen Anforderungen erstellt werden.

Ausgabeform

Bei Anforderungen, bei denen für einen oder mehrere Ausgabeoperanden nicht alle Dimensionen angegeben sind, muss der Treiber nach der Ausführung eine Liste von Ausgabe-Shapes mit den Dimensionsinformationen für jeden Ausgabeoperanden bereitstellen. Weitere Informationen zu den Abmessungen finden OutputShape .

Wenn eine Ausführung aufgrund eines zu kleinen Ausgabepuffers fehlschlägt, muss der Treiber in der Liste der Ausgabeformen angeben, welche Ausgabeoperanden eine unzureichende Puffergröße aufweisen, und sollte so viele Dimensionsinformationen wie möglich melden, wobei Null für unbekannte Dimensionen verwendet wird.

Zeitliche Koordinierung

In Android 10 kann eine App nach der Ausführungszeit fragen, wenn die App ein einzelnes Gerät angegeben hat, das während des Kompilierungsvorgangs verwendet werden soll. Weitere Einzelheiten finden Sie MeasureTiming und Geräteerkennung und Zuordnung . In diesem Fall muss ein NN HAL 1.2 Treiber Ausführungsdauer messen oder berichtet UINT64_MAX (um anzuzeigen , dass die Dauer nicht verfügbar ist) , wenn eine Anfrage ausführt. Der Treiber sollte jegliche Leistungseinbußen minimieren, die sich aus der Messung der Ausführungsdauer ergeben.

Der Fahrer meldet die folgenden Dauern in Mikrosekunden in der Timing

  • Ausführungszeit auf dem Gerät: nicht enthält Ausführungszeit im Treiber, die auf dem Host - Prozessor läuft.
  • Ausführungszeit im Treiber: Beinhaltet die Ausführungszeit auf dem Gerät.

Diese Dauer muss die Zeit umfassen, in der die Ausführung ausgesetzt wird, beispielsweise wenn die Ausführung durch andere Tasks unterbrochen wurde oder wenn darauf gewartet wird, dass eine Ressource verfügbar wird.

Wenn der Fahrer nicht die Ausführungsdauer zu messen, oder wenn es ein Ausführungsfehler gefragt wurde, muss der Fahrer Dauern wie berichten UINT64_MAX . Selbst wenn der Fahrer aufgefordert wurde , die Ausführungsdauer zu messen, kann es stattdessen berichten UINT64_MAX für die Zeit auf dem Gerät, Zeit im Treiber oder beides. Wenn der Fahrer meldet beide Dauern als einen anderen Wert als UINT64_MAX muss die Ausführungszeit in den Fahrer gleich oder die Zeit auf der Vorrichtung übersteigt.

Eingezäunte Ausführung

In Android 11 ermöglicht NNAPI Ausführungen für eine Liste von warten sync_fence Griffen und optional ein Rück sync_fence Objekt, das signalisiert wird , wenn die Ausführung abgeschlossen ist. Dies reduziert den Overhead für kleine Sequenzmodelle und Streaming-Anwendungsfälle. Eingezäunt Ausführung ermöglicht auch eine effizientere Interoperabilität mit anderen Komponenten , die für das Signal oder warten können sync_fence . Weitere Informationen über sync_fence finden Synchronisations - Framework .

In einer eingezäunten Ausführung ruft der Rahmen die IPreparedModel::executeFenced Verfahren eine eingezäunten, asynchrone Ausführung auf einem vorbereitetes Modell mit einem Vektor , der Synchronisations Zäunen starten zu warten. Wenn die asynchrone Aufgabe bevor der Aufruf zurückgegeben beendet ist, kann ein leerer Griff für zurückgegeben werden sync_fence . Ein IFencedExecutionCallback Objekt muss auch den Rahmen , um den Abfragefehlerstatus und Dauer Informationen ermöglichen zurückgegeben werden.

Nach einer Ausführung abgeschlossen ist, werden die folgenden zwei Zeit können Werte , die Dauer der Ausführung durch Messen abgefragt werden IFencedExecutionCallback::getExecutionInfo .

  • timingLaunched : Dauer von dem Zeitpunkt an executeFenced wird aufgerufen , wenn executeFenced signalisiert die zurück syncFence .
  • timingFenced : Dauer aus , wenn alle sync Zäunen , dass die Ausführung wartet , bis signalisiert werden , wenn executeFenced signalisiert die zurück syncFence .

Kontrollfluss

Für Geräte mit Android 11 oder höher, enthält die NNAPI zwei Kontrollflussoperationen, IF und WHILE , dass andere Modelle als Argument und führen sie bedingt ( IF ) oder wiederholt ( WHILE ). Weitere Informationen darüber , wie dies zu realisieren, siehe Flusssteuerung .

Servicequalität

In Android 11 bietet die NNAPI eine verbesserte Dienstqualität (QoS), indem sie es einer App ermöglicht, die relativen Prioritäten ihrer Modelle, die maximal erwartete Zeit für die Vorbereitung eines Modells und die maximal erwartete Zeit für eine Ausführung anzugeben zu vervollständigen. Weitere Informationen finden Sie Quality of Service .

Aufräumen

Wenn eine App fertig ist ein vorbereitetes Modell gibt den Rahmen seine Bezugnahme auf das @1.3::IPreparedModel Objekt. Wenn das IPreparedModel Objekt nicht mehr Bezug genommen wird , wird er automatisch in den Treiberdienst zerstört , die es erstellt. Modellspezifische Ressourcen können zu diesem Zeitpunkt in der Treiberimplementierung des Destruktors zurückgefordert werden. Wenn der Fahrer Service das will IPreparedModel Objekt wird automatisch zerstört , wenn nicht mehr benötigt , durch die Kunden, muss es keine Hinweise auf das halten IPreparedModel Objekt nach dem IPreparedeModel Objekt durch zurückgegeben worden IPreparedModelCallback::notify_1_3 .

CPU auslastung

Von Treibern wird erwartet, dass sie die CPU verwenden, um Berechnungen einzurichten. Treiber sollten die CPU nicht zum Durchführen von Diagrammberechnungen verwenden, da dies die Fähigkeit des Frameworks beeinträchtigt, Arbeit korrekt zuzuweisen. Der Treiber sollte die Teile, die er nicht verarbeiten kann, an das Framework melden und das Framework den Rest erledigen lassen.

Das Framework bietet eine CPU-Implementierung für alle NNAPI-Operationen mit Ausnahme von herstellerdefinierten Operationen. Weitere Informationen finden Sie Erweiterungen des Herstellers .

Die Operationen in Android 10 eingeführt (API - Ebene 29) nur eine Referenz CPU Implementierung zu überprüfen , dass die CTS und VTS Tests korrekt sind. Die optimierten Implementierungen, die in Frameworks für mobiles maschinelles Lernen enthalten sind, werden gegenüber der NNAPI-CPU-Implementierung bevorzugt.

Dienstprogrammfunktionen

Die NNAPI-Codebasis enthält Dienstprogrammfunktionen, die von Treiberdiensten verwendet werden können.

Die frameworks/ml/nn/common/include/Utils.h Datei für die Protokollierung verwendet verschiedene Hilfsfunktionen, wie diejenigen , enthält und für die Versionen zwischen verschiedenen NN HAL umwandelt.

  • Vlogging: VLOG ist ein Wrapper um Makro Android LOG , das nur die Nachricht protokolliert , wenn der entsprechende Tag in der festgelegt ist debug.nn.vlog Eigenschaft. initVLogMask() muss vor allen Anrufen aufgerufen wird VLOG . Das VLOG_IS_ON Makro kann verwendet werden , um zu überprüfen , ob VLOG momentan aktiviert ist , so dass komplizierte Logging - Code übersprungen werden , wenn es nicht gebraucht wird . Der Wert der Immobilie muss einer der folgenden sein:

    • Eine leere Zeichenfolge, die angibt, dass keine Protokollierung durchgeführt werden soll.
    • Das Token - 1 oder all , was darauf hinweist , dass alle Logging durchgeführt werden soll.
    • Eine durch Leerzeichen, Kommas oder Doppelpunkte getrennte Liste von Tags, die angibt, welche Protokollierung durchgeführt werden soll. Die Tags sind compilation , cpuexe , driver , execution , manager und model .
  • compliantWithV1_* : Gibt true , wenn ein NN HAL Objekt ohne Verlust Informationen zu der gleichen Art von einer anderen HAL - Version umgewandelt werden. Zum Beispiel ruft compliantWithV1_0 auf einem V1_2::Model liefert false , wenn das Modell in NN HAL 1.1 oder NN HAL 1.2 eingeführten Typen Betrieb umfasst.

  • convertToV1_* : Wandelt ein NN HAL Objekt von einer Version zur anderen. Eine Warnung wird protokolliert, wenn die Konvertierung zu einem Informationsverlust führt (dh wenn die neue Version des Typs den Wert nicht vollständig darstellen kann).

  • Fähigkeiten: Die nonExtensionOperandPerformance und update - Funktionen können die zum Aufbau verwendet werden Capabilities::operandPerformance Feld.

  • Abfragt Eigenschaften von Typen: isExtensionOperandType , isExtensionOperationType , nonExtensionSizeOfData , nonExtensionOperandSizeOfData , nonExtensionOperandTypeIsScalar , tensorHasUnspecifiedDimensions .

Die frameworks/ml/nn/common/include/ValidateHal.h Datei enthält Utility - Funktionen zum Validieren , dass ein NN HAL Objekt gültig ist entsprechend seine HAL Version der Spezifikation.

  • validate* : Rückkehr true , wenn das NN HAL Objekt nach seiner HAL - Version der Spezifikation gültig ist. OEM-Typen und Erweiterungstypen werden nicht validiert. Zum Beispiel validateModel kehrt false , wenn das Modell eine Operation , dass Verweise einen Operand Index enthält , die nicht vorhanden ist, oder eine Operation , die zu dieser HAL - Version nicht unterstützt wird.

Die frameworks/ml/nn/common/include/Tracing.h Datei Makros enthält zu vereinfachen das Hinzufügen systracing Informationen über Neuronale Netze Code. Ein Beispiel finden Sie in dem NNTRACE_* Makro Anrufungen in dem Beispieltreiber .

Die frameworks/ml/nn/common/include/GraphDump.h Datei enthält eine Programmfunktion , den Inhalt eines dump Model in graphischer Form für Debugging - Zwecke.

  • graphDump : Schreibt eine Darstellung des Modells in Graphviz ( .dot ) -Format an den angegebenen Strom (falls vorhanden) oder auf die logcat (wenn kein Strom zur Verfügung gestellt wird).

Validierung

Verwenden Sie zum Testen Ihrer Implementierung der NNAPI die im Android-Framework enthaltenen VTS- und CTS-Tests. VTS trainiert Ihre Fahrer direkt (ohne das Framework zu verwenden), während CTS sie indirekt über das Framework ausübt. Diese testen jede API-Methode und überprüfen, ob alle von den Treibern unterstützten Operationen korrekt funktionieren und Ergebnisse liefern, die den Genauigkeitsanforderungen entsprechen.

Die Genauigkeitsanforderungen in CTS und VTS für die NNAPI sind wie folgt:

  • Gleitkommazahlen: abs (erwartet - Ist) <= atol + rtol * abs (erwartet); wo:

    • Für fp32, atol = 1e-5f, rtol = 5.0f * 1,1920928955078125e-7
    • Für fp16 ist atol = rtol = 5,0f * 0,0009765625f
  • Quantisiert: off-by-one ( mit Ausnahme mobilenet_quantized , was off-mal-drei)

  • Boolean: exakte Übereinstimmung

Eine Möglichkeit, wie CTS NNAPI testet, besteht darin, feste pseudozufällige Graphen zu generieren, die zum Testen und Vergleichen der Ausführungsergebnisse jedes Treibers mit der NNAPI-Referenzimplementierung verwendet werden. Für Fahrer mit NN HAL 1.2 oder höher, wenn die Ergebnisse der Präzisionskriterien nicht erfüllen, berichtet CTS einen Fehler und Dumps eine Spezifikationsdatei für das ausgefallene Modell unter /data/local/tmp für das Debuggen. Weitere Einzelheiten zu den Präzisionskriterien siehe TestRandomGraph.cpp und TestHarness.h .

Fuzz-Tests

Der Zweck von Fuzz-Tests besteht darin, Abstürze, Assertionen, Speicherverletzungen oder allgemeines undefiniertes Verhalten im getesteten Code aufgrund von Faktoren wie unerwarteten Eingaben zu finden. Für NNAPI Fuzzing verwendet Android Tests basierend auf libFuzzer , die bei fuzzing effizient sind , weil sie Linie Deckung früherer Testfälle verwenden , um neue Zufalls Eingänge zu erzeugen. Beispielsweise bevorzugt libFuzzer Testfälle, die auf neuen Codezeilen ausgeführt werden. Dadurch wird der Zeitaufwand für Tests zum Auffinden von problematischem Code erheblich reduziert.

Zur Durchführung Fuzzing Ihre Treiber - Implementierung, modify zu validieren frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp im libneuralnetworks_driver_fuzzer Testprogramm gefunden in AOSP auf Ihren Treibercode enthält. Weitere Informationen finden Sie auf NNAPI Fuzzing, frameworks/ml/nn/runtime/test/android_fuzzing/README.md .

Sicherheit

Da App-Prozesse direkt mit dem Prozess eines Treibers kommunizieren, müssen Treiber die Argumente der eingehenden Aufrufe validieren. Diese Validierung wird von VTS verifiziert. Der Validierungscode wird in frameworks/ml/nn/common/include/ValidateHal.h .

Treiber sollten auch sicherstellen, dass Apps andere Apps nicht stören können, wenn sie dasselbe Gerät verwenden.

Android Machine Learning Testsuite

Die Android Machine Learning Test Suite (MLTS) ist ein NNAPI-Benchmark, der in CTS und VTS enthalten ist, um die Genauigkeit realer Modelle auf Herstellergeräten zu überprüfen. Die Benchmark - Latenzzeit und Genauigkeit auswertet und vergleicht die Ergebnisse der Fahrer mit den Ergebnissen unter Verwendung von TF Lite auf der CPU ausgeführt wird , für das gleiche Modell und Datensätze. Dadurch wird sichergestellt, dass die Genauigkeit eines Treibers nicht schlechter ist als die der CPU-Referenzimplementierung.

Entwickler von Android-Plattformen verwenden MLTS auch, um die Latenz und Genauigkeit von Treibern zu bewerten.

Der NNAPI-Benchmark ist in zwei Projekten in AOSP zu finden:

Modelle und Datensätze

Der NNAPI-Benchmark verwendet die folgenden Modelle und Datensätze.

  • MobileNetV1 float und u8 quantisiert in verschiedenen Größen, laufen gegen eine kleine Teilmenge (1500 Bilder) von Open Images Dataset v4.
  • MobileNetV2 float und u8 quantisiert in verschiedenen Größen, laufen gegen eine kleine Teilmenge (1500 Bilder) von Open Images Dataset v4.
  • Langes Kurzzeitgedächtnis (LSTM) basiertes akustisches Modell für Text-to-Speech, das gegen eine kleine Teilmenge des CMU Arctic Sets ausgeführt wird.
  • LSTM-basiertes Akustikmodell für die automatische Spracherkennung, das gegen eine kleine Teilmenge des LibriSpeech-Datensatzes ausgeführt wird.

Weitere Informationen finden Sie platform/test/mlts/models .

Stresstest

Die Android Machine Learning Test Suite umfasst eine Reihe von Crashtests, um die Belastbarkeit von Fahrern unter intensiven Nutzungsbedingungen oder in Eckfällen des Kundenverhaltens zu überprüfen.

Alle Crashtests bieten die folgenden Funktionen:

  • Hang Erkennung: Wenn die NNAPI Client hängt während eines Tests, der Test nicht erfolgreich mit der Störungsursache HANG und die Testsuite wechselt zum nächsten Test.
  • NNAPI Client Crasherkennung: Tests überleben Client Abstürze und Tests fehlschlagen mit Störungsursache CRASH .
  • Treiber Crasherkennung: Tests können einen Fahrer Absturz erkennen , die einen Fehler auf einem NNAPI Anruf verursacht. Beachten Sie, dass es bei Treiberprozessen zu Abstürzen kommen kann, die keinen NNAPI-Fehler verursachen und den Test nicht zum Scheitern bringen. Um diese Art von Fehler abzudecken, ist es empfehlenswert , die laufen tail Befehl auf das Systemprotokoll für fahrerbezogene Fehler oder Abstürze.
  • Targeting aller verfügbaren Beschleuniger: Die Tests werden durchgeführt gegen alle verfügbaren Treiber.

Alle Crashtests haben die folgenden vier möglichen Ergebnisse:

  • SUCCESS : Ausführung ohne Fehler beendet.
  • FAILURE : Die Ausführung ist fehlgeschlagen. Wird normalerweise durch einen Fehler beim Testen eines Modells verursacht, der darauf hinweist, dass der Treiber das Modell nicht kompilieren oder ausführen konnte.
  • HANG : Testprozess wurde nicht reagiert.
  • CRASH : Testprozess abgestürzt.

Weitere Informationen zu den Stresstests und eine vollständige Liste der Crash - Tests finden Sie platform/test/mlts/benchmark/README.txt .

Verwenden von MLTS

So verwenden Sie das MLTS:

  1. Schließen Sie ein Zielgerät an Ihrem Arbeitsplatz und sicherstellen , dass es durch erreichbar ist adb . Exportieren des Zielgeräts ANDROID_SERIAL Umgebungsvariable , wenn mehr als ein Gerät angeschlossen ist.
  2. cd in das Android - Top-Level - Quellverzeichnis.

    source build/envsetup.sh
    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available.
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    Am Ende eines Benchmark -Durchlaufs werden die Ergebnisse als HTML - Seite dargestellt und weitergegeben xdg-open .

Weitere Informationen finden Sie platform/test/mlts/benchmark/README.txt .

HAL-Versionen für neuronale Netze

In diesem Abschnitt werden die Änderungen beschrieben, die in den HAL-Versionen von Android und Neural Networks eingeführt wurden.

Android 11

Android 11 führt NN HAL 1.3 ein, das die folgenden bemerkenswerten Änderungen enthält.

  • Unterstützung für vorzeichenbehaftete 8-Bit-Quantisierung in NNAPI. Fügt den TENSOR_QUANT8_ASYMM_SIGNED Operandentyp. Treiber mit NN HAL 1.3, die Operationen mit vorzeichenloser Quantisierung unterstützen, müssen auch die vorzeichenbehafteten Varianten dieser Operationen unterstützen. Wenn mit und ohne Vorzeichen Versionen der meisten quantisiert Operationen ausgeführt wird , Treiber müssen die gleichen Ergebnisse bis zu einem von 128 Offset erzeugen Es gibt fünf Ausnahmen von dieser Anforderung: CAST , HASHTABLE_LOOKUP , LSH_PROJECTION , PAD_V2 und QUANTIZED_16BIT_LSTM . Die QUANTIZED_16BIT_LSTM Operation nicht unterstützt unterzeichnet Operanden und die anderen vier Operationen unterstützen unterzeichnet Quantisierung aber keine Anzeigen benötigen das gleiche sein.
  • Unterstützung für eingezäunten Hinrichtung , wo der Rahmen , um die Anrufe IPreparedModel::executeFenced Methode eine eingezäunten, asynchrone Ausführung auf einem vorbereitetes Modell mit einem Vektor von sync Zäunen zu starten , um zu warten. Weitere Informationen finden Sie Eingezäunt Ausführung .
  • Unterstützung für den Kontrollfluss. Fügt die IF und WHILE Operationen, die anderen Modelle als Argument und führen sie bedingt ( IF ) oder wiederholt ( WHILE ). Weitere Informationen finden Sie Flusssteuerung .
  • Verbesserte Dienstgüte (QoS) als Apps können die relativen Prioritäten ihrer Modelle, die maximal erwartete Zeit für die Vorbereitung eines Modells und die maximal erwartete Zeit für den Abschluss einer Ausführung anzeigen. Weitere Informationen finden Sie Quality of Service .
  • Unterstützung für Speicherdomänen, die Zuweisungsschnittstellen für treiberverwaltete Puffer bereitstellen. Dies ermöglicht die Weitergabe von geräteeigenen Speichern über Ausführungen hinweg, wodurch unnötiges Kopieren und Umwandeln von Daten zwischen aufeinanderfolgenden Ausführungen auf demselben Treiber verhindert wird. Weitere Informationen finden Sie Speicherdomänen .

Android 10

Android 10 führt NN HAL 1.2 ein, das die folgenden bemerkenswerten Änderungen enthält.

  • Die Capabilities Struktur umfasst alle Datentypen einschließlich skalare Datentypen und stellt nicht relaxiertem Leistung durch einen Vektor nicht genannten Bereichen verwenden.
  • Die getVersionString und getType Methoden erlauben der Rahmengerätetyp (zum Abrufen DeviceType ) und Versionsinformationen. Siehe Geräteermittlung und Zuordnung .
  • Die executeSynchronously Verfahren wird standardmäßig genannt synchron eine Ausführung durchzuführen. Die execute_1_2 Methode teilt den Rahmen eine Ausführung asynchron auszuführen. Siehe Ausführung .
  • Der MeasureTiming Parameter executeSynchronously , execute_1_2 und Burst Ausführung Gibt an, ob der Fahrer Ausführungsdauer zu messen. Die Ergebnisse sind in der Timing Siehe Zeitplan .
  • Unterstützung für Ausführungen, bei denen ein oder mehrere Ausgabeoperanden eine unbekannte Dimension oder einen unbekannten Rang haben. Siehe Ausgabeform .
  • Unterstützung für Herstellererweiterungen, bei denen es sich um Sammlungen von anbieterdefinierten Operationen und Datentypen handelt. Die Treiber Berichte Erweiterungen durch die unterstützte IDevice::getSupportedExtensions Methode. Siehe Erweiterungen des Herstellers .
  • Möglichkeit für ein Burst-Objekt, eine Reihe von Burst-Ausführungen mithilfe von Fast Message Queues (FMQs) zu steuern, um zwischen App- und Treiberprozessen zu kommunizieren und so die Latenz zu reduzieren. Siehe Burst Exekutionen und Fast Message Queues .
  • Unterstützung für AHardwareBuffer, damit der Treiber Ausführungen ausführen kann, ohne Daten zu kopieren. Siehe AHardwareBuffer .
  • Verbesserte Unterstützung für das Caching von Kompilierungsartefakten, um die Kompilierungszeit beim Starten einer App zu reduzieren. Siehe Compilation Caching .

Android 10 führt die folgenden Operandentypen und Operationen ein.

  • Operandentypen

    • ANEURALNETWORKS_BOOL
    • ANEURALNETWORKS_FLOAT16
    • ANEURALNETWORKS_TENSOR_BOOL8
    • ANEURALNETWORKS_TENSOR_FLOAT16
    • ANEURALNETWORKS_TENSOR_QUANT16_ASYMM
    • ANEURALNETWORKS_TENSOR_QUANT16_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
  • Betrieb

    • ANEURALNETWORKS_ABS
    • ANEURALNETWORKS_ARGMAX
    • ANEURALNETWORKS_ARGMIN
    • ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN
    • ANEURALNETWORKS_BOX_WITH_NMS_LIMIT
    • ANEURALNETWORKS_CAST
    • ANEURALNETWORKS_CHANNEL_SHUFFLE
    • ANEURALNETWORKS_DETECTION_POSTPROCESSING
    • ANEURALNETWORKS_EQUAL
    • ANEURALNETWORKS_EXP
    • ANEURALNETWORKS_EXPAND_DIMS
    • ANEURALNETWORKS_GATHER
    • ANEURALNETWORKS_GENERATE_PROPOSALS
    • ANEURALNETWORKS_GREATER
    • ANEURALNETWORKS_GREATER_EQUAL
    • ANEURALNETWORKS_GROUPED_CONV_2D
    • ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT
    • ANEURALNETWORKS_INSTANCE_NORMALIZATION
    • ANEURALNETWORKS_LESS
    • ANEURALNETWORKS_LESS_EQUAL
    • ANEURALNETWORKS_LOG
    • ANEURALNETWORKS_LOGICAL_AND
    • ANEURALNETWORKS_LOGICAL_NOT
    • ANEURALNETWORKS_LOGICAL_OR
    • ANEURALNETWORKS_LOG_SOFTMAX
    • ANEURALNETWORKS_MAXIMUM
    • ANEURALNETWORKS_MINIMUM
    • ANEURALNETWORKS_NEG
    • ANEURALNETWORKS_NOT_EQUAL
    • ANEURALNETWORKS_PAD_V2
    • ANEURALNETWORKS_POW
    • ANEURALNETWORKS_PRELU
    • ANEURALNETWORKS_QUANTIZE
    • ANEURALNETWORKS_QUANTIZED_16BIT_LSTM
    • ANEURALNETWORKS_RANDOM_MULTINOMIAL
    • ANEURALNETWORKS_REDUCE_ALL
    • ANEURALNETWORKS_REDUCE_ANY
    • ANEURALNETWORKS_REDUCE_MAX
    • ANEURALNETWORKS_REDUCE_MIN
    • ANEURALNETWORKS_REDUCE_PROD
    • ANEURALNETWORKS_REDUCE_SUM
    • ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR
    • ANEURALNETWORKS_ROI_ALIGN
    • ANEURALNETWORKS_ROI_POOLING
    • ANEURALNETWORKS_RSQRT
    • ANEURALNETWORKS_SELECT
    • ANEURALNETWORKS_SIN
    • ANEURALNETWORKS_SLICE
    • ANEURALNETWORKS_SPLIT
    • ANEURALNETWORKS_SQRT
    • ANEURALNETWORKS_TILE
    • ANEURALNETWORKS_TOPK_V2
    • ANEURALNETWORKS_TRANSPOSE_CONV_2D
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN

Android 10 führt Updates für viele der bestehenden Operationen ein. Die Aktualisierungen beziehen sich hauptsächlich auf Folgendes:

  • Unterstützung für das NCHW-Speicherlayout
  • Unterstützung für Tensoren mit einem anderen Rang als 4 in Softmax- und Normalisierungsoperationen
  • Unterstützung für erweiterte Windungen
  • Unterstützung für Eingänge mit gemischter Quantisierung in ANEURALNETWORKS_CONCATENATION

Die folgende Liste zeigt die Operationen, die in Android 10. Für vollständige Details der Änderungen geändert werden, finden Sie OperationCode in der NNAPI Referenzdokumentation.

  • ANEURALNETWORKS_ADD
  • ANEURALNETWORKS_AVERAGE_POOL_2D
  • ANEURALNETWORKS_BATCH_TO_SPACE_ND
  • ANEURALNETWORKS_CONCATENATION
  • ANEURALNETWORKS_CONV_2D
  • ANEURALNETWORKS_DEPTHWISE_CONV_2D
  • ANEURALNETWORKS_DEPTH_TO_SPACE
  • ANEURALNETWORKS_DEQUANTIZE
  • ANEURALNETWORKS_DIV
  • ANEURALNETWORKS_FLOOR
  • ANEURALNETWORKS_FULLY_CONNECTED
  • ANEURALNETWORKS_L2_NORMALIZATION
  • ANEURALNETWORKS_L2_POOL_2D
  • ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION
  • ANEURALNETWORKS_LOGISTIC
  • ANEURALNETWORKS_LSH_PROJECTION
  • ANEURALNETWORKS_LSTM
  • ANEURALNETWORKS_MAX_POOL_2D
  • ANEURALNETWORKS_MEAN
  • ANEURALNETWORKS_MUL
  • ANEURALNETWORKS_PAD
  • ANEURALNETWORKS_RELU
  • ANEURALNETWORKS_RELU1
  • ANEURALNETWORKS_RELU6
  • ANEURALNETWORKS_RESHAPE
  • ANEURALNETWORKS_RESIZE_BILINEAR
  • ANEURALNETWORKS_RNN
  • ANEURALNETWORKS_ROI_ALIGN
  • ANEURALNETWORKS_SOFTMAX
  • ANEURALNETWORKS_SPACE_TO_BATCH_ND
  • ANEURALNETWORKS_SPACE_TO_DEPTH
  • ANEURALNETWORKS_SQUEEZE
  • ANEURALNETWORKS_STRIDED_SLICE
  • ANEURALNETWORKS_SUB
  • ANEURALNETWORKS_SVDF
  • ANEURALNETWORKS_TANH
  • ANEURALNETWORKS_TRANSPOSE

Android 9

NN HAL 1.1 wird in Android 9 eingeführt und enthält die folgenden bemerkenswerten Änderungen.

  • IDevice::prepareModel_1_1 enthält einen ExecutionPreference Parameter. Ein Fahrer kann damit seine Vorbereitung anpassen, da er weiß, dass die App lieber den Akku schont oder das Modell in schnellen aufeinander folgenden Aufrufen ausführt.
  • Neun neue Operationen wurden hinzugefügt: BATCH_TO_SPACE_ND , DIV , MEAN , PAD , SPACE_TO_BATCH_ND , SQUEEZE , STRIDED_SLICE , SUB , TRANSPOSE .
  • Eine Anwendung kann festlegen , dass 32-Bit - Berechnungen Schwimmers 16-Bit - Schwimmerbereich unter Verwendung betrieben werden können und / oder Präzision durch Einstellen Model.relaxComputationFloat32toFloat16 zu true . Die Capabilities Struktur hat das zusätzliche Feld relaxedFloat32toFloat16Performance so dass der Fahrer seine entspannte Leistung Rahmen mitteilen.

Android 8.1

Die erste Neural Networks HAL (1.0) wurde in Android 8.1 veröffentlicht. Weitere Informationen finden Sie /neuralnetworks/1.0/ .