Konsumelektronikgeräte wie intelligente Lautsprecher haben die Leistungsfähigkeit des maschinellen Lernens (ML) unter Beweis gestellt (Bild 1). Allerdings haben Sie auch Bedenken rund um die Gewährleistung der Privatsphäre ausgelöst und somit eine zweite Welle von Designs losgetreten, die möglichst viele Bestandteile der KI auf dem Gerät selbst enthalten.

Bild 1: Was maschinelles Lernen kann, haben zuallererst intelligente Lautsprecher bei der Spracherkennung gezeigt. Doch KI hält nun auch Einzug in andere Embedded-Systeme.

Bild 1: Was maschinelles Lernen kann, haben zuallererst intelligente Lautsprecher bei der Spracherkennung gezeigt. Doch KI hält nun auch Einzug in andere Embedded-Systeme. NXP

Während das Training der KI-Modelle häufig auf Hochleistungsservern oder in der Cloud stattfindet, lässt sich die Inferenzphase, in der reale Daten auf ein trainiertes Modell angewendet werden, jetzt auch auf Embedded-Systemen mit einem sehr geringen Verlust an Genauigkeit und Leistung durchführen. Dies ist auf Optimierungen in der Hard- und Software zurückzuführen. Mittlerweile ist diese Technologie wesentlich besser verstanden und ihr Einsatz ist nicht mehr nur auf die Erkennung von Geräuschen und Sprache beschränkt. KI-gestützte Anwendungen fließen jetzt in alle Arten von Embedded-Systemen ein, von prädiktiver Wartung über die intelligente Szenenauswertung in Überwachungskameras bis hin zur Verbesserung der Sicherheit von Fahrzeugen.

KI setzt leistungsstarke Techniken zur Bewältigung von Problemen ein, die mit herkömmlichen Software-Algorithmen nur schwer zu lösen sind. Jedoch stellt das Tempo des Wandels auf diesem Gebiet eine Herausforderung dar. Lösungen, die am Anfang eines typischen Projekts sinnvoll erscheinen, werden schon nach kurzer Zeit durch bessere Methoden in den Schatten gestellt, die namhafte und gut finanzierte Forschungsgruppen erarbeitet haben. Auf dem Gebiet der Sprachverarbeitung beispielsweise hat eine Arbeitsgruppe von Google Ende 2018 das sogenannte BERT-Paket veröffentlicht.

Durch die so gewonnenen Innovationen und die Nutzung einer Reihe von Modulen anderer Teams ließen sich die Textanalysefähigkeiten von Computern drastisch verbessern. Innerhalb eines Jahres erschienen weitere Bibliotheken wie die XLNet RoBERTa der Carnegie Mellon University, welche in Zusammenarbeit mit Facebook und der University of Washington erstellt wurde und weitere beeindruckende Fortschritte in puncto Geschwindigkeit und Genauigkeit eröffnete.

Open-Source-Software für KI-Entwicklung

Einen Schlüsselaspekt in der KI-Entwicklung der letzten zehn Jahre stellt die Open-Source-Software dar, die von führenden Arbeitsgruppen in der Forschung und Entwicklung von neuronalen Netzwerken erarbeitet wurde. So hat Google beispielsweise TensorFlow im Jahr 2015 als Framework veröffentlicht, welches für eine breite Palette von Deep-Learning-Anwendungen heranziehbar ist. PyTorch, ein bei Facebook entstandenes Open-Source-Projekt, eröffnet eine weitere Option, mit deren Hilfe Entwickler Modelle für ML wesentlich besser als bisher an ihre speziellen Bedürfnisse anpassen können. Durch diese Frameworks können Entwickler von Embedded-Systemen von den Dollar-Millionen profitieren, die führende Unternehmen für Forschung und Entwicklung auf dem Gebiet des maschinellen Lernens für die Einführung neuer Technologien in ihre eigenen Produktpaletten und Dienstleistungen ausgegeben haben.

