簡體   English   中英

使用SSE內在函數存儲四個16位整數

[英]Store four 16bit integers with SSE intrinsics

我將四個32位浮點數相乘並四舍五入,然后使用SSE內在函數將其轉換為四個16位整數。 我想將四個整數結果存儲到數組中。 使用浮點數很容易: _mm_store_ps(float_ptr, m128value) 但是我還沒有找到使用16位(__m64)整數來執行此操作的指令。

void process(float *fptr, int16_t *sptr, __m128 factor)
{
  __m128 a = _mm_load_ps(fptr);
  __m128 b = _mm_mul_ps(a, factor);
  __m128 c = _mm_round_ps(b, _MM_FROUND_TO_NEAREST_INT);
  __m64 s =_mm_cvtps_pi16(c);
  // now store the values to sptr
}

任何幫助,將不勝感激。

我個人將避免使用MMX。 另外,我將使用顯式存儲而不是隱式存儲,后者通常僅在某些編譯器上有效。 以下代碼可在MSVC2012和SSE 4.1中找到。

請注意, fptr必須為16字節對齊。 如果在64位模式下進行編譯,這不是問題,但是在32位模式下,則應確保其對齊。

#include <stdio.h>
#include <stdint.h>
#include <smmintrin.h>

void process(float *fptr, int16_t *sptr, __m128 factor)
{
  __m128 a = _mm_load_ps(fptr);
  __m128 b = _mm_mul_ps(a, factor);
  __m128i c = _mm_cvttps_epi32(b);
  __m128i d = _mm_packs_epi32(c,c);
  _mm_storel_epi64((__m128i*)sptr, d);
}

int main() {
    float x[] = {1.0, 2.0, 3.0, 4.0};
    int16_t y[4];
    __m128 factor = _mm_set1_ps(3.14159f);
    process(x, y, factor);
    printf("%d %d %d %d\n", y[0], y[1], y[2], y[3]);
}

請注意, _mm_cvtps_pi16不是簡單的內在指令,《英特爾內在指令》說:“此內在指令會創建兩個或更多指令的序列,並且可能比本機指令執行得差。請考慮此內在指令對性能的影響。”

這是使用MMX版本的程序集輸出

mulps   (%rdi), %xmm0
roundps $0, %xmm0, %xmm0
movaps  %xmm0, %xmm1
cvtps2pi    %xmm0, %mm0
movhlps %xmm0, %xmm1
cvtps2pi    %xmm1, %mm1
packssdw    %mm1, %mm0
movq    %mm0, (%rsi)
ret

這是使用僅SSE版本的程序集輸出

mulps   (%rdi), %xmm0
cvttps2dq   %xmm0, %xmm0
packssdw    %xmm0, %xmm0
movq    %xmm0, (%rsi)
ret

使用__m64類型,您可以適當地__m64目標指針:

void process(float *fptr, int16_t *sptr, __m128 factor)
{
  __m128 a = _mm_load_ps(fptr);
  __m128 b = _mm_mul_ps(a, factor);
  __m128 c = _mm_round_ps(b, _MM_FROUND_TO_NEAREST_INT);
  __m64 s =_mm_cvtps_pi16(c);
  *((__m64 *) sptr) = s;
}

使用MMX指令的對齊存儲和不對齊存儲沒有區別,就像SSE / AVX一樣。 因此,您不需要內部函數即可執行存儲。

我認為您可以安全地將其移至通用的64位寄存器( long long對Linux LLP64和Windows LP64均適用)並自行復制。

從我在xmmintrin.h閱讀的內容xmmintrin.h ,gcc可以很好地處理從__m64到很long long 可以肯定的是,您可以使用_mm_cvtsi64_si64x

short* f;
long long b = _mm_cvtsi64_si64x(s);
f[0] = b >> 48;
f[1] = b >> 32 & 0x0000FFFFLL;
f[2] = b >> 16 & 0x000000000FFFFLL;
f[3] = b & 0x000000000000FFFFLL;

您可以使用union鍵入pune以使其看起來更好,但我想這會屬於未定義的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM