SIMD Intrinsics sind nicht so beängstigend, aber sollten wir sie verwenden?

Ist Low-Level-Programmierung eine Sünde oder eine Tugend? Es hängt davon ab, ob.

Wenn ich für die Verwendung der Vektorverarbeitung auf einem modernen Prozessor programmiere, schreibe ich idealerweise Code in meiner Lieblingssprache und er läuft so schnell wie möglich „automatisch“.

Ich vermute, Sie wissen, dass die Welt nicht so funktioniert, es sei denn, Sie haben erst letzte Woche mit dem Programmieren begonnen. Spitzenleistung ist nur mit Aufwand verbunden. Daher meine Frage: Wie tief sollen wir gehen?

Vektoroperationen definiert

Eine "Vektor" -Operation ist eine mathematische Operation, die mehr als eine Operation ausführt. Bei einer Vektoraddition werden möglicherweise acht Zahlenpaare anstelle der regulären Addition hinzugefügt, bei der nur ein Zahlenpaar hinzugefügt wird. Bitten Sie den Computer, zwei Zahlen zu addieren. Wir können das mit einer regelmäßigen Add-Anweisung tun. Bitten Sie den Computer, acht Zahlenpaare zueinander hinzuzufügen (berechnen Sie C1 = A1 + B1, C2 = A2 + B2,… C8 = A8 + B8). Wir können das mit einer Anweisung zum Hinzufügen von Vektoren tun .

Vektoranweisungen umfassen Addition, Subtraktion, Multiplikation und andere Operationen.

 SIMD: Parallelität für Vektoren

Informatiker haben einen ausgefallenen Namen für Vektoranweisungen: SIMD oder "Single Instruction Multiple Data". Wenn wir uns eine reguläre Additionsanweisung als SISD (Single Instruction Single Data) vorstellen, wobei Single ein einzelnes Paar von Dateneingaben bedeutet, dann ist eine Vektoraddition eine SIMD, bei der Multiple acht Paare von Dateneingaben bedeuten kann.

Ich nenne SIMD gerne "die andere Hardware-Parallelität", da "Parallelität" in Computern so oft als Folge mehrerer Kerne angesehen wird. Die Anzahl der Kerne hat stetig zugenommen. Eine Kernanzahl von vier ist üblich, 20 oder mehr sind bei Prozessoren für Server üblich, und Intels höchste Kernanzahl beträgt heute 72 Kerne in einem einzelnen Intel® Xeon Phi ™ -Prozessor.

Auch die Vektorbefehlsgrößen sind gestiegen. Frühe Vektoranweisungen wie SSE führten bis zu vier Operationen gleichzeitig aus. Intels höchste Vektorbreite in AVX-512 führt heute bis zu 16 Operationen gleichzeitig aus.

 Wie tief sollen wir gehen?

Wie viel Arbeit sollten wir bei so viel Leistung leisten, um diese Leistung zu nutzen?

 Die Antwort ist viel, und hier ist der Grund: Vier Kerne können uns höchstens um das Vierfache beschleunigen. AVX (halb so groß wie AVX-512, aber viel häufiger) kann uns höchstens um das 8-fache beschleunigen. Zusammen können sie bis zu 32X erreichen. Beides zu tun macht sehr viel Sinn.

Hier ist meine einfache Liste, wie man versucht, Vektoranweisungen auszunutzen (in der Reihenfolge, in der wir versuchen sollten, sie anzuwenden):

 1.     Rufen Sie zunächst eine Bibliothek auf, die die Arbeit erledigt (die ultimative implizite Vektorisierung). Ein Beispiel für eine solche Bibliothek ist die Intel® Math Kernel Library (Intel® MKL). Alle Arbeiten zur Verwendung von Vektoranweisungen wurden von jemand anderem ausgeführt. Die Einschränkungen liegen auf der Hand: Wir müssen eine Bibliothek finden, die das tut, was wir brauchen.

