首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SSE中的乘-减

SSE中的乘-减
EN

Stack Overflow用户
提问于 2015-06-20 00:51:30
回答 3查看 516关注 0票数 9

我正在向量化一段代码,在某种程度上,我有以下设置:

代码语言:javascript
复制
register m128 a = { 99,99,99,99,99,99,99,99 }
register m128 b = { 100,50,119,30,99,40,50,20 }

我目前在这些寄存器中封装short,这就是为什么我每个寄存器有8个值。我想做的是,如果b的第i个值大于或等于a中的值,则将b中的第i个元素与a中的相应值相减(在本例中,a用常量99填充)。为此,我首先在ba之间使用了一个大于或等于的操作,对于这个例子,它产生了:

代码语言:javascript
复制
register m128 c = { 1,0,1,0,1,0,0,0 }

为了完成这个操作,我想使用乘法和减法,即在b中存储操作b -= a*c。然后,结果将是:

代码语言:javascript
复制
b = { 1,50,20,30,0,40,50,20 }

有没有做这件事的操作?我发现的是Haswell的融合操作,但我目前正在Sandy-Bridge上工作。此外,如果有人有更好的想法,请让我知道(例如,我可以做一个逻辑减法:如果1 in c,那么我减法,否则什么也不做。

EN

回答 3

Stack Overflow用户

发布于 2015-06-20 01:15:43

您实际上想要此代码的SSE版本,对吗?

代码语言:javascript
复制
if (b >= a)
    t = b-a
else
    t = b
b = t

因为我们想要避免SSE版本的条件,所以我们可以像这样摆脱控制流(注意,掩码是颠倒的):

代码语言:javascript
复制
uint16_t mask = (b>=a)-1
uint16_t tmp = b-a;
uint16_t d = (b & mask) | (tmp & ~mask)
b = d

我检查过_mm_cmpgt_epi16内部函数,它有一个很好的属性,它返回0x0000表示false或0xFFFF表示true,而不是返回单个位0或1(从而消除了第一次减法的需要)。因此,我们的SSE版本可能如下所示。

代码语言:javascript
复制
__m128i mask = _mm_cmpgt_epi16 (b, a)
__m128i tmp = _mm_sub_epi16 (b, a)
__m128 d = _mm_or_ps (_mm_and_ps (mask, tmp), _mm_andnot_ps (mask, b))

EDIT:哈罗德提到了一个简单得多的答案。如果您需要修改if/else的else部分,上面的解决方案可能会很有帮助。

代码语言:javascript
复制
uint16_t mask = ~( (b>=a)-1 )
uint16_t tmp = a & mask
b = b - tmp

SSE代码将为

代码语言:javascript
复制
__m128i mask = _mm_cmpgt_epi16 (b, a)
__m128i t = _mm_sub_epi16 (b, _mm_and_si128 (mask, a))
票数 4
EN

Stack Overflow用户

发布于 2021-03-18 01:35:08

另一种方法是,如果您的输入是无符号的,则可以计算

代码语言:javascript
复制
b = min(b, b-a);

这是可行的,因为如果是a>b,那么b-a就会回绕,并且保证会产生比b更大的值。对于a<=b,您将始终获得一个介于0b之间的值。

代码语言:javascript
复制
b = _mm_min_epu16(b, _mm_sub_epi16(b,a));

所需的_mm_min_epu16需要SSE4.1或更高版本(_mm_min_epu8只需要SSE2)。

票数 1
EN

Stack Overflow用户

发布于 2015-06-20 01:06:22

您可以将b复制到c,从c中减去a,在16位值中执行算术右移15位,对c的值进行补码,用a掩码c,最后从c中减去c

我对内部语法不太熟悉,但步骤如下:

代码语言:javascript
复制
register m128 c = b;
c -= a;
c >>= 15;
c = ~c;
c &= a;
b -= c;

下面是一个步骤更少的替代方案:

代码语言:javascript
复制
register m128 c = compare_ge(b, a);
c = -c;
c &= a;
b -= c;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30943332

复制
相关文章

相似问题

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