将无符号字符加载到短整型的SSE操作

3

有没有更好的方法使用SSE将unsigned char数组加载到short中?例如

unsigned char foo1[16];

__m128i foo2 = _mm_loadu_si128((__m128i*)foo1);

我希望foo2能够用short int数据类型存储元素。

1个回答

4

不是很清楚你想要什么。

但是,如果你想要每个输入字节都有一个短值的SSE寄存器,那么你可能需要这样做(未经测试):

__declspec( align( 16 ) ) unsigned char foo1[ 16 ];
// Fill your array with data

const __m128i src = _mm_load_si128( ( __m128i* )foo1 );
const __m128i zero = _mm_setzero_si128();
const __m128i lower = _mm_unpacklo_epi8( src, zero );   // First 8 short values
const __m128i higher = _mm_unpackhi_epi8( src, zero );  // Last 8 short values

1
SSE4.1 pmovzxbw 一次加载8B也是一种选择,但是使用内部函数直接作为加载器很难安全地让编译器使用它。对于无符号数据,使用零来解包低半部分和高半部分效果很好。 - Peter Cordes
@PeterCordes 我认为使用0来解压应该会更快一些。双通道RAM可以同时传输128位批处理,而XMM寄存器的访问速度甚至比L1高速缓存还要快。 - Soonts
2
在Haswell上,您会在洗牌端口上遇到瓶颈,每个周期只有一个未打包的结果。两个负载都来自同一缓存行。SnB系列CPU可以每个时钟维持两个负载。SnB/IvB应该能够每个时钟维持两个pmovzxbw xmm,[mem],因为它们有两个128b的洗牌单元,特别是如果内存地址不使用索引寻址模式(因此可以微融合)。无论如何,如果您的数据是8B对齐但不是16B对齐,则2x pmovzx从内存中读取将更好。这也是较少的融合域uops(没有单独的负载),而且您不需要零向量。 - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接