在循环中,我必须实现一种剪辑
if ( isLast )
{
val = ( val < 0 ) ? 0 : val;
val = ( val > 255 ) ? 255 : val;
}
然而,这个“剪辑”几乎占用了Neon中循环执行时间的<一半。 这就是整个循环的样子 -
for (row = 0; row < height; row++)
{
for (col = 0; col < width; col++)
{
Int sum;
//...Calculate the sum
Short val = ( sum + offset ) >> shift;
if ( isLast )
{
val = ( val < 0 ) ? 0 : val;
val = ( val > 255 ) ? 255 : val;
}
dst[col] = val;
}
}
这是剪辑在霓虹灯
中实施的方式 cmp %10,#1 //if(isLast)
bne 3f
vmov.i32 %4, d4[0] //put val in %4
cmp %4,#0 //if( val < 0 )
blt 4f
b 5f
4:
mov %4,#0
vmov.i32 d4[0],%4
5:
cmp %4,%11 //if( val > maxVal )
bgt 6f
b 3f
6:
mov %4,%11
vmov.i32 d4[0],%4
3:
这是变量到寄存器的映射 -
isLast- %10
maxVal- %11
有什么建议让它更快? 感谢
剪裁现在看起来像 -
"cmp %10,#1 \n\t"//if(isLast)
"bne 3f \n\t"
"vmin.s32 d4,d4,d13 \n\t"
"vmax.s32 d4,d4,d12 \n\t"
"3: \n\t"
//d13 contains maxVal(255)
//d12 contains 0
此部分代码消耗的时间已从 223ms降至18ms
答案 0 :(得分:8)
使用与NEON的正常比较几乎总是一个坏主意,因为它会强制NEON寄存器的内容进入通用ARM寄存器,这会花费很多周期。
您可以使用vmin和vmax NEON指令。这是一个将整数数组钳制到任何最小/最大值的小例子。
void clampArray (int minimum,
int maximum,
int * input,
int * output,
int numElements)
{
// get two NEON values with your minimum and maximum in each lane:
int32x2_t lower = vdup_n_s32 (minimum);
int32x2_t higher = vdup_n_s32 (maximum);
int i;
for (i=0; i<numElements; i+=2)
{
// load two integers
int32x2_t x = vld1_s32 (&input[i]);
// clamp against maximum:
x = vmin_s32 (x, higher);
// clamp against minimum
x = vmax_s32 (x, lower);
// store two integers
vst1_s32 (&output[i], x);
}
}
警告:此代码假定numElements总是2的倍数,我还没有测试过。
如果使用vminq / vmaxq指令一次处理四个元素并且每次迭代加载/存储四个整数,您甚至可以加快速度。
答案 1 :(得分:3)
如果maxVal是UCHAR_MAX,CHAR_MAX,SHORT_MAX或USHORT_MAX,您可以通过使用饱和度进行转换,将int中的neon转换为所需的数据类型。
以示例
// Will convert four int32 values to signed short values, with saturation.
int16x4_t vqmovn_s32 (int32x4_t)
// Converts signed short to unsgigned char, with saturation
uint8x8_t vqmovun_s16 (int16x8_t)
如果您不想使用多数据功能,只需加载并阅读其中一条通道即可使用这些说明。