Игорь 2
Трансиверы, передатчики, РПУ => Software Defined Radio (SDR) => Тема начата: ra0ahc от Декабрь 17, 2020, 06:05:49 pm
-
Провел ряд испытаний на своем stm32f429 по производительности с типом float32_t и получил очень необычный результат 123123.
По порядку:
(чем больше попугаев - тем быстрее работает функция. Используется математический сопроцессор для float )
Циклы FOR или WHILE
for =6726 попугаев
while =6726 попугаев
Вывод: пофиг на сегодня что использовать. Лидера нет.
Логарифмы FAST_LOG2() & LOG2F()
fast_log2 программа с пред подсчетом таблицы
//fast-log2 d 3 раза быстрее log2f()
#define LogPrecisionLevel 5
#define LogTableSize (1<<(LogPrecisionLevel+1))
float32_t log_table[LogTableSize];
uint32_t q, qm1;
//fast log2 ----------------------------------
float fastLog2(float x) {
uint32_t bits= *(uint32_t *) &x;
// int bits = Float.floatToRawIntBits(x);
uint32_t e = (bits >> 23) & 0xff;
uint32_t m = (bits & 0x7fffff);
return (e == 0 ? log_table[m >> qm1] : e + log_table[((m | 0x00800000) >> q)]);
}
/**
* Compute lookup table for a given base table size.
*
* @param n The number of bits to keep from the mantissa. Table storage =
* 2^(n+1) * 4 bytes, e.g. 64Kb for n=13. Must be in the range
* 0<=n<=23
*/
void populateLUT(void) {
int size = 1 << (LogPrecisionLevel + 1);
q = 23 - LogPrecisionLevel;
qm1 = q - 1;
for (int i = 0; i < size; i++) {
log_table[i] = (float) (log(i << q) / log(2)) - 150;
}
}
//fast log2 ----------------------------------
Результат теста (сравниваем со стандартным, включенным в компилятор log2f(), и у fast_log2() точность 5 знаков )
fast_log2() =3445
log2f() =1388
Вывод: редкий случай когда сторонняя программа работает лучше чем встроенная.
SINF() & ARM_SIN_F32() от DSPLIB
sinf() =560.....2453 зависит от входных значений.
arm_sin_f32() =2551
Вывод: arm_sin_f32() от DSPLIB считает быстрее. Однако подправили что-то. sinf() ведет себя непредсказуемо по скорости. Лучше его не использовать.
Корень квадратный из float : fast_sqrt() & sqrtf() & arm_sqrt_f32()
fast_sqrt()
loat fast_sqrt(float a) {
float b = a;
int *x = (int*) (&b); // here I get integer pointer to float b which allows me to directly change bits from float reperesentation
int c = ((*x >> 23) & 255) - 127; // here I get mantisa, that is exponent of 2 (floats are like scientific notation 1.111010101... * 2^n)
if(c < 0) c = -((-c) >> 1); // ---
// |--> This is for halfing the mantisa
else c >>= 1; // ---
*x &= ~(255 << 23); // here space reserved for mantisa is filled with 0s
*x |= (c + 127) << 23; // here new mantisa is put in place
for(int i = 0; i < 5; i++) b = (b + a / b) / 2; // here normal square root approximation runs 5 times (I assume even 2 or 3 would be enough)
return b;
}
Результат теста:
fast_sqrt() =1030
sqrtf() =4393
arm_sqrt_f32()=3187
Вывод: не порадовала работа DSPLIB , ну fast_sqrt возможно неудачную нашел. Пока лидер опять стандартная функция sqrtf().
Дополнительный тест по sqrt(x*x+y*y) нужная тема для прорисовки спектра. Вычисление амплитуды.
Результат:
sqrtf(x*x+y*y) =3354
arm_sqrt_f32(x*x+y*y)=3035
Результат:
sqrtf() лучше, но отрыв сократился. Но там немного отличается процедура запуска функций arm_sqrt_f32(in, *out).
Абсолютное значение fabsf(x) & структура типа: (x?x:-x)
Сравнение с популярным строковым выбором по условию типа: x<0?-x:x
fabsf(x)=9757
(x?x:-x) = 7059
Результат: не выеживаемся и пишем fabsf(x).
-
Компилятор GCC 2017 года с опцией -Ofast
-
О попугаях...
1 попугай - это 10240 вычислений типа arr[ii]*= sqrtf(arr[ii]); где arr[ii] float32_t со значениям внутри 111.00003124
for (int f = 0; f < 10; f++) {
for (int ii = 0; ii < 1024; ii++) {
arr[ii] *= fabsf(arr[ii]);
arr[ii]*=-1;
}
}
-
-fno-math-errno -funroll-loops -fgraphite-identity -ffunction-sections -fdata-sections -ffat-lto-objects -ftree-vectorize
Добавить попробуйте
Да и -flto
Опции должны и компидятору и линкеру идти
-
Да с этими ключами производительность увеличилась на 15% !!!!!
-fno-math-errno -funroll-loops -ffunction-sections -fdata-sections -ffat-lto-objects -ftree-vectorize
-
Аккуратнее с плавающими константами иначе можете получить тормоза на ровном месте
https://mcuoneclipse.com/2019/03/29/be-aware-floating-point-operations-on-arm-cortex-m4f/
-
Да, спасибо, это старая болячка с float и double.
Давно перешел на запись констант 1.0f