2016-04-12 24 views
1

Angenommen, ich habe einen Zeiger auf den Speicher in rsi, und ich möchte den 12-Byte-Wert auf die niedrigen 96 Bits von xmm0 geladen werden. Es ist mir egal, was mit die hohen 32 Bits passiert. Was ist ein effizienter Weg dies zu tun?Wie kann man 96 Bits aus dem Speicher in ein XMM-Register laden?

(Side Frage: das Beste, was ich habe kommen mit beinhaltet die movlpd „Move Low Double-Precision-Fließkommawert Verpackt“ Anweisung Gibt es eine Möglichkeit in , die diese Anweisungen sind spezifisch für Gleitkommazahlen. ? ich verstehe nicht was es auf diese Weise dokumentiert ist,. sicherlich sollte es auch für ganze Zahlen arbeitet)

Antwort

2

Wenn eine 16-Byte Last nicht in einer anderen Seite und Fehler überquert, dann movups verwenden. Die hohen 4 Bytes sind der Müll, der im Speicher vorhanden ist. Es kann ein Problem sein, einen Cache-Fehler für die 4B zu verursachen, die Sie nicht interessieren, ebenso wie die Cache-Zeilen-Aufteilung.

Andernfalls verwenden Sie movq/pinsrd (SSE4.1), oder eine andere Möglichkeit, zwei Lasten + ein Shuffle auszuführen. movq + pinsrd wird 3 Fused-Domain-Ups auf Intel SnB-Familien-CPUs sein, weil pinsrd kann nicht Mikro-Sicherung. (Und seine ALU-UOP benötigt den Shuffle-Port (p5)).


Eine andere Möglichkeit: AVX VMASKMOVPS xmm1, xmm2, m128.

Bedingtes bewegt gepackten Datenelementen aus dem zweiten Quelloperanden in das entsprechende Datenelement des Zieloperanden in Abhängigkeit von den Maskenbits mit jedem Datenelement zugeordnet ist (MSB des ersten Operanden src).

... Fehler werden nicht aufgrund auftreten beliebigen Speicherplatz verweisen, wenn das entsprechende Maskenbit für diesen Speicherplatz ist 0.

Intel Haswell: 3 kondensierten Domain Uops (eine Last und zwei Shuffle (p5)). 4c Latenz, einer pro 2c Durchsatz.

Es ist wahrscheinlich nicht sehr gut im Vergleich, vor allem. wenn der umgebende Code gemischt werden muss.


Ihre Sehr selten genommen bedingte Verzweigung, die movups jederzeit verwendet es nicht zu bemängeln garantiert wird auch 3 kondensierte Domain Uops auf dem schnell weg, und einer von ihnen kann im Wettbewerb läuft auf PORT6 (nicht mit Vektor ALUs überhaupt). Die LEA ist auch nicht auf dem kritischen Pfad.


movlpd ist sicher auf alle Daten zu verwenden. Es wird nie Fehler oder langsam mit Daten, die ein Fließkomma-NaN oder etwas ähnliches darstellt. Sie müssen sich nur darum kümmern, mit Anweisungen, die in der Insn ref Handbuch mit einem nicht leeren "SIMD Floating-Point Exceptions" Abschnitt aufgeführt sind. z.B. addps kann "Überlauf, Unterlauf, ungültig, Genauigkeit, Denormal" Ausnahmen erzeugen, aber shufps sagt "None".

+0

Leider steuere ich nicht die Position oder die Dimensionen des Eingangs Also kann ich nicht überlesen. 'movq' und' pinsrd' ist auch, was ich mir ausgedacht habe; Danke für die Bestätigung. – jacobsa

+0

Danke auch für den Hinweis über 'movlpd'. Aber meine Frage ist dann: Warum ist dokumentiert, wie sie insbesondere auf Fließkommawerte angewendet wird? – jacobsa

+0

@jacobsa: Wenn Sie wissen, dass es lesbaren Speicher * vor * 12B gibt, können Sie von '[addr-4]' laden und dann verschieben ('psrldq'). Oder Sie können sogar die Adresse maskieren, um einen 16B-ausgerichteten Zeiger zu erhalten, der einige der gewünschten Daten abdeckt (und immer noch keine Fehler verursachen kann). –

1

Peter Cordes Antwort dazu beigetragen, mich von Seiten machen denken, und ich Liquidation Überprüfung nur, ob es eine Chance war, dass wir Fehler würde:

// We'd like to perform only a single load from memory, but there's no 96-bit 
// load instruction and it's not necessarily safe to load the full 128 bits 
// since this may read beyond the end of the buffer. 
// 
// However, observe that memory protection applies with granularity of at 
// most 4 KiB (the smallest page size). If the full 16 bytes lies within a 
// single 4 KiB page, then we're fine. If the 12 bytes we are to read 
// straddles a page boundary, then we're also fine (because the next four 
// bytes must lie in the second page, which we're already reading). The only 
// time we're not guaranteed to be okay to read 16 bytes is if the 12 bytes 
// we want to read lie near the end of one page, and some or all of the 
// following four bytes lie within the next page. 
// 
// In other words, the only time there's a risk is when the pointer mod 4096 
// is in the range [4081, 4085). This is <0.1% of addresses. Check for this 
// and handle it specially. 
// 
// We perform the check by adding 15 and then checking for the range [0, 3). 
lea rax, [rsi+15] 
test eax, 0xffc 
jz slow_read 

// Hooray, we can load from memory just once. 
movdqu xmm0, XMMWORD PTR [rsi] 

done_reading: 
[...] 

slow_read: 
movq xmm1, QWORD PTR [rsi] 
pinsrd xmm1, DWORD PTR [rsi+8], 2 
jmp done_reading 
+0

schneller: 'lea eax, [rsi + 15]'/'test eax, 0xffc' /' jz'. Da Sie nur an den niedrigen Bytes interessiert sind, benötigen Sie keine 64-Bit-Regs und speichern Bytes auf REX-Präfixen. Ich habe eax benutzt, weil es eine spezielle Kodierung von 'test eax, imm32' gibt. Du könntest * das ändern, um 'low_read' für Cache-Zeilen-Splits zu verwenden, aber du würdest wahrscheinlich viel schlechter bei Branch-Mispredicts verlieren, als du gewinnst. Sie sollten dies unbedingt testen, indem Sie 'movq' /' pinsrd' verwenden, um sicherzustellen, dass es besser ist. 'lea' /' fusionierter Test-und-Zweig'/'movups' ist 3 Ups, dasselbe wie' movq'/'pinsrd', aber kürzerer kritischer Pfad. –

+0

Gute alte 'lea', wie habe ich es vergessen? Vielen Dank. Mein Benchmark ist nicht empfindlich genug, um hier den Unterschied zu erkennen (oder das ist kein Flaschenhals), aber Ihr Patch ist schöner. Erledigt. – jacobsa

+0

'lea EAX, [rsi + 15]' speichert ein weiteres Byte in der Kodierung. Die Standardadressgröße ist 64 Bit, aber die Standardoperandengröße ist 32 Bit, sogar für LEA. Außerdem ist es seltsam, dass das 'movdqu' in ein anderes Register geladen wird als das' movq'/'pinsrd'. (Sie können auch ein Byte mit 'movups' speichern. Es gibt keinen Nachteil bei der Verwendung von FP Loads/Stores, und Clang tut das manchmal. Verwenden Sie den richtigen Insn-Typ für die Daten für Reg-reg-Moves, obwohl einige bereits vergeben sind kümmere dich darum.) –