KI auf GPUs - das muss nicht immer sündhaft teure Grafikkarten und immensen Energieverbrauch bedeuten. NVIDIA geht seit einiger Zeit in Richtung kleinerer Systeme, sicher auch aufgrund der Konkurrenz durch die Mikrocontrollerhersteller. In diesem Artikel wollen wir einen Blick auf den Jetson Nano werfen. Natürlich gehört auch eine kleinen Demo-Anwendung dazu.

Der Markt für KI-Beschleunigung in Embedded-Systemen ist im Fluss: Unternehmen wie Canaan und Maxim
 Integrated kämpfen mit harten Bandagen um die Vorherrschaft; und auch ARM hat mit der Ankündigung des Cortex M52 einen Gladiator in diese Arena getrieben. Ziel ist durch die Bank das Anbieten von kleinen KI-Systemen, die an der viel besungenen Egde grundlegende KI-Aufgaben ohne Verbindung zum Internet erledigen. Dies führt zu einer wesentlich stabileren Systemarchitektur, weil die ML- beziehungsweise KI-Aufgaben dann auch bei Verlust der Verbindung zum Mutter-Server weiterbearbeitet werden können. Mit der Jetson-Serie versucht NVIDIA seit einiger Zeit, in diesem Marksegment mitzuspielen.

Abonnieren
Tag-Benachrichtigung zu Embedded & AI jetzt abonnieren!


Im Interesse der didaktischen Ehrlichkeit sei angemerkt, dass eigene Platinendesigns mit diesen Systemen schon wegen der extremen Bandbreite beim Zugriff auf den DDR-Arbeitsspeicher für kleinere Unternehmen nicht wirklich handhabbar sind. NVIDIA ist sich dieser Problematik bewusst. Auf der unter bereitstehenden Portfolio-Übersicht, die dem Elektroniker einen Überblick über das gesamte Jetson-Ökosystem anbietet, finden sich deshalb auch verschiedene „Compute cards“, so wie der in Bild 1 gezeigte Jetson TX2.
 

Bild 1. Die Nutzung dieses vorgefertigten Moduls erleichtert die Integration des Jetson in hauseigene Schaltungen erheblich.

Angemerkt sei außerdem noch, dass das von NVIDIA aufgrund der Dominanz im GPU-Bereich gut ausgebaute Drittanbieter-Ökosystem mittlerweile auch die Jetson-Produktpalette für sich entdeckt hat. Unter findet sich eine Liste verschiedenster Drittanbieter-Produkte, deren Integration in eine hauseigene Lösung sehr viel Entwicklungszeit (man denke beispielsweise an Gehäuse-Design und Auswahl von Kamera und Co.) einsparen kann.

Inbetriebnahme des Systems

Zum „Quereinstieg“ bietet NVIDIA das in Bild 2 (neben einem Raspberry Pi und einem Orange Pi 5+) gezeigte Jetson Nano Developer Kit an. Zum Zeitpunkt der Drucklegung dieses Artikels beträgt der OEMSecrets-Bestpreis (siehe ) 155 €. Das ist zwar etwas teurer als ein Raspberry Pi, doch ist die NVIDIA-Technologie besser in das allgemeine KI-Ökosystem eingebunden. Beim Kauf des NVIDIA Jetson Nano ist es empfehlenswert, ein Netzgerät mitzubestellen, das einen DC-Hohlstecker mit den gebräuchlichen Maßen 5,5/2,1 mm aufweist. In den folgenden Schritten verwendet der Autor ein MeanWell-Fabrikat (GST25E05-P1J).
 

Bild 2. Der Jetson, neben einem Raspberry Pi 5 und einem OrangePi 5 Plus.

Bei sorgfältiger Betrachtung des Systems (siehe auch Bild 3) fällt auf, dass es sich um ein zweiteiliges Produkt handelt. Neben dem Träger-Board, das die diversen Schnittstellen exponiert, findet sich das eigentliche Rechenmodul mit dem Kühlkörper. Relevant ist, dass eine mit dem Betriebssystem ausgestattete Micro-SD-Karte in das Rechenmodul gesteckt werden muss. 

