我目前正在写有关ARM优化的演讲,特别是在矢量机(例如NEON)上作为最终目标。
而且由于向量机与if-else激流回旋系统的配合不好,因此我试图演示如何通过位黑客摆脱它们。
我以“绝对饱和”功能为例。这实际上是一个ABS例程,具有将结果限制为0x7fffffff的附加功能。
可能的最大负32位数字为0x80000000,这是非常危险的事情,因为val = -val;返回的初始值与0x80000000相同,这是由二进制补码系统(尤其是DSP操作)中的不对称性引起的,因此必须将其大部分过滤掉通过“饱和”。
int32_t satAbs1(int32_t val)
{
if (val < 0) val = -val;
if (val < 0) val = 0x7fffffff;
return val;
}
Run Code Online (Sandbox Code Playgroud)
以下是我将在汇编中编写的内容:
cmp r0, #0
rsblts r0, r0, #0
mvnlt r0, #0x80000000
bx lr
Run Code Online (Sandbox Code Playgroud)
下面是我实际上从上面的C代码中获得的东西:
satAbs1
0x00000000: CMP r0,#0
0x00000004: RSBLT r0,r0,#0
0x00000008: BX lr
Run Code Online (Sandbox Code Playgroud)
什么 编译器只是完全丢弃了饱和部分!
编译器似乎排除了val在第一条if语句之后为负的情况,如果它为0x80000000,则为true
还是函数应该返回无符号值?
uint32_t satAbs2(int32_t val)
{
uint32_t result;
if (val < 0) result = (uint32_t) -val; else …Run Code Online (Sandbox Code Playgroud) 我是AVX的新手(来自ARM NEON),并且令人不快地惊讶于AVX缺少许多U8算术,绝对差异在于他们之间缺失.
因此我不得不求助于max(a,b)-min(a,b)内联函数:
static inline __m256i _mm256_abd_epu8(__m256i a, __m256i b)
{
return _mm256_sub_epi8(_mm256_max_epu8(a, b), _mm256_min_epu8(a, b));
}
Run Code Online (Sandbox Code Playgroud)
我很好奇是否有更有效的方法来处理这个问题.
是的,我知道_mm256_sad_epu8,但我需要自己的差异,而不是总和.
我很感激任何输入,并且没关系AVX2任何向后兼容性.
提前致谢.