1. 前言
neon加速对图像处理来说(具体到算法/代码上,是指多重循环,二维矩阵的运算),往往能起到奇效,其并行计算的特点能大大加快计算的速度,提高性能。对于其使用方法,网上有不少说明,在此不再累赘。
而对于一些算法来说,条件判断是必不可少的,同时也存在这种情况:对于图像的每个像素点的处理会根据不同的条件有不同的算法式子。那么这时候使用neon加速就比较麻烦了。网上对于这种情况的介绍并没有相关的例子,在此,特写这篇文档以做说明。下面例子忽略多重循环的外包,只对某个元素组进行说明,并且这个条件判断的前提是数值比较。
2. 判断指令
neon对于条件判断的处理,具体使用到:比较,异或,与,取反等基础指令。
- 比较:相等比较(
vceq[q]_type
),大于或等于比较(vcge[q]_type
)等 - 异或:
veor[q]_type
- 与:
vand[q]_type
- 取反:
vmvn[q]_type
,结合异或
指令可以成为同或
其中比较指令有个特点:结果为true时,所有位置1,结果为false,所有位置0,所以结果只能为整型。
以vcgt -> ri = ai > bi ? 1...1:0...0
为例:
指令:uint32x4_t vcgtq_f32 (float32x4_t __a, float32x4_t __b);
float32_t data[4] = {2.1,1.2,0.1,3.1};
float32x4_t a = vld1q_f32(data);
float32x4_t b = vdupq_n_f32(2.0);
uint32x4_t res = vcgtq_f32(a, b);//res[0]=0xFFFF,res[1]=0x0,res[2]=0x0,res[3]=0xFFFF
所以可以得知,当使用判断时,可以将比较为真
的置位,比较为假
清零,那么对于真值
的条件运算就可以通过指令与
得到对应元素的运算后的值,假值
的则会与
得的结果为0。下面举例说明。
3. 条件判断例子
以下例子为了简化原理,都使用uint
类型进行说明,如果是其他变量类型,都有个转换,截取,扩大的操作,使得代码复杂。
3.1 单if语句
-
C语言代码
uint fun(uint val) { uint res = 0; if(val > 20) { res += val; } return res; }
-
neon
uint32x4_t fun_neon(uint32x4_t val) { uint32x4_t res = vdupq_n_u32(0); uint32x4_t cmp = vcgtq_u32(val, vdupq_n_u32(20)); res = vandq_u32(vaddq_u32(res, val), cmp); return res; }
3.2 if…else语句
-
C语言代码
uint fun(uint val) { uint res = 100; if(val > 20) { res += val; } else { res -= val; } return res; }
-
neon
uint32x4_t fun_neon(uint32x4_t val) { uint32x4_t res = vdupq_n_u32(100); uint32x4_t cmp = vcgtq_u32(val, vdupq_n_u32(20)); uint32x4_t cmp2 = vmvnq_u32(cmp); uint32x4_t res1 = vandq_u32(vaddq_u32(res, val), cmp); uint32x4_t res2 = vandq_u32(vsubq_u32(res, val), cmp); res = vaddq_u32(res1, res2); return res; }
3.3 if…else if…else语句
-
C语言代码
uint fun(uint val) { uint res = 100; if(val > 20) { res += val; } else if(val < 10) { res -= val; } else { res *= val; } return res; }
-
neon
uint32x4_t fun_neon(uint32x4_t val) { uint32x4_t res = vdupq_n_u32(100); uint32x4_t cmp = vcgtq_u32(val, vdupq_n_u32(20)); uint32x4_t cmp2 = vcltq_u32(val, vdupq_n_u32(10)) uint32x4_t cmp3 = vmvnq_u32(veorq_u32(cmp, cmp2));//同或 uint32x4_t res1 = vandq_u32(vaddq_u32(res, val), cmp); uint32x4_t res2 = vandq_u32(vsubq_u32(res, val), cmp2); uint32x4_t res3 = vandq_u32(vmulq_u32(res, val), cmp3); res = vaddq_u32(res1, res2); res = vaddq_u32(res, res3); return res; }
博文为ganqiuye原创,转载请附上原文出处链接和本声明。
4. 结语
在判断条件中使用neon语句在实际上不一定就会比用c语言的普通代码快,因为这个转换的过程比较多,但在整体的算法上,使用neon语句化解这些比较语句还是很有必要的。在实际使用上,需要具体问题具体分析。对于一些难以转换的语句,可以将neon元素vst1
出成一个数组,然后再对每个数组的元素进行操作。