Obwohl die Open-Source-Frameworks für ML Standardressourcen für die Entwickler von Embedded-Systemen bereitstellen, ist deren Einsatz in realen Projekten alles andere als einfach. Die Frameworks sind leicht zugänglich und stehen über Websites wie Github zum Download bereit. Aber die Realisierung einer praxisgerechten Entwicklungsumgebung aus dem Quellcode und das Erreichen eines Punktes, an dem Entwickler Produktivität zeigen, erfordern Zeit und Fähigkeiten, die viele Teams nicht haben.

Die Fähigkeit zu experimentieren ist ein Schlüsselfaktor für eine erfolgreiche KI-Entwicklung. Das wirkt sich natürlich kritisch auf die Zeit aus, die dafür aufzuwenden ist, um ein Framework einzurichten und zum Laufen zu bekommen. Die Unterschiede zwischen den bekannten KI-Frameworks können durchaus subtil sein. Für ein Team, das versucht, eine geeignete Strategie für die Auswahl des richtigen Frameworks gleich beim ersten Anlauf zu entwickeln, kann sich das schwierig gestalten. Ein Framework bietet möglicherweise Vorteile für bestimmte Szenarien.

PyTorch verwendet beispielsweise dynamische Grafikdarstellungen von Berechnungen, die die Spontanabstimmung erleichtern. Eine solche Abstimmung erweist sich als besonders vorteilhaft, wenn sie auf rekurrente neuronale Netzwerke zum Streamen von Daten, die beispielsweise von Mikrofonen und anderen analogen Sensoren stammen können, angewendet wird. PyTorch ist jedoch für die Verwendung mit der Programmiersprache Python konzipiert, während TensorFlow für die Integration mit anderen Sprachen wie C++ und Java zu bevorzugen ist.

Herausforderung ML in Embedded-Systemen

Bild 2: Der als Open-Source verfügbare Glow-Compiler durchläuft eine Reihe von Schritten, um einen zielspezifischen Maschinencode zu erstellen. NXP realisiert damit Inferenzfunktionen für i.MX-RT-Crossover-MCUs.

Bild 2: Der als Open-Source verfügbare Glow-Compiler durchläuft eine Reihe von Schritten, um einen zielspezifischen Maschinencode zu erstellen. NXP realisiert damit Inferenzfunktionen für i.MX-RT-Crossover-MCUs. NXP

Ein zentrales Problem bei Umgebungen wie TensorFlow besteht darin, dass diese in erster Linie für die Ausführung in einer Linux-Umgebung geschrieben wurden. Eine Portierung auf Plattformen, die häufiger in der Embedded-Entwicklung zum Einsatz kommen wie zum Beispiel Windows, ist möglich. Doch sie setzt grundlegende Kenntnisse des Quellcodes innerhalb des Frameworks voraus, wenn der Entwickler Versionen erstellen will, die ordnungsgemäß kompiliert und ausgeführt werden. Oft lässt sich das Problem dadurch lösen, dass das Framework in einer virtuellen Linux-Maschine ausgeführt wird. Dies erschwert jedoch die Integration mit anderen Softwareentwicklungen.

Der Fokus auf Linux in wichtigen Frameworks wirft ein weiteres Problem für Entwickler auf, die KI auf Embedded-Systemen implementieren wollen. Die TensorFlow-Lite-Variante des führenden KI-Frameworks bietet zwar Optimierungen für den Embedded-Einsatz, doch die Kernfunktionen des Frameworks für maschinelles Lernen wurden ursprünglich für die Bereitstellung auf Servern und nicht für Zielarchitekturen entwickelt, die nicht nur mit deutlich weniger Ressourcen, sondern auch mit einer Vielzahl von Prozessorarchitekturen zurechtkommen müssen. Skalierbarkeit spielt aber für viele Benutzer eine wichtige Rolle, wenn preisgünstige Implementierungen auf MCUs für den Massenmarkt das Ziel sind. Leistungsfähigere Plattformen hingegen unterstützen komplexere Applikationen.

