如何使用 SSE2 加载 16 x 8 位整数

Posted

技术标签:

【中文标题】如何使用 SSE2 加载 16 x 8 位整数【英文标题】:How to load 16 x 8 bit integer using SSE2 【发布时间】:2012-10-10 00:51:11 【问题描述】:

假设我有 16 个 8 位整数,我想使用 SSE2 将它们加载到 __m128i 中:

__m128i v = _mm_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);

我可以使用_mm_set_epi8 静态执行此操作,但我想动态执行此操作;这些值将在运行时决定。

C = userinput;
for(int i=0; i<16; i++)

    load C*i on v at position i

我该怎么做?

【问题讨论】:

对于您所描述的情况,但使用 16 位整数,请使用您现在所做的常量 (set(1,2,3,4,...)),然后将其乘以 set1(user_input)。广播很容易/便宜,但没有在寄存器中制作系列的说明。在大多数编译器上,_mm_set_epi8(C*1, C*2, ...) 会编译成大量的标量乘法。 【参考方案1】:

一种方法是使用联合:

union 
    __m128i v;
    uint8_t a[sizeof(__m128i)];
 u;

将值加载到数组 a 中,然后从 v 中读取 SSE 向量。

或者,如果您的数据已经在连续内存中,则只需使用 _mm_load_si128(如果您不能保证 16 字节对齐,则使用 _mm_loadu_si128)。

【讨论】:

也许您可以将uint8_t a[16]; 替换为uint8_t a[sizeof(__m128i)];【参考方案2】:

传递给_mm_set_epi8 的值不必是常量——在您的示例中,您可以很好地编写

__m128i v = _mm_set_epi8(   0,    C,  2*C,  3*C,
                          4*C,  5*C,  6*C,  7*C,
                          8*C,  9*C, 10*C, 11*C,
                         12*C, 13*C, 14*C, 15*C);

(我手头没有一个编译器能很好地解决这个问题,但它确实有效。)

【讨论】:

【参考方案3】:

我不确定这个问题是否已经得到解答,但我确信 Paul R 是对的。

对于连续数据,使用内部负载

__m128i v = _mm_load_si128((__m128i*)&C[0]);

如果您的数据不能保证始终对齐,请使用_mm_loadu_si128

【讨论】:

【参考方案4】:
char Strings[10][1001];
char *gc="GC";  

*((__m128i*)gc)  

*((__m128i*)(&(Strings[i][j])))  

如果您愿意这样做,也可以使用。我也喜欢 struct 的答案,但是如果您使用指向文本的指针,您通常将不得不转换并进行指针数学运算。 (反正这是我的经验。)

【讨论】:

以上是关于如何使用 SSE2 加载 16 x 8 位整数的主要内容,如果未能解决你的问题,请参考以下文章

将 64 位整数加载到双精度 SSE2 寄存器的最佳方法?

有效使用vmlaq_s16

你如何在 SSE2 上进行带符号的 32 位扩展乘法?

如何将无符号整数加载到 SIMD 中

用于灰度到 ARGB 转换的 C++ SSE2 或 AVX2 内在函数

在 32 位整数中查找最大值