首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SSE说明: Byte+Short

SSE说明: Byte+Short
EN

Stack Overflow用户
提问于 2012-05-17 22:02:46
回答 2查看 1.7K关注 0票数 6

我有非常长的字节数组,需要添加到short (或int)类型的目标数组中。这样的SSE指令存在吗?或者是他们的套装?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-05-17 22:18:35

您需要将每个8位值的向量解包为两个16位值的向量,然后将它们相加。

代码语言:javascript
运行
复制
__m128i v = _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
__m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0)); // vl = { 7, 6, 5, 4, 3, 2, 1, 0 }
__m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0)); // vh = { 15, 14, 13, 12, 11, 10, 9, 8 }

其中v是16 x 8位值的向量,vlvh是8 x 16位值的两个未打包向量。

请注意,我假设8位的值是无符号的,所以当解包到16位时,高位字节设置为0(即没有符号扩展名)。

如果你想对这些向量求和并得到一个32位的结果,那么一个有用的技巧是使用乘数为1的_mm_madd_epi16,例如

代码语言:javascript
运行
复制
__m128i vsuml = _mm_set1_epi32(0);
__m128i vsumh = _mm_set1_epi32(0);
__m128i vsum;
int sum;

for (int i = 0; i < N; i += 16)
{
    __m128i v = _mm_load_si128(&x[i]);
    __m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0));
    __m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0));
    vsuml = _mm_add_epi32(vsuml, _mm_madd_epi16(vl, _mm_set1_epi16(1)));
    vsumh = _mm_add_epi32(vsumh, _mm_madd_epi16(vh, _mm_set1_epi16(1)));
}
// do horizontal sum of 4 partial sums and store in scalar int
vsum = _mm_add_epi32(vsuml, vsumh);
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 8));
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4));
sum = _mm_cvtsi128_si32(vsum);
票数 7
EN

Stack Overflow用户

发布于 2016-06-29 21:17:23

如果您需要符号扩展字节向量而不是零扩展,请使用pmovsxbw (_mm_cvtepi8_epi16)。与unpack hi/lo指令不同,您只能从src寄存器的下半部/四分之一/八分之一执行pmovsx。

您可以直接从内存中pmovsx,即使内部使这非常笨拙。由于在大多数load+pmovsx上,混洗吞吐量比负载吞吐量更有限,因此执行两个CPU可能比执行一次加载+三次混洗更可取。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10637214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档