Wie findet man die maximale horizontale in eine 256-bit-AVX-Vektor
Ich habe ein __m256d Vektor verpackt mit vier 64-bit-floating-point-Werte.
Ich muss die horizontale maximale von der vector-Elemente und speichert das Ergebnis in einer double-precision-skalaren Wert;
Meine versuche wurden alle mit einer Menge von schlurfenden der vector-Elemente, so dass der code nicht sonderlich elegant noch effizient. Auch fand ich es unmöglich, bleiben nur die AVX-Domäne. Irgendwann hatte ich die Verwendung der SSE-128-bit-Anweisungen zum extrahieren der endgültigen 64-bit-Wert. Ich möchte jedoch zu sein, erwies sich als falsch, auf diese Letzte Aussage.
Also die ideale Lösung:
1) nur verwenden, nur AVX-Anweisungen.
2) minimieren der Anzahl der Anweisungen. (Ich hoffe auf nicht mehr als 3-4 Anweisungen)
Having said that, jede elegante/effiziente Lösung akzeptiert werden, auch wenn Sie nicht Einhaltung der oben genannten Richtlinien.
Vielen Dank für jede Hilfe.
-Luigi
- Das ist eine schwierige Frage... machst du das mit nur 1 Vektor? Oder haben Sie viele Vektoren, für die Sie brauchen, um zu finden, die max? Können Sie (relativ) effizient tun, 4 von diesen parallel mit einem 4 x 4-Vektor transponieren...
- Naja... ich beschäftige mich mit vielen Vektoren. Jedoch ist die Einfachheit der Verarbeitung rechtfertigen nicht zwei 4x4-Transposition Operationen für jede iteration. Also ich bin von der Verarbeitung alles, was "horizontal" ohne transposition. Ich bin immer ein großer speed-up, der Art, der Nähe von 4x, denn ich bin die Vermeidung der Aufwand für die Umsetzung. Alles wird in einer engen Schleife manuell abgerollt 4 mal. Allerdings, wenn die Schleife ist vorbei, ich bin Links mit einem letzten AVX Vektor. Ich habe zu finden, die größte der vier Elemente, um zu speichern das Ergebnis zurück in mein doppelter Genauigkeit skalarer Wert. Daher meine Frage...
- Wenn es nicht in der "enge Schleife", ist es auch performance kritisch?
- Dieses mal nicht wirklich... 🙂 aber ich weiß, ich werde laufen in eine situation, wo es performance-kritisch. Das ist, warum ich formulierte die Frage, wie ich es Tat...
- Ah 🙂 In diesem Fall ist der beste Weg, dies zu tun wäre wahrscheinlich sehr spezifische, wie es verwendet wird. In anderen Worten, es ist nicht vectorizable auf dieser Ebene, aber können Sie schieben Sie es auf eine höhere Ebene...
- Was meinst du mit "schieben Sie es auf eine höhere Ebene" ?
- lassen Sie uns weiter, diese Diskussion im chat
- Beachten Sie, dass Sie bleiben können, in die AVX-Domäne, während mit einer 128-bit-Anweisungen. Es gibt eigentlich 3 Arten von Befehlen: AVX256, AVX128 und legacy SSE128. Ein Schalter zwischen den ersten beiden und letztere zu vermeiden ist, seine teuer auf Intel (also nicht auf AMD), aber die ersten beiden können vermischt werden, fast frei (Sie können zum einfügen
vzeroupper
manchmal)
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube nicht, dass Sie tun können, viel besser als 4 Anleitung: 2 mischt und 2 Vergleiche.
Triviale änderung, nur mit 256-bit-Vektoren:
(ungetestet)
_mm_unpackhi_pd
2 bytes kürzer als_mm_permute_pd
zu verwenden, so dass, wenn Sie nur wollen, ein Skalares Ergebnis. Keinen unmittelbaren Bedarf, eine 2-byte-VEX-Präfix.)Den Allgemeinen Weg, dies zu tun für einen Vektor
v1 = [A, B, C, D]
istv1
zuv2 = [C, D, A, B]
(swap 0. und 2. Elemente und 1. und 3. sind)v3 = max(v1,v2)
. Sie haben jetzt[max(A,C), max(B,D), max(A,C), max(B,D)]
v3
zuv4
Tausch die 0. und 1. Elemente, und die 2. und 3. diejenigen.v5 = max(v3,v4)
. Jetztv5
enthält die horizontale max in all seinen Komponenten.Speziell für AVX, die Permutationen kann man mit
_mm256_permute_pd
und die Höchstwerte getan werden kann, mit_mm256_max_pd
. Ich habe nicht die genauen permutiert Masken praktisch, aber Sie sollte ziemlich einfach sein, um herauszufinden.Hoffe, das hilft.
_mm256_extractf128_pd
durch_mm256_permute2f128_pd(x, x, 1)
,__m128d
durch__m256d
, und_mm_...
durch_mm256_...
,_mm_permute_pd(m1, 1)
durch_mm256_permute_pd(m1, 5)
.extractf128
/ 128bitmaxps
. In der Tat lane stuff erste ist nicht besser auf Intel-CPUs, und auf jeden Fall schlechter auf AMD-CPUs, wo 256b AVX-ops sind doppelt so teuer wie 128b AVX-ops. So oder so, eine 256b speichern und dann zwei Lasten -> ein Skalar zu vergleichen ist einfach nur albern, und langsamer als eineextractf128
.