Използвайки SSE intrinsics, получих вектор от четири 32-битови плаващи числа, фиксирани в диапазона 0-255 и закръглени до най-близкото цяло число. Сега бих искал да запиша тези четири като байтове.
Има вътрешен _mm_cvtps_pi8
, който ще преобразува 32-битово в 8-битово подписано int, но проблемът там е, че всяка стойност над 127 се затяга до 127. Не мога да намеря инструкции, които да затягат до 8-битови стойности без знак.
Имам интуиция, че това, което може да искам да направя, е някаква комбинация от _mm_cvtps_pi16
и _mm_shuffle_pi8
, последвана от инструкция за преместване, за да вкарам четирите байта, които ме интересуват, в паметта. Това ли е най-добрият начин да го направите? Отивам да видя дали мога да разбера как да кодирам маската за контрол на разбъркването.
АКТУАЛИЗАЦИЯ: Следното изглежда прави точно това, което искам. Има ли по-добър начин?
#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;
}
АКТУАЛИЗАЦИЯ 2: Ето още по-добро решение въз основа на отговора на Харолд:
#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;
}
_mm_shuffle_pi8
е версията на mm-register, нали? Не забравяйте своя_mm_empty
- person harold   schedule 24.04.2015-mfpmath=sse
в командния ред на компилатора. - person Timothy Miller   schedule 24.04.2015_mm_packus_epi32
с_mm_packs_epi32
? Както каза Питър, работи добре и изисква само SSE2. Вашият (базиран на Харолд) изисква SSE4.1 - person user1593842   schedule 08.09.2017