sqrt von uint64_t vs. int64_t

8

Ich habe festgestellt, dass die Berechnung des ganzzahligen Teils der Quadratwurzel von uint64_t viel komplizierter ist als von int64_t . Bitte, hat jemand eine Erklärung dafür? Warum ist es scheinbar viel schwieriger, mit einem Extrabit umzugehen?

Folgendes:

%Vor%

kompiliert mit clang 5.0 und -mfpmath=sse -msse3 -Wall -O3 zu

%Vor%

Aber das Folgende:

%Vor%

kompiliert zu:

%Vor%     
Hinrik 06.12.2017, 20:40
quelle

2 Antworten

11

Zunächst müssen Sie sich vergewissern, dass dieser Code 64-Bit-Ganzzahlen (vorzeichenbehaftet oder unsigniert) in Gleitkommazahlen mit doppelter Genauigkeit umwandelt, wobei die Quadratwurzel verwendet wird und das Ergebnis dann wieder in eine vorzeichenbehaftete oder vorzeichenlose Ganzzahl umgewandelt wird / p>

Die Antwort auf Ihre Frage lautet, dass Intel eine 64-Bit-Ganzzahl mit Fließkomma-Konvertierung mit doppelter Genauigkeit (und das Gegenteil davon) in dem Befehlssatz, für den Sie kompilieren, bereitgestellt hat, nicht jedoch für den Fall ohne Vorzeichen. Sie haben die Konvertierung ohne Vorzeichen in AVX-512 hinzugefügt, aber sie existiert vorher nicht. Für den Fall mit Vorzeichen sind also die Umwandlung in doppelte Genauigkeit und die Rückwandlung jeweils eine Anweisung. Für den Fall ohne Vorzeichen muss der Compiler den Konvertierungsvorgang aus verfügbaren Anweisungen synthetisieren.

Hier erfahren Sie, welche Anweisungen in welchen Versionen von SSE2 / AVX / AVX-512 etc. verfügbar sind:      Ссылка

Sie können hier eine Diskussion über die Methode sehen, mit der die Konvertierung erstellt wurde:      Gibt es nicht signierte Äquivalente des x87 FILD und SSE CVTSI2SD Anweisungen?

    
Zalman Stern 06.12.2017, 21:22
quelle
3

Zusätzlich zu Zalmans ausgezeichneter Antwort : Das Ergebnis von sqrt ist immer kleiner als INT64_MAX, weil die Eingabe von sqrt liegt im Bereich uint64_t . Daher ist ein einzelnes cvttsd2si ausreichend, um das Double zurück in uint64_t zu konvertieren. Mit anderen Worten: Für alle Eingabewerte a die Funktion

%Vor%

hat genau dasselbe Verhalten wie der modifizierte Code

%Vor%

Die letztere Funktion wird nach

kompiliert %Vor%

das ist viel weniger Anweisung als der ursprüngliche Code.

    
wim 07.12.2017 11:51
quelle