Провел ряд испытаний на своем stm32f429 по производительности с типом
float32_t и получил очень необычный результат
.
По порядку:
(чем больше попугаев - тем быстрее работает функция. Используется математический сопроцессор для 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() от DSPLIBsinf() =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).