Die Ausgabedaten eines typischen KI-Frameworks basieren auf einem Modell, das eine binäre Laufzeit benötigt, um zu funktionieren. Dieser laufzeitbasierte Ansatz eignet sich für den typischen Einsatz in Clouds und auf Desktops. In MCU-basierten Embedded-Systemen, die lediglich über begrenzte Ressourcen verfügen, verursacht der Laufzeitbezug jedoch einen hohen Mehraufwand. Dies geschieht nicht zuletzt deswegen, weil die Software für eine Linux-Implementierung zu kompilieren ist. Viele MCUs verfügen nicht über die Hardware für die Speicherverwaltung und können keine vollständig Linux-basierte Laufzeit und deren Anforderungen an virtuelle Speicher und andere Dienste unterstützen. MCU-basierte KI-Systeme setzen darüber hinaus eine höhere Recheneffizienz voraus als dies eine Laufzeit-basierte Implementierung üblicherweise zulässt.

Optimierung des Zielsystems mit LLVM

Für eine Embedded-Entwicklung, die ML unterstützen soll, ist es daher wichtig, dass sich nicht nur KI-Frameworks beliebig kombinieren lassen. Ferner muss es möglich sein, dort einen direkt ausführbaren Code zu generieren, wo dies von den übergeordneten Modellen gefordert wird.

Ein Weg, dies zu realisieren – und diesen Weg hat auch NXP beschritten – besteht darin, auf andere Open-Source-Technologien wie den LLVM-Compiler (Low Level Virtual Machine) zurückzugreifen. Dieser Ansatz erlaubt es, Inferenzfunktionen auf ARM-Cortex-M-MCUs auszuführen und so von deren geringen Kosten und der niedrigen Leistungsaufnahme zu profitieren, sich gleichzeitig aber den Umstieg auf wesentlich leistungsstärkere Computerplattformen mit vielen Prozessorkernen offen zu halten.

Ein Plug-in-Ansatz für die Architektur ermöglicht die Codegenerierung aus architekturspezifischen Tools wie ARM NN. Aufgrund seiner Struktur ist LLVM geradezu dafür prädestiniert, die Herausforderungen der Bereitstellung von Code für ML auf Embedded-Hardwareplattformen zu bewältigen. Innerhalb von LLVM generieren Front-Ends für die Sprachverarbeitung Code in einer architekturneutralen Zwischendarstellung (IR, Intermediate Representation). Projektspezifische Back-End-Algorithmen können dann diesen IR-Code übernehmen und in eine Form umwandeln, die am besten für das Zielsystem geeignet ist.

Obwohl LLVM vielleicht für seinen „Wow-Effekt“ in C-Front-Ends bekannt ist, kann es direkte Unterstützung für Machine-Learning-Modelle bieten. Ein Beispiel dafür ist der von Facebook entwickelte Glow-Compiler (Bild 2). Glow wandelt das von einem Machine-Learning-Framework erstellte Datenflussdiagramm auf sehr effiziente Weise in einen LLVM-IR-Code um, ohne dass es die herkömmlichen Schritte zur Generierung und Kompilierung von C-Code benötigt.

Ein in der LLVM-Umgebung laufendes Optimierungs-Modul (Optimizer) stellt sicher, dass effizienter Code erzeugt wird, indem der IR-Code auf Muster hin analysiert wird, welche am besten mit der Pipeline und der Anordnung von Rechenkernen im Zielprozessor übereinstimmen. Dadurch wird es möglich, eine Anpassung auf eine Vielzahl von Zielprozessoren zu erreichen. Viele Embedded-Prozessoren bieten mittlerweile eine breite Palette von Coprozessoren und Beschleunigermodulen wie zum Beispiel SIMD-Einheiten (Single-Instruction Multiple-Data).

