Решил проверить какова производительность микроконтроллеров AVR (ATmega) и ARM (STM32) потому что у меня не раз появлялся вопрос о скорости математических вычислений, особенно с плавающей точкой. Код тестовых функций.
Код:int8_t Test8(int8_t x) { x += 20; x *= 12; x -= 3; x /= 5; x = x % 178; return x; } int16_t Test16(int16_t x) { x += 102; x *= 14; x -= 32; x /= 52; x = x % 17820; return x; } int32_t Test32(int32_t x) { x += 10232; x *= 412; x -= 3286; x /= 3; x = x % 1782543424; return x; } float Test_f(float x) { x += 102.543f; x *= 412.54f; x -= 32.432f; x /= 3.432f; return x; } double Test_d(double x) { x += 102.543d; x *= 412.54d; x -= 32.432d; x /= 3.432d; return x; }
Код:Function Test8(byval X As Byte) As Byte X = X + 20 X = X * 12 X = X - 3 X = x / 5 X = X Mod 178 Test8 = X End Function Function Test16(byval X As Integer) As Integer X = X + 102 X = X * 14 X = x - 32 X = x / 52 X = X Mod 17820 Test16 = X End Function Function Test32(byval X As Long) As Long X = X + 10232 X = X * 412 X = x - 3286 X = X / 3 X = X Mod 1782543424 Test32 = X End Function Function Test_s(byval X As Single) As Single X = X + 102.543 X = X * 412.54 X = x - 32.432 X = x / 3.432 Test_s = X End Function Function Test_d(byval X As Double) As Double X = X + 102.543 X = X * 412.54 X = X - 32.432 X = X / 3.432 Test_d = X End Function
Обычная математика с различной разрядностью переменных.
Результаты тестов. Они в тактах и содержат сумму 1000 вызовов функций.
Код:STM32F103C8T6 - GCC 5.4, O2 + LTO. 1 byte = 34333 2 byte = 33757 4 byte = 38022 float = 193096 double = 1567736 Размер прошивки - 5304 байт. STM32F407VGT6 - GCC 5.4, O2 + LTO. 1 byte = 17050 2 byte = 17980 4 byte = 18024 float = 26022 double = 812320 Размер прошивки - 4872 байт. STM32H750VBT6 - GCC 5.4, O2. 1 byte = 26018 2 byte = 28020 4 byte = 30028 float = 26024 double = 30010 Размер прошивки - 5588 байт. STM32F030F4P6 - GCC 5.4, O2 + LTO. 1 byte = 122301 2 byte = 185132 4 byte = 246360 float = 1474306 double = 3404609 Размер прошивки - 12324 байт. ATmega328 - Bascom 2.0.8.1. 1 byte = 467566 2 byte = 1019516 4 byte = 2632705 Single = 2221984 Double = 5944625 Размер прошивки - 5188 байт. ATmega328 - GCC 3.3.0, O2. 1 byte = 556851 2 byte = 729659 4 byte = 1935740 Float = 7015553 Double = 7015559 Размер прошивки - 5418 байт.
Результат в виде таблицы. Во всех ячейках кроме строки "Размер прошивки", данные в тактах, необходимых на один вызов функции.
int8_t | int16_t | int32_t | Float | Double | Размер прошивки | |
ATmega328 - Bascom 2.0.8.1 | 467 | 1020 | 2633 | 2222 | 5945 | 5188 |
ATmega328 - GCC 3.3.0 | 557 | 730 | 1936 | 7016 | 7016 | 5418 |
STM32F030F4P6 | 122 | 185 | 246 | 1474 | 3404 | 12324 |
STM32F103C8T6 | 34 | 33 | 38 | 193 | 1567 | 5304 |
STM32F407VGT6 | 17 | 18 | 18 | 26 | 812 | 4872 |
STM32H750VBT6 | 26 | 28 | 30 | 26 | 30 | 5588 |
Как и ожидалось, 32-ух битное ядро быстрее, причем намного. Особенно это заметно на Cortex-M3 ядре. Cortex-M4, а тем более Cortex-M7 еще быстрее, особенно при работе с плавающей точкой, которая в них поддерживается аппаратно.
По результатам тестов AVR видно что бейсик оказался примерно таким же эффективным как компилятор Си с уровнем оптимизации O2. Компилятор Си не поддерживает float или double, потому что число тактов одинаковое.
ARM оказался быстрее чем AVR даже при работе с однобайтными переменными. Вероятно это связанно с отсутсвием в AVR аппартаной поддержки деления, но в STM32F030F4P6 ее тоже нет и тем не менее, результат гораздо лучше.