1 Punkte von GN⁺ 2024-10-17 | 2 Kommentare | Auf WhatsApp teilen
  • Das Ausführen von NPU-Benchmarks auf dem Qualcomm-Arm-basierten SoC des Microsoft Surface Pro 11th Edition zeigt einen deutlich geringeren Durchsatz als die von Windows-AI-PCs beworbene Beschleunigungsleistung
  • Der Test ist so aufgebaut, dass mit Onnx Runtime und dem Qualcomm-QNN-Execution-Provider große MatMul-Operationen ausgeführt werden, ähnlich den rechenintensiven Layern von Transformer-Modellen
  • In den Beispielergebnissen erreicht die CPU 821 Gigaops/s, die NPU 225 Gigaops/s in einer quantisierten Konfiguration mit Float-Ein-/Ausgabe und 573 Gigaops/s in einer Konfiguration mit zusätzlicher 8-Bit-Ein-/Ausgabe
  • Die 573 Gigaops/s der NPU entsprechen 1,3 % der in den Marketingunterlagen des Microsoft Surface Pro 11th Edition genannten 45 Teraops/s; führt man dasselbe Modell auf einer Nvidia Geforce RTX 4080 Laptop GPU aus, ergeben sich 3,2 ms und 2.160 Gigaops/s
  • Die aktuellen Ergebnisse gelten mit Stand 2. Oktober 2024; Verbesserungen bei Software, Frameworks und Treibern könnten die Latenz noch senken, doch im aktuellen Benchmark ist die CPU schneller als die NPU

Ziel des Qualcomm-NPU-Benchmarks auf dem Surface

  • Microsoft verkauft Surface-Tablets mit Qualcomm-Arm-basiertem SoC als Windows-AI PC und bewirbt sie damit, Machine-Learning-Modelle schneller und effizienter ausführen zu können
  • Useful Sensors bewertet Qualcomm-Hardware und die NPU grundsätzlich positiv und hat Zeit und Ressourcen investiert, um die eigene Third-Party-App auf diese Plattform zu portieren
  • Da es nur wenige Codebeispiele oder Benchmarks gibt, die externen Entwicklern zeigen, wie sie schnell zu Ergebnissen kommen, wurde die tatsächlich beobachtete Leistung als kleines unabhängiges Projekt veröffentlicht
  • Die gemessene Leistung lag deutlich unter den Erwartungen; da dieselbe Hardware auf anderen Plattformen wie Android bereits effektiv gearbeitet hat, bleibt Raum für künftige Verbesserungen durch Änderungen an Anwendungen, Frameworks und Treibern

Laufzeitumgebung und Installationsbeschränkungen

  • Für den Test wird unter Windows ein Python-Skript verwendet
    • Mit Stand 2. Oktober 2024 unterstützt Python aus dem Microsoft Store die Arm-Architektur nicht und ist daher ungeeignet, um die für den Zugriff auf die Qualcomm-NPU nötigen Pakete auszuführen
    • Für die Ergebnisse wurde die Python-3.11.9-Arm64-Installation verwendet
  • Da es noch keine vorgefertigten Onnx-Pakete für Windows on Arm gibt, werden CMake und der Visual-Studio-Compiler benötigt
    • CMake wird mit winget install cmake installiert
    • Verwendet wird Visual Studio Community Edition; bei der Installation wird der Workload Desktop C++ Development ausgewählt
  • Die Python-Pakete werden im Repository-Ordner mit py -m pip install -r requirements.txt installiert
    • Der Onnx-Branch ist eine Version, in die die Korrektur für die Kompilierung des offiziellen py-Launchers auf Onnx 1.16 zurückportiert wurde
    • Qualcomm Onnx Runtime erzeugt mit aktuellem Onnx den Fehler Unsupported model IR version, daher wird diese Kombination verwendet
    • Für das Qualcomm-Onnx-Runtime-Paket wurde ein Nightly-Build verwendet

