NEON 溢出检测
Posted
技术标签:
【中文标题】NEON 溢出检测【英文标题】:NEON Overflow detection 【发布时间】:2015-08-27 23:16:11 【问题描述】:我有一个长循环,其中对 8 位元素执行霓虹矢量加法。问题是一段时间后,几乎可以肯定部分或全部向量分量由于溢出而饱和。有没有一种快速的方法来检测这一点,以便我可以刷新结果,将向量归零并继续?我已经尝试过检查 C 和 V 标志,但似乎霓虹灯操作没有设置它们。
编辑:这里是感兴趣的代码,稍微简化了一点。还有,我升级到16位了,还是会溢出
int16x8_t Sum;
for(int C = 0; C < 100; C++)
// Sum += |a - b|
Sum = vabaq_u16(
Sum,
vld1q_u16((uint16_t *)a),
vld1q_u16((uint16_t *)b)
);
【问题讨论】:
如果您显示一些代码可能会有所帮助,以便人们可以准确地看到您的意思 我认为 100 项目数之一是简化?我看不出你怎么可能溢出 16 位,否则累积 8 位值(65535 / 255 = 257 > 100)。 另外,vld1q_u16((uint16_t *)a)
中的指针看起来很可疑 - a
是什么类型?如果它仍然是一个 8 位数据的数组,那么这段代码就完全被破坏了。
是的,这是一个简化,是的,a 有问题。 a 是 16 位的,但它是有符号的,现在我使用的是 vld1q_s16 和 (int16_t*)
【参考方案1】:
如果您使用VQADD
进行求和,它不仅会使值饱和(钳位)而不是溢出和回绕(这本身可能是可取的),而且还会设置饱和标志(位 27)每当发生这种情况时,都在 FPSCR 中。设置后,需要手动清除该标志,方法是写回第 27 位为零的 FPSCR 值。
一种可能的替代方法,具体取决于算法的其余部分如何使用结果,可能是将累加器拆分为两个寄存器,并对输入向量的每一半使用扩展操作 (VABAL
) 来累加 16-位元素,那么您可以简单地以预定时间间隔刷新结果,而无需显式检查。由于溢出 16 位累加器所需的无符号 8 位值的最小数量为 258(65535/255 = 257),因此如果循环每 257 次或更少的迭代刷新一次结果,则溢出是不可能的。
【讨论】:
好的,我编辑了问题,添加了一些代码。我将调查检查 vabaq 是否使用 vqadd 来累积结果。如果没有,我可能会创建自己的内在函数,可能使用 vaba 和 vqadd,但我仍然需要对其进行一些研究。 您仍然可以使用扩展方法和一对vabal
内在函数。想一想,这样您实际上就不需要浪费时间检查溢出 - 只需在大约每 256 次迭代后刷新结果向量,您就可以保证它永远不会发生。以上是关于NEON 溢出检测的主要内容,如果未能解决你的问题,请参考以下文章