Für ein Hobby-Projekt, an dem ich gerade arbeite, muss ich bestimmte 64-Bit-Integer-Operationen auf einer x86-CPU emulieren, und es muss schnell sein.
Momentan mache ich das über MMX-Anweisungen, aber das ist wirklich ein Schmerz, mit dem ich arbeiten muss, weil ich den fp-Registerzustand die ganze Zeit leeren muss (und weil die meisten MMX-Anweisungen mit signiert Ganzzahlen, und ich brauche unsigned Verhalten).
Ich frage mich also, ob die SSE / Optimierungsgurus hier auf SO mit SSE eine bessere Implementierung finden können.
Die Operationen, die ich brauche, sind die folgenden (ziemlich spezifischen):
%Vor%Insbesondere brauche ich keine allgemeine Addition oder Verschiebung, z. B. nur eine hinzufügen und links verschieben. Wirklich, nur die genauen Operationen, die hier gezeigt werden.
Außer natürlich, auf x86 wird uint64_t
mit zwei 32-Bit-Skalaren emuliert, was langsam ist (und in meinem Fall einfach nicht funktioniert, weil ich Loads / Stores atomar sein muss, was sie nicht sein werden, wenn zwei separate Register geladen / gespeichert werden.)
Daher brauche ich eine SIMD-Lösung.
Einige dieser Operationen sind trivial und werden bereits von SSE2 unterstützt. Andere ( !=
und <
) erfordern etwas mehr Arbeit.
Vorschläge? SSE und SSE2 sind in Ordnung. Es würde einige Überzeugungsarbeit erfordern, um SSE3 zuzulassen, und SSE4 kommt wahrscheinlich nicht in Frage (Eine CPU, die SSE4 unterstützt, wird wahrscheinlich sowieso 64-Bit ausführen , und daher brauche ich diese Umgehungslösungen nicht)
SSE2 bietet direkte Unterstützung für einige 64-Bit-Integer-Operationen:
Setzen Sie beide Elemente auf 0:
%Vor%Setzen Sie beide Elemente auf 1:
%Vor%Jede 64-Bit-Ganzzahl vertikal addieren / subtrahieren:
%Vor%Linke Umschalttaste:
%Vor%Bitweise Operatoren:
%Vor% SSE hat keine Inkremente, daher müssen Sie eine Konstante mit 1
verwenden.
Vergleiche sind schwieriger, da es keine 64-Bit-Unterstützung gibt.
Hier ist der für die Gleichheit:
%Vor% Dadurch wird jedes 64-Bit-Element auf 0xffffffffffff
gesetzt, wenn sie gleich sind. Wenn Sie es als 0
oder 1
in int
möchten, können Sie es mit _mm_cvtsi32_si128()
herausziehen und 1
hinzufügen.
Und weniger als: (nicht vollständig getestet)
%Vor% Dadurch wird jedes 64-Bit-Element auf 0xffffffffffff
gesetzt, wenn das entsprechende Element in a
kleiner als b
ist.
Hier sind Versionen von "equals" und "less-than", die einen Bool zurückgeben. Sie geben das Ergebnis des Vergleichs für die untere 64-Bit-Ganzzahl zurück.
%Vor%Tags und Links optimization c++ x86 sse