Benchmark-Ausführung und Interpretation der Ausgabe

  • Der Benchmark wird mit py benchmark_matmul.py ausgeführt
  • Onnx Runtime gibt beim ersten Lauf viele Logs aus
    • Beispielsweise erscheint eine cpuinfo-Meldung, dass das Chipmodell Snapdragon(R) X 12-core X1E80100 @ 3.40 GHz nicht erkannt wird
    • Außerdem werden Logs zur Finalisierung und zum Abschluss des Graphen ausgegeben
  • Die eigentlichen Benchmark-Ergebnisse werden am Ende angezeigt
    • NPU quantized compute, float I/O accuracy difference is 0.0100
    • NPU quantized compute and I/O accuracy difference is 0.0060
    • CPU took 8.42ms, 821,141,860,688 ops per second
    • NPU (quantized compute, float I/O) took 30.63ms, 225,667,671,183 ops per second
    • NPU (quantized compute and I/O) took 12.05ms, 573,475,650,364 ops per second
  • Die ersten beiden Zeilen zeigen die Genauigkeitsdifferenz, um zu prüfen, ob CPU- und NPU-Ergebnisse numerisch zueinander passen
  • Die letzten drei Zeilen zeigen die Wall-Clock-Zeit für die vollständige Ausführung des Modells sowie den daraus berechneten Durchsatz in Operationen pro Sekunde

Gemessenes Modell und Quantisierungsmethode

  • Der Benchmark ist so ausgelegt, dass er sechs große Matrixmultiplikationen nachbildet, ähnlich den zeitaufwendigen Layern in Transformer-Modellen wie OpenAI Whisper
    • Die Eingabeform ist (6, 1500, 256) X (6, 256, 1500)
    • Die Ausgabeform ist (6, 1500, 1500)
    • Das Modell besteht aus einem einzelnen MatMul-Knoten mit zwei Eingaben und einer Ausgabe
  • Das Modell wird zur Laufzeit im Onnx-Modell-Framework erzeugt und anschließend an Onnx Runtime übergeben
  • Das Basismodell ist eine reine Float-Version und wird nur auf der CPU ausgeführt
  • Für eine effektive Ausführung auf der NPU sind in der Regel quantisierte Modelle erforderlich; float16 wird nur eingeschränkt unterstützt
  • Der erste NPU-Ansatz verwendet die offizielle ORT-Methode quantize_static()
    • Der Einfachheit halber bleiben Eingabe- und Ausgabe-Tensoren 32-Bit-Float
    • Zur Laufzeit werden am Anfang und Ende des Graphen Konvertierungen durchgeführt, der restliche Rechenpfad läuft in 8 Bit
  • In dieser Konfiguration waren die Konvertierungsoperationen auf der NPU sehr langsam; in npu_quant_profile.csv machten sie mehr als 75 % der gesamten Zeit aus
  • Der zweite Ansatz erzeugt programmatisch einen äquivalenten Modellgraphen mit 8-Bit-Eingaben und -Ausgaben
    • Diese Variante quantized compute and I/O ist in der Regel etwa dreimal schneller als die Version mit Float-I/O
    • Im Profiling entfällt der Großteil der Zeit erwartungsgemäß auf die Matrixmultiplikation

Variablen, die bei der Leistungsmessung berücksichtigt wurden

  • Es wurde berücksichtigt, ob der Workload compute-bound ist, indem eine stärker quadratische Matrixform gewählt wurde
    • Moderne Transformer-Modelle basieren im Gegensatz zu älteren Convolution-Modellen auf großen Matrixmultiplikationen
    • Wenn Layer eher Matrix-Vektor-Multiplikationen ähneln, nimmt die Wiederverwendung von Gewichten ab und das Nachladen von Werten aus dem DRAM kann zum Flaschenhals werden
    • In der ursprünglichen tiny-Whisper-Matrix war die k-Dimension 64; in diesem Benchmark wurde sie auf 256 erhöht, um mehr Spielraum für SIMD-Optimierungen zu schaffen
  • Die Energieeinstellungen wurden auf maximale Leistung ausgerichtet
    • In Windows sollten alle Energieoptionen auf Best Performance stehen
    • Der Benchmark wurde ausgeführt, während das Tablet am Strom angeschlossen war
    • Die Sitzungsoption htp_performance_mode der Qualcomm Onnx Runtime wurde auf sustained_high_performance gesetzt, da dies in den Tests die geringste Gesamtlatenz ergab
  • Die Modellstruktur wurde zur einfacheren Interpretation auf eine einzelne Matrixmultiplikation beschränkt
    • Mehrere Layer, Convolution und statische Gewichte wären ebenfalls möglich gewesen, aber um die in LLMs und modernen Modellen weit verbreitete Transformer-Struktur abzubilden, wurde ein einzelnes MatMul mit dynamischen Eingaben gewählt
  • Die Möglichkeit einer Fehlkonfiguration bleibt bestehen
    • Verwendet werden vorzeichenlose 8-Bit-Quantisierung und qdq-Elemente im Graphen
    • Es wurde versucht, den Best Practices der Dokumentation zu folgen, dennoch könnte man schnelle Pfade in Treibern oder der Accelerator-Implementierung verfehlt haben
  • Auch die Auswahl möglicher APIs für den Zugriff auf AI-Beschleunigung unter Windows wurde betrachtet
    • DirectML scheint nur GPU-Zugriff zu unterstützen
    • OpenVino scheint auf der betreffenden Arm-Hardware nicht zu laufen
    • Auch bei direkter Verwendung des Qualcomm QNN SDK wurden ähnliche Leistungswerte beobachtet
    • TensorFlow Lite unterstützt Windows for Arm nicht
    • In dieser Untersuchung und den Tests erscheint Onnx als das Framework, das sowohl von Microsoft als auch von Qualcomm unterstützt wird und am besten geeignet ist, NPU-Beschleunigung zu erreichen

