优化加权移动平均 我怎样才能更快地完成它?

问题描述

环境:STM32H7 和 GCC
处理数据流:每 250 us 从 SPI 接收 1 个样本
我做了一个带有 256 个样本的“三角形”加权移动平均线,比如 this,但中间样本的权重为 1,它围绕它形成一个三角形
我的样本存储在 uint32_t val[256] 循环缓冲区中,它与 uint8_t write_index
样本为 24 位,样本的最大值为 0x00FFFFFF

uint8_t write_idx =0;
uint32_t val[256];
float coef[256];

void init(void)
{
  uint8_t counter=0;
  // I calculate my triangle coefs
  for(uint16_t c=0;c<256;c++) 
  {
    coef[c]=(c>127)?--counter:++counter;
    coef[c]/=128;
  }
}

void ACQ_Complete(void)
{
  uint32_t moy=0;
  // write_idx is meant to wrap
  val[write_idx++]= new_sample;
  // calc moving average (uint8_t)(c-write_idx) is meant to wrap
  for(uint16_t c=0;c<256;c++)
    moy += (uint32_t)(val[c]*coef[(uint8_t)(c-write_idx)]);
  moy/=128;
}

我必须在 250 us 的时间跨度内进行计算,但我用调试 GPIO 引脚测量了“moy”部分需要 252 us
代码模拟here
有趣的事实:如果我在接近尾声时移除 (uint32_t) 演员表,它需要 274 us 而不是 252 us

我怎样才能更快地完成它?

我曾考虑对 uint32 使用 float 而不是 coef(例如乘以 1000),但我的 uint32 会溢出

解决方法

这无疑应该以整数形式完成。它会更快更准确。

这个处理器可以在一个周期内做 32x32+64=64 的乘法累加!

将所有系数乘以 2 的幂(不是评论中提到的 1000),然后在最后向下移动而不是除以。

uint32_t coef[256];

uint64_t moy = 0;

for(unsigned int c = 0; c < 256; c++)
{
   moy += (val[c] * (uint64_t)coef[(c - write_idx) & 0xFFu]);
}

moy >>= N;