Das verbaute SoC ist ein Mehrkernsystemen, das neben dem eigentlichen KI-Beschleuniger auch vier vollwertige Arm Cortex A57-Kerne mitbringt. Daraus folgt ein an Prozessrechner erinnerndes Setup, auf dem normalerweise Embedded Linux läuft. NVIDIA empfiehlt die Verwendung einer MicroSD-Karte mit mindestens 32 GB Kapazität und einer Mindestgeschwindigkeit von UHS1. Unter findet sich die Imagedatei, die Sie - wie gewohnt - unter Nutzung eines Cardreaders auf die auserkorene Speicherkarte extrahieren.
 

Bild 3. Wer die beiden Schrauben löst, kann sein Entwicklerkit auseinandernehmen.

Für die erstmalige Inbetriebnahme ist außerdem eine USB-Maus und eine USB-Tastatur erforderlich; im Bereich der Bildschirm-Ausgabe unterstützt Jetson sowohl HDMI als auch Displayport. Dass das Anschließen eines Ethernet-Kabels ebenfalls „vernünftig“ ist, wollen wir in den folgenden Schritten als gegeben annehmen.

Problematisch erweist sich bei der Inbetriebnahme das Fehlen einer Kamera. Statt einem CCD-Sensor verbaut man im Hause NVIDIA zwei der von Raspberry Pi 4 und Co. bekannten Steckverbinder. Manche Raspberry-Pi-Kameras lassen sich direkt mit dem Jetson verbinden. Der Autor verwendet in den folgenden Schritten eine Kamera für den Raspberry Pi 2, die über ein für den Raspberry Pi vorgesehenes FPC-Kabel mit dem Port CAM0 Kontakt aufnimmt. Zu beachten ist lediglich, dass die für den Raspberry Pi 5 vorgesehene Variante des Kabels mit dem Jetson nicht kompatibel ist. Für die Positionierung der Kamera stehen in ThingiVerse verschiedene 3D-Modelle zur Verfügung, deren Ausdrucken das Leben des Entwicklers verbessert.

Wer den NVIDIA Jetson unter Nutzung des soeben erwähnten MeanWell-Netzgeräts in Betrieb nehmen möchte, muss eine kleine Anfängerfalle beachten. Der in Bild 4 gesteckt gezeigte Jumper ist im Auslieferungszustand nicht gesteckt, so dass der DC-Anschluss nicht mit der Energieversorgung verbunden ist. Beim Einstecken des Netzteils leuchtet die Status-LED nicht auf, was verwirrend sein kann.
 

Bild 4. Dieser Jumper ist von eminenter Bedeutung.

Im Rahmen des ersten Starts gilt, dass der Prozessrechner den HDMI-Bildschirm sofort einschaltet. Die Rekonfiguration der MicroSD-Karte und einige andere „Einführungsrituale“ nehmen dann etwas Zeit in Anspruch. Nach getaner Arbeit präsentiert das System einen Ubuntu-Desktop und fordert danach zur Abarbeitung des Welcome-Assistenten auf.

Im Allgemeinen handelt es sich dabei um den gewöhnlichen Ubuntu-Set-up-Assistenten, der von NVIDIA aber unter anderem um einen Schritt zum Abnicken der hauseigenen Softwarelizenzen erweitert wurde. Wichtig ist der Assistent zur Auswahl des Energiemodells: Hier ist es empfehlenswert, die ausgewählte Option beizubehalten. Sie sorgt dafür, dass der Jetson die maximale Menge an Energie entgegennimmt.

Nach der erfolgreichen Abarbeitung des Assistenten gilt jedenfalls, dass noch etwas Zeit ins Land geht, bevor das Jetson-Board gefechtsbereit ist, denn auch am Desktop erscheinen mitunter noch einige Aufforderungen zum Rebooten des Systems.

Abonnieren
Tag-Benachrichtigung zu Electronics jetzt abonnieren!

Erste Experimente

NVIDIA setzt im Jetson auf ein mehr oder weniger komplett standardkonformes Ubuntu 18.04. Der Autor konfiguriert derartige Prozessrechner gerne für den Remote-Zugriff, um sich das Wechseln zwischen der PC- und der Prozessrechnertastatur zu ersparen.

