Будет ли бесконечный цикл внутри цикла () работать быстрее?

Когда вы пишете типичный эскиз, вы обычно полагаетесь на вызов loop(), который вызывается многократно, пока работает Arduino. Однако перемещение и из функции loop() должно содержать небольшие накладные расходы.

Чтобы этого избежать, вы могли бы создать свой собственный бесконечный цикл, например:

void loop()
{
    while (true)
    {
        // do stuff...
    }
}

Является ли это жизнеспособным способом повышения производительности? Это вызовет другие проблемы, если loop() не вернется?

15 голосов | спросил Peter Bloomfield 21 FebruaryEurope/MoscowbFri, 21 Feb 2014 19:36:19 +0400000000pmFri, 21 Feb 2014 19:36:19 +040014 2014, 19:36:19

2 ответа


14

Часть кода на ядре ATmega, который выполняет setup () и loop (), выглядит следующим образом:

#include <Arduino.h>

int main(void)
{
        init();

#if defined(USBCON)
        USBDevice.attach();
#endif

        setup();

        for (;;) {
                loop();
                if (serialEventRun) serialEventRun();
        }

        return 0;
}

Довольно просто, но есть накладные расходы на serialEventRun (); там.

Давайте сравним два простых эскиза:

void setup()
{

}

volatile uint8_t x;

void loop()
{

    x = 1;

}

и

void setup()
{

}

volatile uint8_t x;

void loop()
{
    while(true)
    {
        x = 1;
    }
}

x и volatile просто для того, чтобы гарантировать, что он не оптимизирован.

В выпуске ASM вы получаете разные результаты: Сравнение двух

Вы можете видеть, что while (true) просто выполняет rjmp (относительный переход) назад несколько инструкций, тогда как loop () выполняет вычитание, сравнение и вызов. Это 4 инструкции против 1 инструкции.

Чтобы создать ASM, как описано выше, вам нужно использовать инструмент avr-objdump. Это включено в avr-gcc. Расположение зависит от ОС, поэтому проще всего искать его по имени.

avr-objdump может работать с файлами .hex, но у них отсутствует исходный источник и комментарии. Если вы только что создали код, у вас будет файл .elf, который содержит эти данные. Опять же, расположение этих файлов зависит от ОС - самый простой способ найти их - включить подробную компиляцию в настройках и посмотреть, где хранятся выходные файлы.

Выполните команду следующим образом:

  

avr-objdump -S output.elf> asm.txt

И просмотрите вывод в текстовом редакторе.

ответил Cybergibbons 21 FebruaryEurope/MoscowbFri, 21 Feb 2014 20:43:46 +0400000000pmFri, 21 Feb 2014 20:43:46 +040014 2014, 20:43:46
5

Ответ Cybergibbons довольно хорошо описывает генерации кода сборки и различий между двумя методами. Это должно быть дополнительным ответом, рассматривающим проблему с точки зрения практических различий, то есть, какая разница в любом из этих подходов будет в терминах времени выполнения . р>


Изменения кода

Я сделал анализ , включающий следующие варианты:

  • Основной void loop() (который встраивается в компиляцию)
  • Un-inlined void loop() (используя __attribute__ ((noinline)))
  • Loop с while(1) (который оптимизируется)
  • Loop с не оптимизированным while(1) (добавив __asm__ __volatile__("");. Это инструкция nop, которая предотвращает оптимизацию цикла, не приводя к дополнительным накладным расходам переменной volatile)
  • Un-inlined void loop() с оптимизированным while(1)
  • Un-inlined void loop() с не оптимизированным while(1)

Эскизы можно найти здесь .

Эксперимент

Я запускал каждый из этих эскизов в течение 30 секунд, тем самым накапливая 300 данные указывают каждый . В каждом цикле существовал 100-миллисекундный вызов delay (без которого плохие вещи происходят ) ,

Результаты

Затем я вычислил среднее время выполнения каждого цикла, вычитал 100 миллисекунд из каждого и затем построил результаты.

http: //raw2.github .com /AsheeshR /Arduino-петля-анализ /ведущий /Рисунки /timeplot.png

Заключение

  • Не оптимизированный цикл while(1) в void loop быстрее, чем оптимизированный компилятором void loop.
  • Разница во времени между не оптимизированным кодом и оптимизированным кодом Arduino по умолчанию невелика практически . Вам лучше скомпилировать с помощью avr-gcc и использовать свои собственные флаги оптимизации, а не в зависимости от IDE Arduino, чтобы помочь вам в этом (если вам нужны микросекундные оптимизации).

ПРИМЕЧАНИЕ: Фактические значения времени здесь не имеют значения, разница между ними. ~ 90 микросекунд времени выполнения включает вызов Serial.println, micros и delay. Суб>

ПРИМЕЧАНИЕ2: Это было сделано с использованием Arduino IDE и флагов компилятора по умолчанию, которые он предоставляет. Суб>

ПРИМЕЧАНИЕ 3: Анализ (график и расчеты) выполнялся с использованием R. Суб>

ответил asheeshr 22 FebruaryEurope/MoscowbSat, 22 Feb 2014 12:11:33 +0400000000pmSat, 22 Feb 2014 12:11:33 +040014 2014, 12:11:33

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132