Бутылочное горлышко или как измерять скорость выполнения критических участков кода

Тема в разделе "Arduino & Shields", создана пользователем roggedhorse, 8 фев 2013.

  1. roggedhorse

    roggedhorse Гик

    Как много времени затрачивает процессор на выполнение моего кода ?
    Вопрос возник, когда программа разрослась и некоторые исполнительные устройства моего девайса начали тормозить. Очевидно, пришло время оптимизировать код.

    Точно узнать можно следующим образом (далее речь пойдет об Arduino Mega):

    В начале main() разрешить таймер Timer/Counter 1
    Код (Text):
    TCCR1B = 0x00;
    TCNT1 = 0x00;
    TCCR1B = 0x01;
    Перед интересующим (критическим) куском кода поставить следующие строки:
    Код (Text):
    cli();
    TCNT1=0;
    А после интересующего куска кода следующие:
    Код (Text):
    uint32_t tc=TCNT1;
    sei();
    Затем вывести значение tc:
    Код (Text):
    Serial.println(tс);
    Это будет число тактов, в течение которых выполнялся критический участок кода, заключенный между cli() и sei().
    Если cli() и sei() не указать, то число тактов ts будет выше, поскольку в промежутках между TCNT1=0; и uint32_ttc=TCNT1; вполне могли выполняться прерывания.

    Поскольку таймер 16-битный, то оценивать скорость можно для сравнительно небольших кусков кода. Учитывайте это 65535 циклов = 4,1 миллисекунды на Atmega 2560 с тактовой частотой 16 МГц.

    Еще один простой способ:
    Написать PORTB |= _BV(7); перед критическим участком и PORTB &= ~(_BV(7)); после него.
    Подключить осцилограф к ноге Digital pin 13 и смотреть на экране сколько времени проходит между фронтами.

    Последний способ очень эффективен при отладке обработчиков прерываний.

    Надеюсь, кому-нибудь был я полезен
     
  2. hibiki

    hibiki Гик

    ага, только не надо закрывать в cli() .. sei() кусок кода, в том числе библиотечного, где используются прерывания :) нехорошо выйдет
     
  3. roggedhorse

    roggedhorse Гик

    Верно, об этом я не упомянул.
    Если в куске кода используются линейные вычисления, то использование cli/sei даст результат с точностью до 1 такта. Если есть подозрения, что вызовы из критического (оцениваемого) фрагмента кода могут затрагивать обработчики прерываний, то лучше cli/sei убрать. Погрешность будет не высокой, поскольку, как правило, обработчики прерывания крайне компактны.