Wie Berechne Vektor-Skalarprodukt SSE Verwenden Intrinsische Funktionen in C
Ich versuche multiplizieren von zwei Vektoren zusammen, wo jedes element des einen Vektors multipliziert mit dem element in der gleichen index auf den anderen Vektor. Dann möchte ich die Summe aller Elemente des resultierenden Vektors zu erhalten, eine Zahl. Zum Beispiel, die Berechnung Aussehen würde, wie dies für die Vektoren {1,2,3,4} und {5,6,7,8}:
1*5+2*6+3*7+4*8
Im wesentlichen, ich nehme das Skalarprodukt der beiden Vektoren. Ich weiß, es ist eine SSE-Befehl, um dies zu tun, aber der Befehl nicht über eine systeminterne Funktion zugeordnet. An dieser Stelle möchte ich nicht zu schreiben, inline-Montage in meinem C-code, so möchte ich nur systeminterne Funktionen. Dies scheint eine gemeinsame Berechnung, so bin ich überrascht von mir selbst, dass ich konnte nicht finden, die Antwort auf Google.
Hinweis: ich bin die Optimierung für eine spezielle micro-Architektur, die unterstützt bis zu SSE 4.2.
Vielen Dank für Ihre Hilfe.
Du musst angemeldet sein, um einen Kommentar abzugeben.
, Wenn Sie tun eine dot-Produkt von mehr Vektoren verwenden multiplizieren und regelmäßige
_mm_add_ps
(oder FMA) innerhalb der inneren Schleife. Speichern Sie die horizontale Summe bis zum Ende.Aber wenn Sie tun, eine dot-Produkt von nur einem einzigen paar von SIMD-Vektoren:
GCC (ab version 4.3) umfasst
<smmintrin.h>
mit SSE4.1 Ebene-Interna, darunter die single-und double-precision-dot-Produkte:Auf Intel mainstream CPUs (nicht Atom/Silvermont) diese sind etwas schneller als es manuell zu tun mit mehreren Anweisungen.
Aber auf AMD (einschließlich Ryzen),
dpps
ist deutlich langsamer. (Siehe Agner Fog-Anweisung Tabellen)Als fallback für ältere Prozessoren, diesen Algorithmus können Sie verwenden, um erstellen Sie das Skalarprodukt der Vektoren
a
undb
:und dann horizontale Summe
r1
mit Am schnellsten horizontal float Vektorsumme auf x86 (siehe dort für eine kommentierte version dieses, und warum geht es schneller.)Eine langsame alternative Kosten 2 shuffles pro
hadd
, die leicht Engpass auf shuffle Durchsatz, insbesondere auf Intel-CPUs._mm_hadd_ps
. Siehe stackoverflow.com/a/35270026/195787.Ich würde sagen, der Schnellste SSE Methode wäre:
Folgte ich - Am schnellsten Horizontal Float Vektorsumme Auf x86.
Schrieb ich dies und kompiliert es mit
gcc -O3 -S -ftree-vectorize -ftree-vectorizer-verbose=2 sse.c
Und GCC 4.3.0 auto-vektorisiert es:
Allerdings wäre es nur, wenn ich eine Schleife mit genug Iterationen -- sonst wird die ausführliche Ausgabe klarstellen würde, dass die Vektorisierung war unrentabel oder die Schleife zu klein war. Ohne die
__restrict__
Schlüsselwörter generieren separate, nicht-vektorisierte Versionen zum Umgang mit Fällen, in denen die Ausgabeo
kann in einem der Eingänge.Ich würde fügen Sie den Anweisungen, als ein Beispiel, aber da ein Teil der Vektorisierung entrollen der loop, es ist nicht sehr gut lesbar ist.
Dort ist ein Artikel von Intel hier berührt dot-Produkt-Implementierungen.