Die in Ubuntu enthaltene Settings-Applikation ist für diese Aufgabe allerdings ungeeignet, weshalb wir stattdessen im ersten Schritt sudo apt-get update und sudo apt-get upgrade zur Aktualisierung des Paketbestands ausführen. Eventuelle Abfragen sind durch Drücken von Enter zu quittieren; ein Begehr im Bezug auf den Neustart des Docker-Systems ist zu erlauben. Danach ist ein Neustart des Jetson erforderlich. Die Eingabe von sudo apt install vino stellt sicher, dass der VNC-Server gefechtsbereit ist.

Zu guter Letzt sind dann noch die folgenden Befehle erforderlich, um die Konfiguration in einen brauchbaren Zustand zu bringen. Der String thepassword ist hierbei natürlich durch ein für Ihre Installation geeignetes Passwort zu ersetzen:

 

tamhan@tamhan-desktop:~$ mkdir -p ~/.config/autostart

tamhan@tamhan-desktop:~$ cp /usr/share/applications/vino-server.desktop ~/.config/autostart

tamhan@tamhan-desktop:~$ gsettings set org.gnome.Vino prompt-enabled false

tamhan@tamhan-desktop:~$ gsettings set org.gnome.Vino require-encryption false

tamhan@tamhan-desktop:~$ gsettings set org.gnome.Vino authentication-methods "['vnc']"

tamhan@tamhan-desktop:~$ gsettings set org.gnome.Vino vnc-password $(echo -n 'thepassword'|base64)

 

Nach dem nächsten Reboot lässt sich der Jetson mit dem VNC-Client Reminna ansprechen, wenn ein Benutzer „eingeloggt“ ist. Zu beachten ist dabei allerdings, dass das Applet für den Remote-Zugriff in der Settings-Applikation nach wie vor nicht funktioniert.

Im nächsten Schritt bietet sich ein erster Test der Kameraverbindung durch Eingabe des folgenden Befehls an:

 

tamhan@tamhan-desktop:~$ gst-launch-1.0 nvarguscamerasrc ! nvoverlaysink

 

Die mit diesem primitiven Befehl aktivierbare Kamera-Preview erscheint ausschließlich auf einem physikalisch mit dem Jetson verbundenen Monitor - die per VNC mit dem Rechner kommunizierende Anlage sieht stattdessen die Terminalausgabe. Zur Beendigung des Spuks reicht es aus, mittels Control + C ein Interrupt-Event zu schicken.

Der eigentliche Kamerazugriff erfolgt dann allgemein durch die von PC beziehungsweise Workstation bekannten Methoden. Besonders interessant ist die Datei , die die Einrichtung einer Open-CV-basierten Pipeline demonstriert.

Zu ihrer Ausführbarmachung sind die folgenden Befehle erforderlich:

 

tamhan@tamhan-desktop:~$ git clone https://github.com/JetsonHacksNano/CSI-Camera

tamhan@tamhan-desktop:~$ cd CSI-Camera/

tamhan@tamhan-desktop:~/CSI-Camera$ python3 simple_camera.py

 

Das gestartete Kamera-Fenster ist dann übrigens auch über VNC sichtbar, weil es die Informationen nicht direkt in den Framebuffer der Tegra-GPU wirft.

Sollte das Kamerabild auf dem Kopf stehen, dann sorgt das Adjustieren des Parameters flip_method in der Datei für Abhilfe:

 

def show_camera():

    window_title = "CSI Camera"

    print(gstreamer_pipeline(flip_method=2))

    video_capture = cv2.VideoCapture(gstreamer_

      pipeline(flip_method=2), cv2.CAP_GSTREAMER)

    if video_capture.isOpened():

    . . .

Interaktion mit GPIO-Pins (via Python)

Systeme der künstlichen Intelligenz verlangen vom Diensthabenden einen komplett anderen Skillset, der mit klassischer Embedded-Entwicklung nicht wirklich verträglich ist.

