Видимые преимущества языка "C" сопровождается издержками, скрытыми расходами вычислительных ресурсов на указатели, пересылку данных "память <=> регистр", согласование разрядности, выравнивание и т. п.
Разница ожидаемого и реального времени выполнения критических участков кода чувствительна для промышленного программирования бюджетных микроконтроллеров, где главное — низкая цена.
Низкая цена — ключевое преимущество в массовом производстве.
Низкая цена естественно балансируется скромными вычислительными возможностями бюджетных микроконтроллеров.
Все сложные вычисления состоят из конечного ряда простых.
Представление о реальном времени выполнения примитивных операторов языка "C" открывает возможность для экспресс-оценки продуктивности критических участков кода на этапе проектирования через простой подсчёт числа примитивных операторов.
Замеры времени выполнения примитивных операторов языка "C" произведены на двух аппаратных платформах в равных условиях.
Сразу отметим, производительность Cortex M4 выше, чем Cortex M0, что естественно.
Общие наблюдения в результате замеров:
- операции int32 на ~20% быстрее, чем int16;
- double в 2 раза медленнее, чем float на Cortex M0;
- double в 27 раз медленнее, чем float на Cortex M4;
- арифметика float на Cortex M4 конкурентна int16 там же;
- деление - самая медленная операция всегда, что ожидаемо.
Результаты замеров далее в таблицах, где:
- fn: - формула оператора на языке "C";
- cc: - скорость выполнения оператора в тактах CPU;
- us: - скорость выполнения оператора в микросекундах (1E-6).
+=========================================
+-------------- # 1 ---------------------
+-- RELEASE at 12:26:28
+-- CPU:48 MHz, STM32 ARM Cortex M0
+-----------------------------------------
+-- cpu time of simple int16 "C"
fn: i3 = i1 + i2, cc: 7, us: 0
fn: i3 = i1 - i2, cc: 9, us: 0
fn: i3 = i1 * i2, cc: 8, us: 0
fn: i3 = i1 / i2, cc: 67, us: 1
fn: i3 = i1 % i2, cc: 70, us: 1
--- is:715826417 ---
+-----------------------------------------
+-- cpu time of simple int32 "C"
fn: l3 = l1 + l2, cc: 5, us: 0
fn: l3 = l1 - l2, cc: 6, us: 0
fn: l3 = l1 * l2, cc: 5, us: 0
fn: l3 = l1 / l2, cc: 61, us: 1
fn: l3 = l1 % l2, cc: 68, us: 1
--- ls:223077021 ---
+-----------------------------------------
+-- cpu time of simple float32 "C"
fn: f3 = f1 + f2, cc: 139, us: 2
fn: f3 = f1 - f2, cc: 182, us: 4
fn: f3 = f1 * f2, cc: 181, us: 3
fn: f3 = f1 / f2, cc: 568, us: 11
fn: f = (float)l, cc: 110, us: 1
fn: l = (int32)f, cc: 35, us: 1
--- fs:613566756 ---
+-----------------------------------------
+-- cpu time of simple float64 "C"
fn: d3 = d1 + d2, cc: 211, us: 4
fn: d3 = d1 - d2, cc: 235, us: 4
fn: d3 = d1 * d2, cc: 397, us: 7
fn: d3 = d1 / d2, cc: 877, us: 18
fn: d = (doubl)l, cc: 105, us: 1
fn: l = (int32)d, cc: 59, us: 0
--- ds:613566756 ---
+=========================================
+-------------- # 1 ---------------------
+-- RELEASE at 12:32:47
+-- CPU:48 MHz, STM32 ARM Cortex M4
+-----------------------------------------
+-- cpu time of simple int16 "C"
fn: i3 = i1 + i2, cc: 7, us: 0
fn: i3 = i1 - i2, cc: 6, us: 0
fn: i3 = i1 * i2, cc: 7, us: 0
fn: i3 = i1 / i2, cc: 12, us: 0
fn: i3 = i1 % i2, cc: 14, us: 0
--- is:715826417 ---
+-----------------------------------------
+-- cpu time of simple int32 "C"
fn: l3 = l1 + l2, cc: 5, us: 0
fn: l3 = l1 - l2, cc: 4, us: 0
fn: l3 = l1 * l2, cc: 4, us: 0
fn: l3 = l1 / l2, cc: 8, us: 0
fn: l3 = l1 % l2, cc: 9, us: 0
--- ls:223077021 ---
+-----------------------------------------
+-- cpu time of simple float32 "C"
fn: f3 = f1 + f2, cc: 6, us: 0
fn: f3 = f1 - f2, cc: 7, us: 0
fn: f3 = f1 * f2, cc: 5, us: 0
fn: f3 = f1 / f2, cc: 19, us: 0
fn: f = (float)l, cc: 4, us: 0
fn: l = (int32)f, cc: 3, us: 0
--- fs:613566756 ---
+-----------------------------------------
+-- cpu time of simple float64 "C"
fn: d3 = d1 + d2, cc: 120, us: 2
fn: d3 = d1 - d2, cc: 122, us: 2
fn: d3 = d1 * d2, cc: 84, us: 1
fn: d3 = d1 / d2, cc: 688, us: 13
fn: d = (doubl)l, cc: 59, us: 0
fn: l = (int32)d, cc: 31, us: 0
--- ds:613566756 ---
Использованное оборудование:
- ARM Cortex M0 — STM32F030R8T6;
- ARM Cortex M4 — STM32F303VCT6.
Погрешность измерения +/- 1 такт.
Сравнительная таблица результатов.
Простой отказ от int16 в пользу int32 повышает производительность участка программы приблизительно на 20%.
Есть риск свести "на нет" все преимущества FPU на Cortex M4, используя без должной осмотрительности double.