Interpretation der Ergebnisse

  • Die Ergebnisse gelten mit Stand 2. Oktober 2024 und wurden auf einem Microsoft Surface Pro 11th Edition gemessen
    • Das SoC ist ein Snapdragon(R) X 12-core X1E80100 @ 3.40 GHz
  • Auch ohne Float-Konvertierungen ist das NPU-Ergebnis langsamer als das der CPU
    • Aus Sicht eines Beschleunigers ist das nicht ideal
    • Ein möglicher Vorteil bei Energieeffizienz oder Dauerleistung wird damit jedoch nicht ausgeschlossen
  • Die gemessene maximale NPU-Leistung von 573 billion ops/s entspricht 1,3 % der in den Marketingunterlagen zum Microsoft Surface Pro 11th Edition genannten 45 trillion ops/s
  • Dasselbe Modell benötigt auf einer Nvidia Geforce RTX 4080 Laptop GPU 3,2 ms
    • Das entspricht 2.160 billion ops/s
    • Das ist fast der vierfache Durchsatz des gemessenen NPU-Werts im Surface

2 Kommentare

 
bungker 2024-10-18

Ich dachte, dass die Ryzen-NPU etwas schneller als die CPU ist, aber dadurch ist meine Begeisterung für Snapdragon komplett verflogen.

 
GN⁺ 2024-10-17
Meinungen auf Hacker News
  • Den Ergebnissen nach sieht es insgesamt so aus, als würden die Rechenressourcen nicht gut genutzt. 8,4 ms auf der CPU und 3,2 ms auf der GPU sind ein viel zu kleiner Unterschied; hier hätte man wohl eher einen Faktor von 10 bis 20 erwartet.
    Die Ursache könnte onnxruntime sein. Es wirkt so, als würden manche Hardwareanbieter zwar Recheneinheiten bereitstellen, aber noch keinen vernünftigen Support dazu liefern; man wird sehen müssen, wie schnell sich das ändert.
    Außerdem wird der Zweck einer NPU oft fälschlich als „Geschwindigkeit“ verstanden; der Kern ist niedriger Energieverbrauch. Wenn man auf Geschwindigkeit abzielt, muss man den Speicherflaschenhals beseitigen und landet am Ende bei einem ASIC mit eigenem Speicher. Die NPUs in den meisten Geräten hängen am SoC rund um die CPU und dienen dazu, KI-Berechnungen auszulagern.
    Es wäre interessant, diesen Benchmark auf CPU/NPU/GPU in einer Endlosschleife laufen zu lassen und den Stromverbrauch zu messen. Ich würde erwarten, dass die NPU am wenigsten verbraucht und auch die beste Rechenleistung pro Watt liefert.

    • Ich habe den Verdacht, dass der eigentliche Grund für NPUs vielleicht Marketing ist. Es könnte so eine Dynamik sein wie: „NVDA ist 3,3 Billionen Dollar wert? Dann packen wir auch irgendwas mit AI in unser Produkt.“
    • NPUs dienen auch stark dem Offloading. Je nach Anwendungsfall können CPU und GPU mit anderen Aufgaben beschäftigt sein; die NPU wird dann zu zusätzlicher Bandbreite, die sich nicht gegenseitig Ressourcen wegnimmt.
      Bei einem KI-Fotofilter etwa rendert wahrscheinlich die GPU die Vorschau, während die CPU mit UI und Nutzereingaben beschäftigt ist.
    • Das ist Nvidias Burggraben. Fast alles hat für CUDA optimierte Kernel, und in manchen Fällen gibt es noch Apple Accelerate.
      Apple Accelerate war praktisch der einzige Weg, auf die CPU-Matrixeinheiten vor dem M4 und auf die NPU zuzugreifen. Wenn man etwas anderes nutzen will, sollte man bereit sein, Patches für das gewählte Machine-Learning-Framework einzureichen oder Trainings- und Inferenzcode selbst zu schreiben.
    • Ich entwickle mit onnxruntime eine App in reinem C, und sie war deutlich schneller als eine ähnliche App in Python. Es gibt immer noch viel Performance herauszuholen.
      Am Ende ruft auch Python C auf, aber es ist ziemlich interessant, wie viel Leistung dabei verschwindet.
    • Es wirkt nicht so, als würde das Timing korrekt gemessen, und die üblicherweise vermarktete „Zeit“ ist oft nicht derselbe Messwert, an den Leute denken. Trotzdem sind Marketingwerte manchmal leichter zu vergleichen.
      Wenn eine GPU genutzt wird, muss man berücksichtigen, ob asynchrone Arbeit im Timing enthalten ist.
      Wenn man naiv time.time() verwendet, zeichnet die CPU nur die Zeit auf; model(input.cuda()).cuda() schiebt die Daten in den GPU-Speicher und startet die Berechnung, aber weil das asynchron ist, kann die Endzeit erfasst werden, unabhängig davon, ob das Ergebnis tatsächlich bereitsteht.
      Ohne Kenntnisse des Systems und der Hardware ist dieses Verhalten schwer zu erwarten. Nicht nur Python, sondern die meisten Sprachen sind so ausgelegt, dass sie in eine stärker optimierte Form kompiliert werden als der geschriebene Code; da es keine Sperre gibt, wird die CPU-Arbeit nicht blockiert.
      Um GPU-Arbeit tatsächlich zu messen, sollte man sich CUDA-Event-Timer ansehen. In PyTorch verwendet man dafür torch.cuda.Event(enable_timing=True).
      Zusätzlich sind Speichergröße und Layout komplex. Dieser Benchmark verwendet ein Format, das für die NPU ungünstig ist. NPUs und GPUs wollen normalerweise channels last, daher ist [1,1500,1500,6] statt [1,6,1500,1500] richtig.
      Auch 1500 und 6 sind ungünstige Zahlen und nicht gut für die NPU; wenn man bedenkt, dass solche Geräte noch neu sind, können die Performanceverluste ziemlich groß sein.
      Mehr Details habe ich unter https://news.ycombinator.com/item?id=41864828 aufgeschrieben.
  • Diese NPUs belegen eine beträchtliche Siliziumfläche, daher wäre es wirklich schade, wenn sie am Ende kaum genutzt würden. Eine Die-Analyse, bei der nur die NPU des Snapdragon X separat herausgelöst wurde, konnte ich nicht finden; bei AMD mit einem ähnlichen Ziel von etwa 50 TOPS kann man es hier sehen, und sie nimmt ungefähr die Fläche von drei High-Performance-CPU-Kernen ein.
    https://www.techpowerup.com/325035/amd-strix-point-silicon-p...

    • Ich hoffe, dass der LLM-Hype endet und wieder ein gewisses Maß an gesundem Menschenverstand und Effizienz zurückkehrt. Ich persönlich habe keine Verwendung für diese zusätzliche Hardware, „GenAI“ hilft mir überhaupt nicht und unterstützt auch keine arbeitsbezogenen Aufgaben.
      Schlimmer noch: Für die meisten Menschen scheint es ebenfalls nicht nötig zu sein, und aktuelle Umfragen zeigen sogar überwiegend Ablehnung gegenüber der KI-Durchdringung. Dafür sollte man keinen Aufpreis zahlen müssen; es sollte optional sein.
      Dann würden die Verkaufszahlen zeigen, wie wenige Menschen bereit sind, einen „AI“-Aufpreis zu zahlen, und es würde deutlich, wie übertrieben und unnötig das Ganze ist.
    • Moderne Chips müssen einen gewissen Anteil des Dies als Dark Silicon belassen. Andernfalls würden sie schmelzen oder so stark throtteln, dass sie nutzlos wären. Solche Komponenten zählen ebenfalls zu diesem Anteil.
      Der Zweck solcher Teile ist also, genutzt zu werden, aber nicht zu stark.
      Statt der NPU hätte man diese Transistoren und Die-Fläche zwar für verschiedene andere Zwecke verwenden können, aber man hätte wohl keine weiteren High-Performance-CPU-Kerne eingebaut. Das würde die Leistungsdichte zu stark erhöhen und thermische Probleme verursachen, die ohne permanentes Throttling kaum lösbar wären.
      [1] https://en.wikipedia.org/wiki/Dark_silicon
    • Ich sehe das genauso. Im Moment muss man gezielt nach einem System mit NPU suchen, deshalb habe ich noch keines; ich fürchte aber, dass sie künftig standardmäßig enthalten sein werden.
      Für Leute, die keine Modelle ausführen wollen, wirkt das wie Verschwendung, und ich frage mich, welche Möglichkeiten es gibt, sie anderweitig zu nutzen.
    • Der Snapdragon X hat weiterhin 12 Kerne, und zwar in einer homogenen Struktur mit lauter gleichen Kernen. Strix Point hat ebenfalls 12 Kerne, aber in einer 4+8-Konfiguration; auch die „kleinen“ Kerne opfern nicht so viel Leistung, dass sie wie die kleinen Kerne mancher ARM-Designs kaum eine Daseinsberechtigung hätten.
      Consumer-Software skaliert nicht bis zu diesem Grad; was könnte man also sinnvoll tun, wenn man noch mehr Transistoren der CPU zuweist?
      Das ist ähnlich wie bei Apple, die viele Video-Engines in ihre SoCs packen. Mit dem verfügbaren Transistorbudget gibt es nicht allzu viele andere sinnvolle Einsatzorte. Verbesserungen bei Single-Thread-Performance sind längst nicht mehr nur durch die Transistorzahl begrenzt, und Software ist nicht gut im Multithreading.
  • Ich dachte, der Zweck solcher Geräte sei nicht, schnell zu sein, sondern kleine Modelle mit sehr geringer Leistungsaufnahme laufen zu lassen. Ich nutze ein aktuelles AMD-Notebook mit NPU: Wenn ich die angeblich auf der NPU laufenden Videoeffekte aktiviere, ändert sich der Stromverbrauch nicht, bei Nvidia Studio Effects steigt er dagegen an.
    Die NPU scheint für sehr stark optimierte Modelle gedacht zu sein, die kleine Aufgaben erledigen, etwa Blickkontakt, Hintergrundunschärfe, automatische Korrekturmodelle, Transkription und OCR. Besonders unter Windows hatte ich den Eindruck, dass für die Rewind-Funktion Vollbild-OCR und Embeddings für die Suche laufen.

    • Besonders dann, wenn dieses Gerät ein Xilinx-FPGA ist. Das, was an den neuesten mobilen Ryzen angebunden ist, ist außerdem fünfmal schneller.
      AMD leistet derzeit hervorragende Arbeit, scheint das aber nicht groß an die Glocke zu hängen. Das hier ist besonders interessant: https://lore.kernel.org/lkml/DM6PR12MB3993D5ECA50B27682AEBE1...
      Edit: Es war kein FPGA. Wieder etwas gelernt.
    • So verstehe ich es auch. Entscheidend sind geringer Stromverbrauch und niedrige Latenz.
      Das lässt sich sehen, wenn man CoreML-Modelle unter macOS evaluiert. Die ANE braucht etwa halb so viel Zeit wie die GPU, und die GPU etwa halb so viel wie die CPU. Die tatsächlichen Faktoren hängen vom Modell ab.
    • Geringer Stromverbrauch bedeutet günstigere Tokens und führt zu erschwinglicherer und nachhaltigerer Nutzung. Darin liegt der allgemeine Vorteil für Verbraucher. Stromhungrige GPUs scheinen besser zu Forschung, kommerzieller Nutzung und Enterprise zu passen.
      Der Chip, der Nvidia gefährlich werden könnte, wird ein Chip samt Speicher sein, der billig genug ist, um ausreichend gute Modelle auf persönlichen Geräten wie Smartphones laufen zu lassen.
      Wenn die breite Öffentlichkeit den Nutzen von LLMs anerkennt und bereit ist, einen kleinen Aufpreis für Geräte zu zahlen, sehe ich die Zukunft dieser Technik im Kern in privaten Modellen, die Privatsphäre bieten.
      Die Menge an persönlichen Informationen, die Menschen bei Diensten wie ChatGPT abladen, ist erstaunlich. Auf Reddit sieht es oft so aus, als würden Süchtige von KI-Virtual-Girlfriend-Apps ihre dunkelsten Vorlieben, verletzlichen Geständnisse und sogar potenziell strafbare Gespräche an namenlose App-Firmen weitergeben.
      Auch Google weist ausdrücklich darauf hin, dass Gespräche überprüft werden können, wenn der Gemini-Verlauf aktiviert ist.
      Für komplexe Token-Vorhersagen, die größere Modelle erfordern, kann man wohl ein Cloud-LLM fragen, aber für Verbraucher muss Privatsphäre unbedingt gewährleistet sein.
      Für alltägliche persönliche Assistenten, Chats und Informationssuche braucht es meiner Ansicht nach kein Spitzen-Reasoning und keine LLM-Kunststücke.
    • Nach dem, was ich bei der Einführung der On-Device-Spracherkennung auf dem Pixel gehört habe, und nach meinen Erfahrungen nach meinem Weggang von Google mit ONNX-Workloads auf der Apple Neural Engine und der CPU, halte ich das für richtig.
      Die konkreten Schlussfolgerungen des Artikels finde ich allerdings etwas fragwürdig. Es ist Qualcomm-ONNX, und es könnte veraltet sein. Auf Android-Seite wurde viel über Qualcomms Software Engineering geschimpft.
      Die Richtung stimmt trotzdem. Die meisten KI-Beschleunigungsbehauptungen bei Consumer-Hardware sind fast durchgängig eher heiße Luft; Ausnahmen sind A) man nutzt 1P-Software oder B) jemand intern bei einem 1P-Anbieter will wirklich, dass man diese Funktion verwendet.
    • Stimmt. Allerdings möchte man solche Geräte wahrscheinlich nicht mit Python programmieren. Besonders weil es sich um neue Geräte handelt und Optimierungen vermutlich noch nicht gut portiert sind, sollte man keine gute Performance erwarten.
      Selbst mit etwas wie TensorRT wird es nicht so schnell sein wie etwas, das man von Grund auf selbst schreibt; es gibt einen Grund, warum Nvidia dafür viele Leute einsetzt. Trotzdem kommt man ziemlich nah heran und spart viel Entwicklungszeit.
      Solche Geräte sind im Allgemeinen für sich wiederholende, ähnliche Aufgaben optimiert. Deshalb könnten einige der hier gesammelten Informationen ungenau sein.
      Ich habe diese NPU-Chips nicht selbst verwendet, aber den Timings traue ich nur bedingt. Das CUDA-Timing am Ende wurde im Code sehr wahrscheinlich nicht korrekt gemessen. Timing-Messungen sind schwieriger, als man denkt.
      Die beworbene Zahl an Operationen zählt nur die direkt auf der NPU ausgeführten Operationen, während der ursprüngliche Beitrag bei den NPU- und GPU-Messungen möglicherweise auch CPU-Arbeit mit eingerechnet hat. In der Dokumentation gibt es ein Benchmarking-Tool; vermutlich wurde etwas Ähnliches verwendet, und mich würde auch interessieren, wie die Varianz nach dem Warm-up aussieht.
      Auch das Datenformat scheint falsch zu sein. Hier braucht man channels last. Die Dokumentation bestätigt das ebenfalls.
      Die Zahl 1500 wirkt ebenfalls seltsam, wodurch weitere Fehler entstehen können. Bei 1536, 2048, 256 oder kleineren Werten könnten die Ergebnisse anders ausfallen. Reale Modelle verarbeiten nicht das Bild in voller Auflösung, und wenn man die Architektur für das Modell optimiert, werden Shape-Informationen wichtig. Im Machine Learning ist Shape-Optimierung ziemlich wichtig.
      Ein schneller Blick in die Dokumentation lässt auch die Konfiguration unpassend erscheinen. Im „Model Workflow“ heißt es, dass die Daten als 8-Bit- oder 16-Bit-Fließkommawerte gewünscht werden, aber es gibt mehrere Arten von Fließkomma. PyTorchs bfloat ist nicht dasselbe wie torch.half oder torch.float16.
      Mixed Precision ist immer noch ein verwirrendes Thema; wenn solche Probleme auftreten, lohnt es sich, genauer hinzusehen. Ich würde nicht empfehlen, einfach nur den Standard-Quantisierungsprozess laufen zu lassen und es dabei zu belassen. Als Ausgangspunkt ist das gut, aber wenn „gut genug“ nicht wirklich reicht, sollte man dort nicht aufhören.
      Trotzdem halte ich diese Ergebnisse nicht für nutzlos. Sie müssen nur verbessert werden. Solche Dinge sind komplexer, als man denkt, und ein erheblicher Teil davon liegt daran, dass die Technik neu ist und die Details noch ausgearbeitet werden.
      Beim Vergleich mit CPUs oder GPUs, insbesondere CUDA, sollte man bedenken, dass dort Hunderttausende Personenstunden hineingeflossen sind und selbst in High-Level-Bibliotheken wie Python mindestens Zehntausende Personenstunden stecken. Diese Geräte sind noch nicht wirklich bereit, auf der Abstraktionsebene der Sprache genutzt zu werden, die durchschnittliche Nutzer bevorzugen; wer aber bereit ist, näher an der Hardware zu arbeiten, kann sie durchaus sinnvoll einsetzen.
      Um asynchrone GPU-Arbeit in PyTorch zu messen, sollte man CUDA-Events und torch.cuda.synchronize() verwenden, statt die Modellausgabe mit einem CPU-Timer zu umschließen.
      [1] https://www.thonking.ai/p/what-shapes-do-matrix-multiplicati...
  • Um ein Modell auf einer NPU bereitzustellen, ist erhebliche profilbasierte Optimierung nötig. Wenn man ein Modell, das auf der CPU gut läuft, ohne Optimierung für die NPU übernimmt, sind die Ergebnisse meist enttäuschend.

    • Das Schöne an CPUs ist, dass sie selbst ziemlich chaotischen Code noch mit vernünftiger Geschwindigkeit durchkauen.
    • Immer wenn ich mit Leuten gesprochen habe, die mit Dingen wie IREE oder OpenXLA arbeiten, hatte ich den Eindruck, dass allein das Verstehen und Nutzen solcher Compiler und Runtimes ein eigener Beruf ist.
  • Die Beschreibung im GitHub-Repository ist deutlich informativer als der Blog.
    Wenn man int8-Matrixmultiplikation mit onnx ausführt, liegt die Performance bei etwa 0,6 TF.
    https://github.com/usefulsensors/qc_npu_benchmark

  • Es heißt zwar, man habe die Eingabematrizen quadratischer gemacht, damit Tiling und Wiederverwendung möglich werden, aber es würde mich nicht wundern, wenn viele mögliche Optimierungen nicht in Onnx gelandet sind.
    Qualcomm scheint keinen direkten Zugriff auf die NPU zu geben, sondern erwartet, dass Nutzer ihre Modelle mit einem Framework konvertieren und übergeben. Meiner Erfahrung nach sind Konvertierungstools meist nicht besonders gut und verpassen viele Optimierungen.
    Daher ist es vielleicht weniger „die NPU ist schlecht“ als vielmehr „das Konvertierungstool ist schlecht“. Ich werde warten, bis direkter Zugriff möglich ist, und vertraue den Konvertierungstools nicht.
    Ich sehe NPUs als gut geeignet für sehr kleine Machine-Learning-Modelle und sehr schnelle Funktionsapproximation. Genau dafür will ich sie nutzen. LLMs sind derzeit zwar angesagt, aber es gibt enorm viele spezialisierte Aufgaben, bei denen kleine Modelle wirklich nützlich sind.

    • Kannst du Beispiele für spezialisierte Aufgaben nennen, bei denen kleine Modelle nützlich sind? Am besten solche, bei denen selbst ein kleines Modell dauerhaft ausgeführt wird, sodass es im Cache bleibt, und bei denen es für genügend Nutzer wertvoll ist, um diese Cache-Belegung zu rechtfertigen.
      Ich meine nicht, dass es so etwas nicht gibt, aber ehrlich gesagt weiß ich nicht genau, was das wäre, und würde es gern verstehen.
    • Genau das wollte ich auch sagen. Ich habe den Elite X nicht ausprobiert, aber bei Geräten früherer Generationen, vor allem dem 865, brauchten der Compute-DSP als Beschleuniger und die deutlich kleinere NPU sehr spezifische Setups, Kompilierung mit eigener Toolchain, RPC-Kommunikation und Ähnliches.
      Ich hoffe, dass die NPU des Elite X wegen Copilot+ leichter zugänglich geworden ist, aber der Punkt ist: So einfach wie „man führt ein generisches Modell aus und es teleportiert sich magisch auf die NPU“ kann es kaum sein.
  • Eine RTX 4080 sollte etwa 40 TFLOPS schaffen, hier werden aber nur 216 Milliarden Operationen pro Sekunde gemeldet. Da sollte man den Benchmark wohl noch einmal überprüfen.
    Es ist sehr wahrscheinlich, dass bei der FLOPS-Messung ein gravierender Fehler vorlag. Dass die CPU die NPU schlägt, ist möglich, aber für einen sauberen Vergleich müsste man mehrere Matrixmultiplikationen ohne Anwendungssynchronisation benchmarken.

    • Das ist nur ein Teil davon. Schon beim groben Überfliegen der Dokumentation sieht man, dass auch die CPU-Inferenz nicht auf vergleichbare Weise durchgeführt wurde.
  • Der Benchmark ist eine Matrixmultiplikation der Form (6, 1500, 256) X (6, 256, 1500), was in der AI-Welt keine besonders große Größe ist. Bei deutlich größeren Matrizen würde die Lücke größer werden.
    Zum Beispiel hat selbst eines der kleineren Modelle, Llama 3.1 8B, Matrixmultiplikationen wie (batch, 14336, 4096) x (batch, 4096, 14336).
    Ich halte diesen Benchmark für nicht realistisch genug.

  • Ich habe den Qualcomm-NPU-Profiler qprof auf diesen Benchmark angesetzt. Den Profiling-Ergebnissen zufolge wurde die Arbeit nicht den Tensor Cores zugewiesen, die den Großteil der NPU-Rechenleistung liefern, sondern den Vector Cores.
    Grob gerechnet scheint HMX 30-mal stärker zu sein als HVX.
    Die Arbeitslast ist relativ klein, sodass die Hardwarekapazität wegen des Overheads für I/O-Quantisierung/Dequantisierung und NCHW-NHCW-Mapping nicht ausreichend genutzt wird. Auch das Padding der Gewichte und Eingaben auf Vielfache von 64 würde der Performance helfen.
    Profiling-Grafik: https://imgur.com/a/2OKR93e
    Die geschätzte HVX-Rechenleistung beträgt bei int8 4 * 2 * 1.43 * 1024 / 8 = 1.46TOPS. Dabei steht 4 für die Anzahl der Vector Cores, 2 für Operationen pro Takt, 1,43 GHz für die HVX-Frequenz, 1024 bit für die Breite der Vektorregister und 8 bit für die Präzision.

    • Die Formelformatierung ist falsch; es sollte 4 * 2 * 1.43 * 1024 / 8 heißen.
  • Der eigentliche Titel des Artikels sollte „Benchmarking Qualcomm's NPU on the Microsoft Surface Tablet“ lauten.
    Es geht hier nicht um NPUs im Allgemeinen, sondern um eine bestimmte NPU, betrachtet mit einem bestimmten Benchmark und einer bestimmten Kombination aus Bibliotheken/Frameworks. Daher beweist das im Grunde gar nichts.