Die praktische Erfahrung lehrt, dass fachfremde Personen mit Hintergrund im Bereich der klassischen Großrechnertechnik oft besser mit KI zurechtkommen als Embedded-Entwickler. Die in Java sehr effizient programmierende Lebensgefährtin des Autors löst KI-Aufgaben schneller – von Assembler hat sie indes nur wenig Ahnung.

Sinn dieses softwarearchitekturalen Exkurses ist die Feststellung, dass wir den GPIO-Zugriff auf dem Jetson in den folgenden Schritten absichtlich unter Python illustrieren. Ursache dafür ist, dass der Gutteil der anwenderorientierten Erzeugung von KI-Systemen unter Python erfolgt: Wer hier auf C setzt, handelt sich ein unnötiges natives Interface ein.

Die Standard-Distribution von Python bringt am Jetson keine Paketverwaltung mit, weshalb die Eingabe der Befehle sudo apt install python-pip und sudo apt install python3-pip erforderlich ist. Im nächsten Schritt bietet sich das Überprüfen der korrekten Installation der GPIO-Module an. Auch hier sind zwei Befehle erforderlich, weil die Python-Umgebungen (logischerweise) nicht wirklich zum Teilen ihres Bibliotheksschatzes befähigt sind:

 

tamhan@tamhan-desktop:~$ sudo pip install Jetson.GPIO

tamhan@tamhan-desktop:~$ sudo pip3 install Jetson.GPIO

 

Schon aus Platzgründen können wir die GPIO-API des Jetson hier nicht vollständig vorstellen. Unter findet sich eine Gruppe vorgefertigter Beispiele, die die API vollumfänglich erklären.

Für unseren kleinen Test reicht dann folgendes Programm aus:

 

import RPi.GPIO as GPIO

import time

 

output_pin = 18  # BCM pin 18, BOARD pin 12

 

def main():

    GPIO.setmode(GPIO.BCM) 

# BCM pin-numbering scheme from Raspberry Pi

    GPIO.setup(output_pin, GPIO.OUT, initial=GPIO.HIGH)

 

    print("Starting demo now! Press CTRL+C to exit")

    try:

        while True:

            GPIO.output(output_pin,  GPIO.HIGH)

            GPIO.output(output_pin,  GPIO.LOW)

            GPIO.output(output_pin,  GPIO.HIGH)

            GPIO.output(output_pin,  GPIO.LOW)

 

    finally:

        GPIO.cleanup()

 

if __name__ == '__main__':

    main()

 

Interessant ist hier vor allem, dass NVIDIA dem angehenden Jetson-Entwickler „mehrere“ Wege zur Ansprache der Pins anbietet. Wir nutzen hier die Option GPIO.BCM, die sich am Raspberry-Pi-Pinout orientiert. Lohn der Mühen ist dann das in Bild 5 gezeigte Schirmbild. Die Frequenzstabilität mag nicht besonders hoch sein, reicht aber zum Auslösen von IoT-Ereignissen mehr als aus.
 

Bild 5. Der NVIDIA Jetson produziert unter Python Rechtecksignale.

Angemerkt sei außerdem, dass die Ausführung von GPIO-Programmbeispielen ohne Superuserrechte mitunter Probleme verursacht - unter findet sich eine detaillierte Besprechung der Thematik.

Experimente mit der ML-Funktion

Die Verfügbarkeit eines vollwertigen Linux-Betriebssystems und eines (sehr schnellen) USB3-Interfaces animiert eigentlich zur Ausführung von Experimenten. Ein mögliches Beispiel wäre Stable Diffusion: In der Praxis ist es unter Nutzung eines (adaptierten) Runners möglich, den Jetson als Bildgenerator einzuspannen.

In der Praxis ist diese Vorgehensweise allerdings nicht empfehlenswert: Sowohl der mit nur 4 GB VRAM vergleichsweise kleine Grafik-Speicher als auch die kleine Zahl von „nur” 128 Kernen sorgt dafür, dass die Bild-Generierung Geduld voraussetzt. Auf Reddit finden sich Berichte von ML-Experimentatoren, die bei einer Clustergröße von 512 × 512 Pixel von bis zu fünf Stunden Rechenzeit pro Bild ausgehen.

