【发布时间】:2019-03-06 23:47:14
【问题描述】:
我想在 SSE 中实现一个简单的功能(像Izhikevich spiking neuron model 这样的程序)。它应该适用于 16 位有符号整数(8.8 定点),并且需要在某个积分步骤中检查溢出条件,并设置 SSE 掩码(如果发生溢出):
// initialized like following:
short I = 0x1BAD; // current injected to neuron
short vR = 0xF00D; // some reset threshold when spiked (negative)
// step to be vectorized:
short v0 = vReset;
for(;;) {
// v0*v0/16 likely overflows => use 32 bit (16.16)
short v0_sqr = ((int)v0)*((int)v0) / (1<<(8+4)); // not sure how "(v0*v0)>>(8+4)" would affect sign..
// or ((int)v0)*((int)v0) >> (8+4); // arithmetic right shift
// original paper used v' = (v0^2)/25 + ...
short v1 = v0_sqr + v0 + I;
int m; // mask is set when neuron fires
if(v1_overflows_during_this_operation()) { // "v1 > 0x7FFF" - way to detect?
m=0xFFFFFFFF;
else
m=0;
v0 = ( v1 & ~m ) | (vR & m );
}
但我还没有找到_mm_mul_epi16() 指令来检查乘法的高位字。为什么以及如何在 SSE 中实现 v1_overflows_during_this_operation() 这样的任务?
【问题讨论】:
-
你确定不是
short v1 = (v0*v0>>6) + v0 + I;?假设这是真正的 C,+的优先级高于>>,所以你写了v1 = v0*v0 >> (6 + v0 + I)。 NVM,你在我评论的时候就编辑了。 -
@PeterCordes 抱歉,我已经解决了问题。在原始论文中,它就像
v' = (v0^2)/25 + ...。不过后来我可以将定点乘法和除法混合成 32 位运算。 -
SSE 没有 16x16=>32 位乘法。它具有单独的低/高半乘法指令。希望我们可以为溢出检查做一次乘法运算,为实际结果做一次乘法运算。
-
您只担心上次编辑的标志,对吧? (因为 C 不保证负整数的算术右移)。您实际上并不需要有符号除法舍入语义(向 0 截断)而不是算术右移(向 -Inf 舍入),对吗?
-
见鬼!获得另一位或两位精度可能会使您的性能降低 2 倍,因为您必须计算另一个乘法结果来检查溢出,或者有效地扩大到 32 位(将每个向量的元素数量减半)。
标签: c vectorization sse simd intrinsics