C 优化加权移动平均值

C 优化加权移动平均值,c,embedded,stm32,moving-average,stm32h743,C,Embedded,Stm32,Moving Average,Stm32h743,环境:STM32H7和GCC 使用数据流:每250美国从SPI接收1个样本 我用256个样本做了一个“三角形”加权移动平均,就像但中间的样本是加权1,它围绕它形成一个三角形 我的样本存储在uint32\u t val[256]循环缓冲区中,它与uint8\u t write\u索引一起工作 样本为24位,样本的最大值为0x00FFFFFF uint8_t write_idx =0; uint32_t val[256]; float coef[256]; void init(void) {

环境:STM32H7和GCC
使用数据流:每250美国从SPI接收1个样本
我用256个样本做了一个“三角形”加权移动平均,就像但中间的样本是加权1,它围绕它形成一个三角形
我的样本存储在
uint32\u t val[256]
循环缓冲区中,它与
uint8\u t write\u索引一起工作

样本为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;
}
uint8\u t write\u idx=0;
uint32_t val[256];
浮点数系数[256];
void init(void)
{
uint8_t计数器=0;
//我计算三角形系数
对于(uint16_t c=0;c127)?--计数器:++计数器;
coef[c]/=128;
}
}
作废ACQ_完成(作废)
{
uint32_t moy=0;
//write_idx是用来包装的
val[write_idx++]=新样本;
//计算移动平均线(uint8_t)(c-write_idx)是用来换行的

对于(uint16_t c=0;c而言,这无疑应该以整数进行。它将更快更准确

这个处理器可以在一个周期内完成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;
uint32_t coef[256];
uint64_t moy=0;
for(无符号整数c=0;c<256;c++)
{
moy+=(val[c]*(uint64_t)coef[(c-write_idx)和0xFFu]);
}
moy>>=N;

您的平均值看起来像是一个循环卷积。在这种情况下,使用FFT可以获得较大的增益。除此之外,您的基准测试是否考虑了硬件FPU与软件浮点?您是否确实需要浮点?为什么?您使用的优化器选项是什么?如何编译?
-O2
通常是我想要的推荐用于ARM GCC。
-Ofast
降低了标准符合性,这可能会导致各种疯狂的事情。这不仅仅是一个FIR滤波器,具有三角形脉冲响应吗?CMSIS为此优化了功能(将使用C编译器可能不使用的固有M7 DSP和SIMD指令).Hi,我看到两个问题,
moy
将溢出,因为我的样本是24位的,
c-write\u idx
没有强制转换将无法正确包装。我认为当您编写
moy/=128
gcc时,它已经发生了变化(我可以检查disasm),因此它不会改善这一部分。很抱歉,我将代码中累加器的大小从32位更改为16位,当时我打算将其从32位更改为64位,正如我在文中所写的那样。