Ähnliches gilt auch für die gerne demonstrierten „End-to-end“-Lösungen: Das Trainieren eines Modells setzt so viel Rechenleistung und Ressourcen voraus, dass NVIDIA in den meisten Tutorials die Auslagerung auf einen Desktop oder einen Großrechner empfiehlt und der Jetson dann mit den schlüsselfertigen Modellgewichten parametriert wird. Unter finden sich mehr oder weniger schlüsselfertige Beispiele, die die Leistungsfähigkeit des Jetson auf eine unbürokratische Art und Weise illustrieren.

Zur Nutzung dieser Modell-Powershow ist es erforderlich, ein NVIDIA-Softwarepaket herunterzuladen und zu deployen. In der Theorie bietet sich hier auch die Nutzung eines Docker-Containern, für mit der Container-Technik fremdelnde Personen aber alternativ das lokale Kompilieren an, was durch Eingabe der folgenden Befehle bewerkstelligt werden kann:

 

sudo apt-get update

sudo apt-get install git cmake libpython3-dev python3-numpy

git clone --recursive --depth=1 https://github.com/dusty-nv/jetson-inference

cd jetson-inference

mkdir build

cd build

cmake ../

make -j$(nproc)

sudo make install

sudo ldconfig

 

Die Frage nach der Installation der Trainingskomponenten können Sie nach Belieben beantworten. Der Autor hat sie in den folgenden Schritten verneint, um auf seiner nur 32 GB großen Micro SD-Karte etwas Speicher einzusparen.

Nach dem erfolgreichen Durchlaufen des Kompilations-Prozesses findet sich im Verzeichnis ~/jetson-inference/build/aarch64$/bin eine vergleichweise komplexe Projektstruktur, die neben diversen Binärdateien Python-Files bereitstellt. Interessant ist, dass NVIDIA hier sogar einige fertige Testbeispiele platziert.

Als Erstes wollen wir den Klassifikator verwenden - er analysiert Bilddateien und stellt fest, was auf dem angelieferten Bild zu sehen ist:

 

tamhan@tamhan-desktop:~/jetson-inference/build/aarch64/bin$ ./imagenet.py images/orange_0.jpg images/test/output_0.jpg

 

Die erstmalige Ausführung dieses Befehls nimmt dabei etwas mehr Zeit in Anspruch, weil die bereitgestellten Module für die Bedürfnisse des Jetson-Systems optimiert werden. Danach erfolgt die Ausgabe der Bild 6 gezeigten Timinginformationen.
 

Bild 6. Das mit dem Jetson ausgelieferte Demoprogramm zeigt sich auf Kommandozeilen-Ebene nur wenig kommunikativ.

Zur eigentlichen Sichtbarmachung der vom ML-Prozess angelieferten Ergebnisse müssen Sie stattdessen die generierte Bilddatei ansehen - die Eingabe des folgenden Befehls öffnet den Ausgabe-Ordner direkt im Nautilus-Dateimanager:

 

tamhan@tamhan-desktop:~/jetson-inference/build/aarch64/bin$ nautilus images/test/output_0.jpg

Bild 7. Die Obst-Erkennung gelang dem NVIDIA-Beispielprogramm vorbildlich.

Lohn der Mühen ist das Erscheinen des in Bild 7 gezeigten Schirmbilds.

Analyse des Python-Files

Als nächstes Element wollen wir einen kurzen Blick auf das soeben verwendete Beispielprogramm werfen. Sein Quellcode lässt sich im Gedit-Editor durch Eingabe des folgenden Befehls in der Kommandozeile öffnen:

 

tamhan@tamhan-desktop:~/jetson-inference/build/aarch64/bin$ gedit imagenet.py

 

Schon auf den ersten Blick fällt auf, dass die hier verwendete Bibliothek mit dem klassischen ImageNet verwandt ist - im Jetson-Starterkit verpackt NVIDIA verschiedene weit verbreitete Systeme der künstlichen Intelligenz.
 

