Оптимизировать взвешенное скользящее среднее

Среда: STM32H7 и GCC
Работа с потоком данных: 1 образец, полученный от SPI каждые 250 мкс.
Я использую "треугольное" взвешенное скользящее среднее с 256 образцами, как это, но средний образец имеет вес 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 мкс, но я измерил с помощью вывода GPIO отладки, что "моя" часть занимает 252 мкс. Здесь
смоделирован код. Интересный факт: если я удалю
(uint32_t) бросить ближе к концу требуется 274 нас вместо 252 нас

Как мне сделать это быстрее?

Я думал использовать вместо float за coef (например, умножить на 1000), но мой uint32 переполнится

1 ответ

Это, безусловно, должно быть целым числом. Это будет и быстрее, и точнее.

Этот процессор может выполнять умножение 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;
Другие вопросы по тегам