2.     Verwenden Sie zweitens die implizite Vektorisierung. Bleiben Sie abstrakt und schreiben Sie es selbst mit Vorlagen oder Compilern. Viele Compiler verfügen über Vektorisierungsschalter und -optionen. Compiler sind wahrscheinlich der tragbarste und stabilste Weg. Es gab viele Vorlagen für die Vektorisierung, aber keine wurde im Laufe der Zeit ausreichend genutzt, um ein klarer Gewinner zu sein (ein neuer Eintrag ist Intel® SIMD Data Layout Templates [Intel® SDLT]).

3.     Verwenden Sie drittens die explizite Vektorisierung. Dies ist in den letzten Jahren sehr populär geworden und versucht, das Problem zu lösen, abstrakt zu bleiben, aber den Compiler zu zwingen, Vektoranweisungen zu verwenden, wenn er sie sonst nicht verwenden würde. Die Unterstützung von SIMD in OpenMP ist hier das Schlüsselbeispiel, bei dem Vektorisierungsanforderungen für den Compiler sehr explizit angegeben werden. In vielen Compilern gibt es nicht standardmäßige Erweiterungen, häufig in Form von Optionen oder „Pragmas“. Wenn Sie diesen Weg einschlagen, ist OpenMP der richtige Weg, wenn Sie sich in C, C ++ oder Fortran befinden.

4.     Schließlich werden Sie niedrig und schmutzig. Verwenden Sie SIMD Intrinsics. Es ist wie Assemblersprache, aber in Ihrem C / C ++ - Programm geschrieben. SIMD-Intrinsics sehen tatsächlich wie ein Funktionsaufruf aus, erzeugen jedoch im Allgemeinen einen einzelnen Befehl (einen Vektoroperationsbefehl, der auch als SIMD-Befehl bezeichnet wird).

SIMD-Intrinsics sind nicht böse; Sie sind jedoch ein letzter Ausweg. Die ersten drei Optionen sind für die Zukunft immer besser zu warten, wenn sie funktionieren. Wenn die ersten drei jedoch unsere Anforderungen nicht erfüllen, sollten wir auf jeden Fall versuchen, SIMD Intrinsics zu verwenden.

 Wenn Sie mit SIMD Intrinsics beginnen möchten, haben Sie ein ernstes Problem, wenn Sie an die Programmierung von Assemblersprachen gewöhnt sind. Dies liegt hauptsächlich daran, dass Sie die Dokumentation, in der die Vorgänge erläutert werden, leichter lesen können, einschließlich des hervorragenden Online-Intrinsics-Handbuchs von Intel. Wenn Sie völlig neu in diesem Bereich sind, bin ich auf einen kürzlich erschienenen Blog gestoßen („SSE: Beachten Sie die Lücke!“), Der eine sanfte Hand bei der Einführung von Intrinsics hat. Ich mag auch "Crunching Numbers with AVX and AVX2".

 Wenn eine Bibliothek oder ein Compiler das tun kann, was Sie benötigen, sind SIMD-Intrinsics nicht die beste Wahl. Sie haben jedoch ihren Platz und sind nicht schwer zu benutzen, wenn man sich erst einmal an sie gewöhnt hat. Probieren Sie es aus. Die Leistungsvorteile können erstaunlich sein. Ich habe SIMD-Intrinsics gesehen, die von cleveren Programmierern für Code verwendet werden, den wahrscheinlich kein Compiler produzieren wird.

Selbst wenn wir SIMD Intrinsics ausprobieren und schließlich eine Bibliothek oder einen Compiler die Arbeit machen lassen, kann das, was wir lernen, von unschätzbarem Wert sein, um die beste Verwendung einer Bibliothek oder eines Compilers für die Vektorisierung zu verstehen. Und das ist vielleicht der beste Grund, SIMD intrinsics zu testen, wenn wir das nächste Mal etwas benötigen, um Vektoranweisungen zu verwenden.

Klicken Sie hier, um Ihre kostenlose 30-Tage-Testversion von Intel Parallel Studio XE herunterzuladen