Diese ermöglichen die parallele Ausführung vieler Integer-Arithmetik-Operationen in nur einem Taktzyklus. Obwohl ursprünglich in erster Linie für die Multimediaverarbeitung entwickelt, tragen Codeoptimierungstechniken dazu bei, auch bei KI-Modellen einen hohen Leistungsdurchsatz sicherzustellen. Durch die starke Verbreitung von KI werden Beschleuniger entwickelt, welche noch besser an die Tensorarithmetik angepasst sind, die solchen Aufgaben zugrunde liegt. Durch die Verwendung eines LLVM-basierten Back-Ends gestaltet es sich einfach, Universalprozessoren wie auch solche mit dedizierten Beschleunigerfunktionen als Zielsystem zu bedienen.

Integrierte Entwicklungsumgebung

Entwickler von Embedded-Systemen können sogar noch weitergehen, indem sie die Integration von Unterstützung für KI-Frameworks mit Back-End-Codegenerierung in einer einzigen Entwicklungsumgebung nutzen. Zahlreiche Forschungsprojekte haben gezeigt, dass in Deep-Learning-Pipelines ein erheblicher Spielraum für arithmetische Optimierungen vorhanden ist. Das Training wird häufig auf Gleitkommaprozessoren mit hoher Auflösung durchgeführt, da diese Darstellung gut zu den Gradienten-basierten Algorithmen passt. Diese kommen zum Einsatz, um Änderungen der Neuronengewichtung über das Netzwerk zu verbreiten.

In der Praxis kommen Inferenzfunktionen mit einer deutlich geringeren Auflösung aus. Einige Experimente haben gezeigt, dass die Reduzierung einer signifikanten Anzahl von Operationen auf 8-Bit-Integerzahlen oder sogar einfache binäre oder ternäre Multiplikationen zu einer Vorhersagegenauigkeit des trainierten Modells führt, die praktisch nicht von der Gleitkommaimplementierung zu unterscheiden ist, aber mit massiven Einsparungen bei Kosten und Leistungsbedarf einhergeht.

Eine integrierte Entwicklungsumgebung macht es wesentlich einfacher, die Implementierung im Laufe des Projekts abzuwandeln, und das mit einem hohen Maß an Flexibilität bei der Umsetzung einzelner Teile des Modells. In einem System, in dem die Akkulaufzeit wichtig ist, lassen sich beispielsweise einige Teile der Anwendung so kompilieren, dass sie auf einer energiesparenden MCU ausführbar sind. Dies könnte ein stark vereinfachtes Modell sein, welches nur grundlegende Inferenzfunktionen ausführt, um zu bestimmen, ob ein Schwellenwert erreicht wurde, bevor eine zweite, komplexere KI-Pipeline aktiviert wird, die eine eingehendere Analyse durchführt.

Schichten in KI-Modellen

Innerhalb eines vollständigen KI-Modells wird es zahlreiche Arten von Schichten geben. Manche lassen sich gut auf Hardware mit bestimmten Beschleunigern abbilden, während andere zu einer allgemeineren Architektur passen. Beispielsweise wird sich eine Faltungsschicht oft ausgezeichnet mit einem Beschleuniger unter intensiver Nutzung von SIMD-Modulen decken. Pooling und vollständig vernetzte Schichten können den Einsatz eines anderen Prozessors bedingen. Eine einheitliche Entwicklungsumgebung, die eine direkte Kompilierung auf eine Vielzahl von Zielsystemen ermöglicht, erleichtert es den Entwicklern, einzelne Schichten auf die am besten geeigneten Module im Bereitstellungsziel zu verteilen und dieses Ziel auf Kosten und Leistungsbedarf abzustimmen. Das optimierende Back-End stellt dann sicher, dass für jede Schicht der effizienteste Code verfügbar ist.