2016-07-12 12 views
0

Ich habe ein 256-Bit-AVX-Register mit 4 komplexen komplexen Zahlen, die als real, imaginär, real, imaginär usw. gespeichert sind. Ich schreibe gerade das gesamte 256-Bit-Register zurück und summiere es dort, aber das scheint ineffizient.AVX, Horizontale Summe der Einzelpräzision Komplexe Zahlen?

Wie kann die komplexe Zahl horizontale Summe mit AVX (oder AVX2) intrinsics durchgeführt werden? Ich würde eine Antwort mit Assembly akzeptieren, wenn es keine Antwort mit vergleichbarer Effizienz unter Verwendung von intrinsics gibt.

Bearbeiten: Um zu klären, ob das Register enthält AR, AI, BR, BI, CR, CI, DR, DI, ich möchte die komplexe Zahl berechnen (AR + BR + CR + DR, AI + BI + CI + DI). Wenn das Ergebnis in einem 256-Bit-Register ist, kann ich die 2 Gleitkommazahlen mit einfacher Genauigkeit extrahieren.

Edit2: Mögliche Lösung, wenn auch nicht unbedingt optimal ...

float hsum_ps_sse3(__m128 v) { 
    __m128 shuf = _mm_movehdup_ps(v);  // broadcast elements 3,1 to 2,0 
    __m128 sums = _mm_add_ps(v, shuf); 
    shuf  = _mm_movehl_ps(shuf, sums); // high half -> low half 
    sums  = _mm_add_ss(sums, shuf); 
    return  _mm_cvtss_f32(sums); 
} 

float sumReal = 0.0; 
float sumImaginary = 0.0; 

__m256i mask = _mm256_set_epi32 (7, 5, 3, 1, 6, 4, 2, 0); 

// Separate real and imaginary. 
__m256 permutedSum = _mm256_permutevar8x32_ps(sseSum0, mask); 
__m128 realSum = _mm256_extractf128_ps(permutedSum , 0); 
__m128 imaginarySum = _mm256_extractf128_ps(permutedSum , 1); 

// Horizontally sum real and imaginary. 
sumReal = hsum_ps_sse3(realSum); 
sumImaginary = hsum_ps_sse3(imaginarySum); 
+0

Wir sind eine Code-Site; Mit einem einfachen Beispiel könnten Sie leichter erklären, was Sie wollen. Das heißt, ich vermisse das Problem. Ja, AVX ist ein wahnsinniges Design mit seinen 2 Spuren, aber in diesem Fall tut das nicht weh. Mischen Sie die reellen Teile auf eine Spur, imaginäre Komponenten auf die andere Spur (Bits 0: 127 und 128: 255), führen Sie eine horizontale Addition innerhalb der Spur durch. Ergebnisse enden in 0:31 und 128: 159. – MSalters

+0

Was ist Ihr Ziel? Vielleicht möchten Sie acht komplexe Zahlen in zwei AVX-Registern speichern: die echten Teile in einem und die imaginären Teile in einem anderen. Es hängt wirklich davon ab, was dein Ziel ist. –

+0

@Zboson Mein Ziel ist genau wie in der Frage angegeben. Die Daten werden so gespeichert, dass reale und imaginäre Werte alternieren und dies nicht geändert werden kann. Die Lösung, die ich in meinem Edit vorgeschlagen habe, trennt die realen und imaginären Komponenten, um sie zu summieren, aber die Eingabedaten werden abwechselnd real und imaginär sein. – user1777820

Antwort

3

Eine recht einfache Lösung, die nur AVX (nicht AVX2) erfordert:

__m128i v0 = _mm256_castps256_ps128(v);  // get low 2 complex values 
__m128i v1 = _mm256_extractf128_ps(v, 1); // get high 2 complex values 
v0 = _mm_add_ps(v0, v1);      // add high and low 
v1 = _mm_shuffle_ps(v0, v0, _MM_SHUFFLE(1, 0, 3, 2)); 
v0 = _mm_add_ps(v0, v1);      // combine two halves of result 

Das Ergebnis wird in v0 sein als { sum.re, sum.im, sum.re, sum.im }.

+0

Seltsamerweise etwas mit CR/LF-Zeilenenden zu tun? –

+0

Hahaha ... Ich benutze einen Zufalls Agenten Spoofer in Firefox, den ich vor kurzem installiert habe, um es auszuprobieren. Anscheinend hat das Profil, das es zufällig auswählte, das getan (ich denke, dass es IE10 war). Wenn ich ein neues zufälliges Profil wähle, wird es korrekt angezeigt. –

+0

Aha - das ist eine Erleichterung dann - ich traf früher [Bearbeiten] und konnte nichts falsch mit der Post sehen. –