Mit SSE-Intrinsics, habe ich einen Vektor von vier 32-Bit-Floats im Bereich von 0-255 geklammert und auf nächste Ganzzahl gerundet. Ich möchte jetzt diese vier als Bytes schreiben.SSE intrinsics: Konvertieren 32-Bit-Gleitkommazahlen in UNSIGNED 8-Bit-Ganzzahlen
Es ist eine intrinsische _mm_cvtps_pi8
, die 32-Bit-8-Bit-unterzeichnet int konvertieren, aber das Problem ist, dass jeder Wert über 127 bis 127 einklemmt kann ich keine Anleitung finden, die klemmt vorzeichenlose 8-Bit-Werte.
Ich habe eine Intuition, was ich tun möchte, ist eine Kombination von _mm_cvtps_pi16
und _mm_shuffle_pi8
gefolgt von der Anweisung, um die vier Bytes, die ich interessiere, in den Speicher zu bekommen. Ist das der beste Weg? Ich werde sehen, ob ich herausfinden kann, wie man die Shuffle-Control-Maske codiert.
UPDATE: Folgendes scheint genau das zu tun, was ich will. Gibt es einen besseren Weg?
#include <tmmintrin.h>
#include <stdio.h>
unsigned char out[8];
unsigned char shuf[8] = { 0, 2, 4, 6, 128, 128, 128, 128 };
float ins[4] = {500, 0, 120, 240};
int main()
{
__m128 x = _mm_load_ps(ins); // Load the floats
__m64 y = _mm_cvtps_pi16(x); // Convert them to 16-bit ints
__m64 sh = *(__m64*)shuf; // Get the shuffle mask into a register
y = _mm_shuffle_pi8(y, sh); // Shuffle the lower byte of each into the first four bytes
*(int*)out = _mm_cvtsi64_si32(y); // Store the lower 32 bits
printf("%d\n", out[0]);
printf("%d\n", out[1]);
printf("%d\n", out[2]);
printf("%d\n", out[3]);
return 0;
}
UPDATE2: Hier ist eine noch bessere Lösung zu Harold Antwort basiert:
#include <smmintrin.h>
#include <stdio.h>
unsigned char out[8];
float ins[4] = {10.4, 10.6, 120, 100000};
int main()
{
__m128 x = _mm_load_ps(ins); // Load the floats
__m128i y = _mm_cvtps_epi32(x); // Convert them to 32-bit ints
y = _mm_packus_epi32(y, y); // Pack down to 16 bits
y = _mm_packus_epi16(y, y); // Pack down to 8 bits
*(int*)out = _mm_cvtsi128_si32(y); // Store the lower 32 bits
printf("%d\n", out[0]);
printf("%d\n", out[1]);
printf("%d\n", out[2]);
printf("%d\n", out[3]);
return 0;
}
Warten Sie, Sie wissen '_mm_shuffle_pi8' ist die mm-Register-Version, oder? Vergiss nicht deine '_mm_empty' – harold
@harold: Oh, guter Punkt. Ich habe jedoch "-mfpmath = sse" in der Compiler-Befehlszeile. –
Darf ich vorschlagen, das '_mm_packus_epi32' durch' _mm_packs_epi32' zu ersetzen? Wie Peter sagte, es funktioniert gut und erfordert nur SSE2. Dein (basierend auf Harolds) benötigt SSE4.1 – user1593842