val = ( val < 0 ) ? 0 : val;
我想要上述指示。 (即)如果val小于dan 0那么将具有值'0'并且如果val小于0,那么'val'将是结果。 是否有任何一组霓虹灯指令将执行上述操作?
答案 0 :(得分:4)
有可能。使用NEON非常简单,因为它有最小和最大指令。
以下是使用float数据类型的示例。
float32x2_t clampToZero (float32x2_t value)
{
// generate a vector containing all zeros:
float32x2_t allZero = vdup_n_f32 (0.0f);
// take the parallel maximum between your value and zero.
return vmax_f32 (allZero, value);
}
答案 1 :(得分:0)
假设您正在处理16位有符号数据,d0包含值:
vshr.s16 d1, d0, #15
vbic.16 d0, d0, d1
这将成功。
或者,您可以诉诸:
vshll.s16 q0, d0, #16
vqshrun.s32 d0, q0, #16
甚至:
vmovl.s16 q0, d0
vqmovun.s32 d0, q0
即使你正在处理浮动数据,你也可以像s32一样处理它们:
vshr.s32 d1, d0, #31
vbic.32 d0, d0, d1
你知道,MSB是float和int上的符号位,0.0f就是0x000000000000。
简单明了。编辑:
人们似乎对上面代码中的位操作感到困惑。以下是解释:
int MinusIsZero(int n)
{
if (n < 0) n = 0;
return n;
}
正如您所看到的,这是一个非常简单的功能,可以满足OP的需求。
然而,由于其矢量性质,这种简单的“if”语句对SIMD来说是一个真正的痛苦。
幸运的是,在没有'if'的情况下,ALU指令非常好。
int MinusIsZero(n)
{
int mask;
mask = (n>>31);
n &= ~mask;
return n;
}
首先要做的事情是:如果右移有符号的int32 31位,结果只能是0x00000000(如果是正数)或0xffffffff(如果是负数)。
如果n为正,n&amp; ~0x00000000将导致n。
如果n为负数,则n&amp; ~0xffffffff将导致0。
OP想要的是什么。
到目前为止,对于像NEON这样的SIMD单元最有效的方法(ALU指令是最快的),即使在整数核心上,它也是非常理想的方法,因为它不会破坏CPSR。
不必要地破坏CPSR可能会严重削弱管道和乱序执行能力,具体取决于例行程序的其他部分。