ich nicht schnellste garantieren kann, aber das ist ein Ansatz, der SSE verwendet. Acht 12-16-Bit-Konvertierungen werden pro Iteration durchgeführt und zwei Konvertierungen (ungefähr) werden pro Schritt durchgeführt (dh jede Iteration benötigt mehrere Schritte).
Dieser Ansatz straddelt die 12-Bit-Ganzzahlen um die 16-Bit-Grenzen im xmm-Register. Unten zeigt, wie dies gemacht wird.
- Ein xmm-Register wird verwendet (nehme xmm0 an). Der Zustand des Registers wird durch eine Buchstabenzeile dargestellt.
- Jeder Buchstabe steht für 4 Bits einer 12-Bit-Ganzzahl (dh AAA ist das gesamte erste 12-Bit-Wort im Array).
- Jede Lücke stellt eine 16-Bit-Grenze dar.
- >> 2 bedeutet eine logische Rechtsverschiebung von einem Byte.
- Das Karotte (^) Symbol wird verwendet, um hervorzuheben, welche relevanten 12-Bit-Ganzzahlen in jedem Schritt eine 16-Bit-Grenze überspannen.
:
load
AAAB BBCC CDDD EEEF FFGG GHHH JJJK KKLL
^^^
>>2
00AA ABBB CCCD DDEE EFFF GGGH HHJJ JKKK
^^^ ^^^
>>2
0000 AAAB BBCC CDDD EEEF FFGG GHHH JJJK
^^^ ^^^
>>2
0000 00AA ABBB CCCD DDEE EFFF GGGH HHJJ
^^^ ^^^
>>2
0000 0000 AAAB BBCC CDDD EEEF FFGG GHHH
^^^
Bei jedem Schritt können wir die ausgerichteten 12-Bit-Integer und speichern sie in der XMM1 Register extrahieren. Am Ende wird unser xmm1 wie folgt aussehen. Fragezeichen bezeichnen Werte, die uns nicht interessieren.
AAA? ?BBB CCC? ?DDD EEE? ?FFF GGG? ?HHH
Extrahieren der hochausgerichteten ganzen Zahlen (A, C, E, G) in xmm2 und dann auf xmm2, eine rechte logischen Wort Verschiebung von 4 Bits durchzuführen. Dadurch werden die hoch ausgerichteten Ganzzahlen in niedrig ausgerichtete konvertiert. Mischen Sie diese angepassten Ganzzahlen wieder in xmm1. Der Zustand der XMM1 ist jetzt:
?AAA ?BBB ?CCC ?DDD ?EEE ?FFF ?GGG ?HHH
Endlich können wir die ganzen Zahlen maskieren (dh wandeln die 's auf 0 ist?) Mit 0FFFh auf jedes Wort.
0AAA 0BBB 0CCC 0DDD 0EEE 0FFF 0GGG 0HHH
Jetzt enthält xmm1 acht aufeinanderfolgende konvertierte Ganzzahlen.
Das folgende NASM-Programm demonstriert diesen Algorithmus.
global main
segment .data
sample dw 1234, 5678, 9ABCh, 1234, 5678, 9ABCh, 1234, 5678
low12 times 8 dw 0FFFh
segment .text
main:
movdqa xmm0, [sample]
pblendw xmm1, xmm0, 10000000b
psrldq xmm0, 1
pblendw xmm1, xmm0, 01100000b
psrldq xmm0, 1
pblendw xmm1, xmm0, 00011000b
psrldq xmm0, 1
pblendw xmm1, xmm0, 00000110b
psrldq xmm0, 1
pblendw xmm1, xmm0, 00000001b
pblendw xmm2, xmm1, 10101010b
psrlw xmm2, 4
pblendw xmm1, xmm2, 10101010b
pand xmm1, [low12] ; low12 could be stored in another xmm register
Ich habe etwas Code hinzugefügt. Die Konvertierung eines 12-Bit-Bildes in ein Float-Array kann aber auch in ein UInt16 umgewandelt werden (ändern Sie einfach das Casting) – Gilad
Dies ist eine interessante Frage. Es muss sicherlich nicht geschlossen werden. – erisco
Schnellste ... hängt von der Plattform ab. RAM, Cache, etc etc .. Sie können SSE nicht nur mit der C# -Sprache verwenden. Definieren Sie Ihre Parameter/Einschränkungen und halten Sie sich daran. Ansonsten ist die Frage wirklich nicht beantwortbar –