Für die Funktion, die ich schreibe, möchte ich eine Nan zurückgeben, wenn die Eingabe keinen Sinn ergibt.
Wie kann ich am einfachsten ein NaN in ein xmm-Register einfügen ?
Für die Funktion, die ich schreibe, möchte ich eine Nan zurückgeben, wenn die Eingabe keinen Sinn ergibt.
Wie kann ich am einfachsten ein NaN in ein xmm-Register einfügen ?
Antworten:
All-one ist ein leises (nicht signalisierendes, auch normales) NaN, was Sie wollen. Der einfachste Weg, eine zu erzeugen, besteht darin, mit SSE2 pcmpeqd xmm0,xmm0
jedes Bit im Register auf 1
die Komplement-Ganzzahl von 2 zu setzen -1
. ( Setzen Sie alle Bits im CPU-Register effizient auf 1 / Was sind die besten Befehlssequenzen, um Vektorkonstanten im laufenden Betrieb zu generieren? )
Es ist eigentlich ein -NaN
- das Vorzeichenbit ist gesetzt. Betrachten Sie eine ganzzahlige Rechtsverschiebung ( psrld xmm0,1
) oder dividieren Sie durch Null / Null ( xorps xmm0,xmm0
/ divpd xmm0,xmm0
), wenn dies unerwünscht ist.
Mathematikfunktionen, die NaN zurückgeben möchten, möchten häufig auch sicherstellen, dass das FP-ungültige Sticky-Exception-Bit in MXCSR gesetzt wird (oder tatsächlich eine Ausnahme auslösen, wenn Ihr Anrufer diese Ausnahme entlarvt hat). Zu tun , dass , können Sie multiplizieren oder den NaN mit sich selbst hinzufügen. z.B
...
.error_return_path:
pcmpeqd xmm0, xmm0
mulsd xmm0, xmm0 ; Cause an FP-invalid operation.
ret
Oder mulss
für einfache Präzision float
. mulpd
Ich mulps
wäre auch angemessen.
Das Bitmuster für das Multiplizieren oder Addieren von NaN mit NaN ist definitiv immer noch ein NaN und sollte immer noch die gleiche Nutzlast sein, also immer noch alle.
Wenn der Rückgabewert ein Ergebnis von mulsd
oder addsd
(oder divsd
) ist, hat dies auch den Vorteil, dass der Anrufer, wenn er dieses Register wiederholt in einer Schleife verwendet, keine Bypass-Latenz beim Überqueren von Domänen aufweist. (In der Sandybridge-Familie dauert dies ewig. ZB addsd xmm1, xmm0
würde jeder einen zusätzlichen Latenzzyklus von xmm1-Eingang zu xmm1-Ausgang haben, wenn xmm0 von kommt pcmpeqd
, selbst wenn das schon lange her ist und das Integer-SIMD-UOP bereits in den Ruhestand gegangen ist.)
Möglicherweise können Sie dies sogar verzweigungslos tun, wenn Sie cmpsd
oder verwenden cmppd
: Sie können orps
diese 0 / -1-Maske in ein Ergebnis umwandeln, um es NaN oder unverändert zu machen. Wenn eine andere Berechnung das FP-ungültige Flag setzt (oder bereits gesetzt hat) oder wenn Sie sich nicht darum kümmern, sind Sie fertig.
Achten Sie darauf, den kritischen Pfad nicht mit zusätzlichen cmp / oder zu verlängern. Wenn Sie erwarten, dass es sehr selten ist, können Sie lieber noch vergleichen und verzweigen, z. B. mit movmskpd
/ test eax,eax
/ jnz
auf einem cmppd-Ergebnis, um festzustellen, ob eines der Bits gesetzt wurde => eines der SIMD-Elemente hat eine Prüfung nicht bestanden.