Der Kern des Programmbeispiels ist dabei eine Endlosschleife, die den Eingangs-Strom um ein Bild erleichtert, dieses dem ML-Modell vorwirft und zu guter Letzt die „errechneten“ Informationen ausgibt (Listing 1).

Die Initialisierung der Datenströme und des zu verwendenden Modells erfolgt weiter oben nach folgendem Schema:

 

net = imageNet(args.network, sys.argv)

input = videoSource(args.input, argv=sys.argv)

output = videoOutput(args.output, argv=sys.argv)

font = cudaFont()

 

Interessant ist dann noch die Beschaffung beziehungsweise Bevölkerung des Parameters network, der den Namen des zu verarbeitenden Modells anliefert. NVIDIA setzt hierbei auf die ArgParser-Klasse, die normalerweise auf die Verarbeitung von über die Kommandozeile angelieferten Parameter spezialisiert ist.

Im Fall der hier vorliegenden Deklaration wird ein Default-Wert eingeschrieben, der normalerweise das GoogLeNet aktiviert und lädt:
 

parser.add_argument("--network", type=str, default="googlenet", help="pre-trained model to load (see below for options)")

 

Exkurs: „Geführte“ Online-Fortbildung samt Zertifikation

Die Erfolge der Sowjetunion in diversen arabischen und afrikanischen Staaten lassen sich unter anderem auf die enge Ausbildungspartnerschaft zurückführen - womit der Kadett lernt, das setzt er später gerne im Beruf ein. NVIDIA ist sich dieser Situation offensichtlich bewusst, weshalb mit Jetson AI Certification ein zweigeteilter und komplett kostenloser ML-Kurs wie in der Bild 8 zu sehen zur Verfügung steht. Hervorzuheben ist dabei außerdem noch, dass das erfolgreiche Absolvieren von NVIDIA sogar mit einem Zertifikat honoriert wird.

Sollten Sie daran Interesse haben, empfiehlt sich der Besuch von . Dort finden Sie weitere Informationen dazu, wie man die Teilnahme am NVIDIA-Fortbildungskurs am effizientesten gestaltet.
 

Bild 8. Zweigleisiger Bildungsweg à la NVIDIA! (Bildquelle: NVIDIA)

Vorteile durch Linux

Mit dem Jetson schickt NVIDIA ein Zwitterwesen ins Rennen, das sich im Bereich der künstlichen Intelligenz zwischen alle Stühle setzt. Einerseits gilt, dass dedizierte Low-Power-Mikrocontroller wie der Maxim MAX78000 einen wesentlich geringeren Energieverbrauch bieten. Andererseits leiden solche Controller darunter, dass sie keine Unterstützung für CUDA bieten: Ein auf dem PC oder im Großrechner-Bereich lauffähiges Modell benötigt deshalb Adaption, bevor es sich unter Nutzung dieser Chips im IoT verwenden lässt.

Andererseits ist der NVIDIA Jetson keine vollwertige GPU: Das Modul ist sowohl vom Energieverbrauch als auch von der unterstützten CUDA-Variante (CUDA 11 läuft nicht) kein vollwertiger Ersatz für eine RTX 4000.

Unterm Strich gilt, dass sich ein Deployment auszahlt, wenn ein am Rechner oder Großrechner problemlos funktionierendes Modell aufwandsarm mobilisiert werden muss und es mit den vom Jetson angebotenen Ressourcen auskommt. Wegen des Linux-Betriebssystems gilt, dass dies für einen Data Scientist vergleichsweise wenig Aufwand bei der Umstellung bedeutet - die Einarbeitung in die von Maxim und Co. verwendeten Embedded-APIs erforder erheblich mehr Mannstunden. Die höheren Kosten der Hardware lassen sich so, insbesondere in kleineren Serien, schnell und unbürokratisch amortisieren.


Dieser Artikel (230740-02) erschien in Elektor März/April 2024. Übersetzt von Rolf Gerstendorf.


Sie haben Fragen oder Kommentare?

Gerne können Sie sich an den Autor unter der E-Mail-Adresse tamhan@tamoggemon.com oder an die Elektor-Redaktion unter der E-Mail-Adresse redaktion@elektor.de wenden.