Berechne den absoluten Unterschied zwischen Ganzzahlen ohne Vorzeichen mithilfe von SSE

7

In C gibt es eine verzweigte Technik, um die absolute Differenz zwischen zwei vorzeichenlosen Ints zu berechnen? Zum Beispiel möchte ich für die Variablen a und b den Wert 2 für Fälle, wenn a = 3, b = 5 oder b = 3, a = 5. Idealerweise möchte ich auch die Berechnung mithilfe der SSE-Register vektorisieren können.

    
Jack Nock 01.08.2010, 04:52
quelle

8 Antworten

8

Es gibt mehrere Möglichkeiten dies zu tun, ich erwähne nur eins:

SSE4

  • Verwenden Sie PMINUD und PMAXUD , um den größeren Wert in Register # 1 und den kleineren Wert in Register # 2 zu trennen.
  • Subtrahiere sie.

MMX / SSE2

  • Kehre das Vorzeichenbit der beiden Werte um, weil der nächste Befehl nur den Vergleich mit Vorzeichen mit Vorzeichen akzeptiert.
  • %Code%. Verwenden Sie dieses Ergebnis als Maske.
  • Berechne die Ergebnisse von PCMPGTD und (a-b)
  • Verwenden Sie (b-a) , um den korrekten Wert für die absolute Differenz auszuwählen.
rwong 01.08.2010 05:24
quelle
3
%Vor%

Sie können sicherlich SSE-Register verwenden, aber der Compiler kann das sowieso für Sie tun

    
Anycorn 01.08.2010 05:22
quelle
3

Von tommesani.com besteht eine Lösung für dieses Problem darin, die vorzeichenlose Subtraktion mit Sättigung zweimal zu verwenden.

Da die Sättigungssubtraktion nie unter 0 fällt, berechnen Sie: r1 = (a-b) .sättigen r2 = (b-a) .saturierend

Wenn a größer als b ist, enthält r1 die Antwort und r2 wird 0 und umgekehrt für b & gt; a.   Eine ODER-Verknüpfung der beiden Teilergebnisse ergibt das gewünschte Ergebnis.

Laut das VTUNE Benutzerhandbuch , PSUBUSB / PSUBUSW ist für 128-Bit-Register verfügbar, so dass Sie eine Menge Parallelisierung auf diese Weise erhalten können.

    
Justin W 21.07.2011 18:06
quelle
2

berechnet die Differenz und gibt den absoluten Wert zurück

%Vor%

Dies erfordert eine Operation weniger, die die vorzeichenbehaftete Vergleichsoperation verwendet, und erzeugt weniger Registerdruck.

Gleicher Registerdruck wie zuvor, zwei weitere Ops, bessere Verzweigung und Zusammenführung von Abhängigkeitsketten, Befehlspaarung für die Dekodierung von uops und separate Einheitenauslastung. Obwohl dies eine Last erfordert, die nicht im Cache sein kann. Ich habe keine Ideen nach diesem.

%Vor%

Nach dem Timing jeder Version mit 2 Millionen Iterationen auf einem Core2Duo sind die Unterschiede nicht messbar. Wähle also, was leichter zu verstehen ist.

    
Phernost 19.08.2010 18:14
quelle
2

SSE2:

Scheint ungefähr so ​​schnell zu sein wie Phernosts zweite Funktion. Manchmal plant GCC es einen vollen Zyklus schneller, andere mal ein wenig langsamer.

%Vor%

SSSE3:

Immer etwas schneller als vorher. Abhängig davon, wie Dinge außerhalb der Schleife deklariert werden, gibt es viele Variationen. (Wenn Sie beispielsweise " a " und " b volatile " erstellen, wird die Verarbeitung beschleunigt. Dies scheint jedoch ein zufälliger Effekt für die Planung zu sein.) Dies ist jedoch konsistent am schnellsten um einen Zyklus oder so.

%Vor%

SSE4 (thx rwong):

Kann das nicht testen.

%Vor%     
Potatoswatter 20.08.2010 00:06
quelle
1

Probieren Sie das aus (nimmt zweite Ergänzungen an, was OK ist, wenn Sie nach SSE fragen):

%Vor%

Erläuterung: Das Zeichen-Bit (Bit 31) wird bis zum ersten Bit übertragen. das | 1 Teil stellt sicher, dass der Multiplikator entweder 1 oder -1 ist. Multiplikationen sind auf modernen CPUs schnell.

    
zvrba 01.08.2010 05:25
quelle
0

Ähm ... es ist ziemlich einfach ...

%Vor%

Leicht vektorisierbar (mit SSE3 as):

%Vor%

a und b sind vorzeichenlose Ganzzahlen. Betrachte a = 0 und b = 0xffffffff. Der korrekte absolute Unterschied ist 0xffffffff, aber Ihre Lösung wird 1 geben.

    
Goz 11.09.2010 14:48
quelle
0

Einer oder mehrere der folgenden Punkte führen wahrscheinlich zu verzweigungsfreiem Code, abhängig von der Maschine und dem Compiler, da die bedingten Ausdrücke alle sehr einfach sind.

Ich habe nicht alle Antworten durchgelesen, aber möglicherweise sind einige der folgenden im Vektorcode dargestellt; Sicherlich sind alle unten genannten vektorisierbar (wenn Sie den unsignierten Vergleich haben, um damit zu beginnen, oder fälschen Sie ihn, indem Sie zuerst die msb umschalten.). Ich dachte, es wäre hilfreich, praktische skalare Antworten auf die Frage zu haben.

%Vor%

Dies funktioniert auf x86_64 (oder irgendetwas, wo 64-Bit-Temps im Prinzip frei sind)

%Vor%     
greggo 21.03.2014 16:56
quelle

Tags und Links