两个 __m128i 的两个位到一个 __m128i 的四个位 -SSE

Posted

技术标签:

【中文标题】两个 __m128i 的两个位到一个 __m128i 的四个位 -SSE【英文标题】:Two bits of two __m128i to four bits of one __m128i -SSE 【发布时间】:2014-10-16 15:39:38 【问题描述】:

我有两个变量 __m128i(a 和 b),我只对 bit63 和 bit127 感兴趣。

最后,我想要一个变量 __m128i (c),其中变量 a 和 b 的四个位分别位于 bit31、bit 63、bit 95 和 bit 127。

总结(伪代码):

c.bit31  = a.bit63
c.bit63  = a.bit127
c.bit95  = b.bit63
c.bit127 = b.bit127

如果我使用 store(float array),cast to int array[4],最后是 load(int array),我会浪费很多时间。

我不知道如何使用 intrinsecs 操作 (SSEx x

【问题讨论】:

有什么问题? 发布一些代码。如果您需要替代方案,请确保我们首先了解您的问题。 你为什么不能简单地做c = (((a>>63)&1)<<31)|(((a>>127)&1)<<63)|(((b>>63)&1)<<95)|(((b>>127)&1)<<127) 现在您已经添加了最后一条语句(粗体部分) - 内部操作是特定于硬件的,即,对于每个处理器,指定的编译器都提供一组唯一的这些操作。那你用的是什么处理器?如果可能,请先在网络上查找(使用您最喜欢的搜索引擎),然后将这些内在操作的列表添加为您的问题的一部分。 我正在使用 SSEx | x 【参考方案1】:

你可以像这样只使用 SSE2 来做到这一点

__m128i t1 = _mm_shuffle_epi32(a,0xd0); //0xd0 = 3100 in base 4
__m128i t2 = _mm_shuffle_epi32(b,0xd0); //0xd0 = 3100 in base 4
__m128i t3 = _mm_unpackhi_epi32(t1,t2);
__m128i t4 = _mm_shuffle_epi32(t3,0xd8); //0xd8 = 3120 in base 4
__m128i t5 = _mm_and_si128(t4,_mm_set1_epi32(0x8000000));

这是一个工作示例

#include <x86intrin.h>
#include <stdio.h>

int main(void) 
    __m128i a = _mm_setr_epi32(1,-2,3,-4);
    __m128i b = _mm_setr_epi32(5,-6,7,-8);

    __m128i t1 = _mm_shuffle_epi32(a,0xd0); //0xd0 = 3100 in base 4
    __m128i t2 = _mm_shuffle_epi32(b,0xd0); //0xd0 = 3100 in base 4
    __m128i t3 = _mm_unpackhi_epi32(t1,t2);
    __m128i t4 = _mm_shuffle_epi32(t3,0xd8); //0xd8 = 3120 in base 4
    __m128i t5 = _mm_and_si128(t4,_mm_set1_epi32(0x8000000));  
    int x[4];
    _mm_store_si128((__m128i*)x,t5);
    for(int i=0; i<4; i++) printf("%x ", x[i]); printf("\n");

【讨论】:

以上是关于两个 __m128i 的两个位到一个 __m128i 的四个位 -SSE的主要内容,如果未能解决你的问题,请参考以下文章

将 __m256i 设置为两个 __m128i 值的值

将 __m256i 设置为两个 __m128i 值的值

如何在 MSVC 中高效地将两个 __m128d 转换为一个 __m128i?

将 __m256 拆分为两个 __m128 寄存器

AVX/SSE 将浮点符号掩码转换为 __m128i

如何将两个_pd 转换为一个_ps?