Utilizzando gli intrinseci SSE, ho ottenuto un vettore di quattro float 32 bit fissati all'intervallo 0-255 e arrotondati al numero intero più vicino. Mi piacerebbe ora scrivere quei quattro come byte.Elementi intrinseci SSE: Converti i float a 32 bit in interi a 8 bit UNSIGNED
C'è un intrinseco _mm_cvtps_pi8
che converte a 32 bit a 8-bit firmato int, ma il problema non è che qualsiasi valore oltre 127 viene fissato al 127. Non riesco a trovare tutte le istruzioni che vi morsetto per valori a 8 bit senza segno.
Ho intuito che quello che potrei voler fare è una combinazione di _mm_cvtps_pi16
e _mm_shuffle_pi8
seguita da istruzioni di spostamento per ottenere i quattro byte che mi interessano nella memoria. È il modo migliore per farlo? Vedrò se riesco a capire come codificare la maschera di controllo shuffle.
AGGIORNAMENTO: Quanto segue sembra fare esattamente ciò che voglio. C'è un modo migliore?
#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: Ecco una soluzione ancora migliore in base alla risposta di Harold:
#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;
}
Aspetta, lo sai '_mm_shuffle_pi8' è la versione mm-register, giusto? Non dimenticare il tuo '_mm_empty' – harold
@harold: Oh, buon punto. Tuttavia, ho '-mfpmath = sse' sulla riga di comando del compilatore. –
Posso suggerire di sostituire '_mm_packus_epi32' con' _mm_packs_epi32'? Come ha detto Peter, funziona perfettamente e richiede solo SSE2. Il tuo (basato su harold's) richiede SSE4.1 – user1593842