STM32F4,开FPU 用DSP计算开平方sqrt()要比arm_sqrt_f32要快,这是...

2019-12-12 18:25发布

本帖最后由 王涛 于 2019-3-6 12:52 编辑

STM32F4,开FPU 用DSP计算开平方sqrt()要比arm_sqrt_f32要快,这是为什么???

在做工作时遇到一个现象就是要做大量的单精度浮点数的开平方计算就自然想到了要用F4的dsp来就算。可是反复测试后发sqrt()要比arm_sqrt_f32要快,这是为什么?
貌似arm_math还不如math给力啊,这是什么回事?

arm_sqrt_f32
对于CM4带FPU的处理器来说,浮点数的平方根求解很简单,只需调用指令__sqrtf,仅需要14个时钟周期就可以完成。函数定义如下(在arm_math.h里面):

static __INLINE arm_status arm_sqrt_f32(
  float32_t in,
  float32_t * pOut)
  {
    if(in > 0)
    {

//      #if __FPU_USED
#if (__FPU_USED == 1) && defined ( __CC_ARM   )
      *pOut = __sqrtf(in);
#else
      *pOut = sqrtf(in);
#endif

      return (ARM_MATH_SUCCESS);
    }
    else
    {
      *pOut = 0.0f;
      return (ARM_MATH_ARGUMENT_ERROR);
    }

  }
有遇到过的吗?希望给点提示帮助一下。

在arm_math.h中是这么定义的:

             static __INLINE arm_status  arm_sqrt_f32(float32_t in, float32_t *pOut)
                     {
                        if(in > 0)
                             {
                                     //    #if __FPU_USED
                                    #if (__FPU_USED == 1) && defined ( __CC_ARM   )
                                              *pOut = __sqrtf(in);
                                   #else      
                                              *pOut = sqrtf(in);
                                   #endif
                                 return (ARM_MATH_SUCCESS);
                            }
                        else
                           {
                               *pOut = 0.0f;
                                return (ARM_MATH_ARGUMENT_ERROR);
                          }
               }   

        即开方用的函数是arm_sqrt_f32(),其中首先判断被开发的书是否大于0,只有大于0的才能进行运算,否则输出结果为0并返回“错误”标志。如果大于0,并且实用了FPU和__CC_ARM控制项,那调用__sqrtf()来完成编译,否则调用sqrtf()——这个sqrtf()是能在keil的math.h中找到的,即调用子函数来完成运算,而__sqrtf()呢?新出现的,相信大家都能猜到是什么玩意儿:对,就是VSQRT指令!因此要把这点性能也要发挥出来,就需要工程选项之C/C++选项卡的define中继续加入语句__CC_ARM才行。大家可以比较一下是否加入__CC_ARM编译后会汇编代码的差别巨大差别。

       当然,对于arm_sqrt_f32()函数还是有些麻烦,如果你确认被开方的书是大于等于0的,那就直接使用__sqrtf()函数完成运算,即一条简单的VSQRT指令。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
16条回答
XA144F
1楼-- · 2019-12-14 11:47
你加了编译控制项没有?要有__CC_ARM才能直接调用指令。
wye11083
2楼-- · 2019-12-14 14:15
王涛 发表于 2019-3-6 12:44
用这个算法那还要DSP 和FPU干什么呢?
对于CM4带FPU的处理器来说,浮点数的平方根求解很简单,只需调用指 ...

是,有硬件指令效率更可控。
王涛
3楼-- · 2019-12-14 19:36
XA144F 发表于 2019-3-6 12:49
你加了编译控制项没有?要有__CC_ARM才能直接调用指令。

没有犯这种低级错误。
在arm_math.h中是这么定义的:

             static __INLINE arm_status  arm_sqrt_f32(float32_t in, float32_t *pOut)
                     {
                        if(in > 0)
                             {
                                     //    #if __FPU_USED
                                    #if (__FPU_USED == 1) && defined ( __CC_ARM   )
                                              *pOut = __sqrtf(in);
                                   #else      
                                              *pOut = sqrtf(in);
                                   #endif
                                 return (ARM_MATH_SUCCESS);
                            }
                        else
                           {
                               *pOut = 0.0f;
                                return (ARM_MATH_ARGUMENT_ERROR);
                          }
               }   

        即开方用的函数是arm_sqrt_f32(),其中首先判断被开发的书是否大于0,只有大于0的才能进行运算,否则输出结果为0并返回“错误”标志。如果大于0,并且实用了FPU和__CC_ARM控制项,那调用__sqrtf()来完成编译,否则调用sqrtf()——这个sqrtf()是能在keil的math.h中找到的,即调用子函数来完成运算,而__sqrtf()呢?新出现的,相信大家都能猜到是什么玩意儿:对,就是VSQRT指令!因此要把这点性能也要发挥出来,就需要工程选项之C/C++选项卡的define中继续加入语句__CC_ARM才行。大家可以比较一下是否加入__CC_ARM编译后会汇编代码的差别巨大差别。

       当然,对于arm_sqrt_f32()函数还是有些麻烦,如果你确认被开方的书是大于等于0的,那就直接使用__sqrtf()函数完成运算,即一条简单的VSQRT指令。
90999
4楼-- · 2019-12-14 21:14
王涛 发表于 2019-3-6 12:44
用这个算法那还要DSP 和FPU干什么呢?
对于CM4带FPU的处理器来说,浮点数的平方根求解很简单,只需调用指 ...

肯定是硬件快啊。

一周热门 更多>