Arm 裁剪的高效实现

Arm 裁剪的高效实现,arm,simd,neon,Arm,Simd,Neon,在一个循环中,我必须实现一种剪裁 if ( isLast ) { val = ( val < 0 ) ? 0 : val; val = ( val > 255 ) ? 255 : val; } 有什么建议可以加快速度吗? 谢谢 编辑- 现在的剪辑看起来像- for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { Int sum;

在一个循环中,我必须实现一种剪裁

if ( isLast )
{
    val = ( val < 0 ) ? 0 : val;
    val = ( val > 255 ) ? 255 : val;        
}
有什么建议可以加快速度吗? 谢谢

编辑- 现在的剪辑看起来像-

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                            \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

如果maxVal是UCHAR\u MAX、CHAR\u MAX、SHORT\u MAX或USHORT\u MAX,则您只需使用neon将int转换为所需的数据类型,方法是使用饱和度进行强制转换

以身作则

// 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) 

如果您不想使用多个数据功能,您仍然可以使用这些指令,只需加载和读取其中一个通道。

使用normal compares with NEON几乎总是一个坏主意,因为它会将NEON寄存器的内容强制放入通用ARM寄存器中,这需要大量的周期

您可以使用vmin和vmax指令。下面是一个将整数数组钳制为任何最小/最大值的小示例

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);
  }
} 
void clampArray(最小整数,
int最大值,
int*输入,
int*输出,
国际货币基金组织(国际货币基金组织)
{
//使用每条车道的最小值和最大值获取两个霓虹灯值:
int32x2\u t下限=vdup\u n\u s32(最小值);
int32x2\u t更高=vdup\u n\u s32(最大值);
int i;

对于(i=0;iGOD解决方案-另请参见
vmax(q)\u xxx
/
vmin(q)\u xxx
。maxVal是255。我们可以以某种方式使用vqshrn吗?您可以链接两个强制转换操作:vqmovun\u s16(vqmovn\u s32(…)但是Nils的回答更灵活和完整。这就减少了从200毫秒到18ms的开销。谢谢!你可以考虑删除循环中的条件分支。例如,如果“ISESTATE”在循环中没有变化,你总是可以剪辑到(LO,HI)(LO,HI)预先设置的地方(0255),(最后),(-0x800 000 000,0x7FFFFFF)。否则。
// 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) 
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);
  }
}