Странное поведение millis()
- Войдите на сайт для отправки комментариев
Добрый день!
Хотел посчитать разницу выполнения по времени двух вариантов вычислений. Т.е. берем перед вычислениями (в цикле многократно, чтобы время "ощутить") , вызываем millis(), затем цикл с функцией и далее опять вызываем millis () - смотрим разницу времен = бинго :)
Однако на вывод разница времен попадала почему-то нулевая. После мЫшления над разными возм. причинами взял совсем простую уж прогу (занимается подсчетом времени выполнения цикла и выводом результатов по Serial
#define MAXSTEP 100000L
void setup() {
// put your setup code here, to run once:
Serial.begin( 9600 ) ;
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
unsigned char incomingByte = 0 ;
long i; double x;
unsigned long millis_begin , millis_end ;
millis_begin = millis() ;
for ( i=0 ; i < MAXSTEP ; i ++ ) {
x = sin ( (float)( x + 1.) ) ;
}
millis_end = millis() ;
Serial.println ( i ) ;
// Serial.println ( x) ; ----------- ВОТ ЭТО ВАЖНО! не включена строка эта
Serial.println( millis_begin ) ;
Serial.println( millis_end ) ;
// read the incoming byte:
while( incomingByte = Serial.read () != 'y' ) {
; // Это просто чтоб ждало ввода "y" для следующего оборота loop() а не фигачило изо всех сил
}
delay(1000);
}
На печать выводится при запуске этого варианта:
100000
0
0
Т.е. время както не затрачено на выполнение цикла :)
Включаем в проге строчку с печатью "x" (и больше ниче не трогаем! )
#define MAXSTEP 100000L
void setup() {
// put your setup code here, to run once:
Serial.begin( 9600 ) ;
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
void loop() {
unsigned char incomingByte = 0 ;
long i; double x;
unsigned long millis_begin , millis_end ;
millis_begin = millis() ;
for ( i=0 ; i < MAXSTEP ; i ++ ) {
x = sin ( (float)( x + 1.) ) ;
}
millis_end = millis() ;
Serial.println ( i ) ;
Serial.println ( x) ; ----------- ВОТ ЭТО ВАЖНО! теперь включили вывод для "x"
Serial.println( millis_begin ) ;
Serial.println( millis_end ) ;
// read the incoming byte:
while( incomingByte = Serial.read () != 'y' ) {
; // Это просто чтоб ждало ввода "y" для следующего оборота loop() а не фигачило изо всех сил
}
delay(1000);
}
На выводе при запуске имеем:
100000
0.93
0
11764
То есть бац - и тут же millis() выдал для времени выполнения какое-то осмысленное уже число....
Что на самом деле происходит, почему какаято левая совершенно (не имеющая отношения к millis вообще строка все так меняет???
Poprobyi:
ОК, сработало (с вариантом без печатания "x" ) ! Спасибо.
Правда, глубинный смысл произошедшего остался неясен - ведь millis() как бы не связан с x-ом.... И остальные переменные вроде объявляюются как неволатильные - и ниче плохого от этого не происходит..
Вариант, что без объявления "volatile" цикл пролетается слишком быстро (как бы не вычисляя ниче) вроде не проходит - я там задавал MAXSTEP до миллиона - а разница времен оставалась одинаково никакой, что миллион, что тысяча степов. И "i" ведь тоже печатался правильный - то есть по идее цикл хотя бы на уровне i++ что-то делал - время на миллионе шагов какое-никакое бы должно уйти.
то есть по идее цикл хотя бы на уровне i++ что-то делал - время на миллионе шагов какое-никакое бы должно уйти.
Спасибо, познавательно вышло. В первоначальной программке сравнения вычислений тоже переменная, которой присваивалось значение функции, не использовалось - после объявления волатильной сразу время выполнения образовалось, вполне пропорциональное количеству шагов цикла. Кстати, не думал , что такая мелкофигня, как Атмега 328 так быстро на самом деле считает простую, правда, арифметику.. На 286 по воспоминаниям , как бы не медлееннее считалось.
Извините, а с чего она должна "медленее" считать? Теже 16 мегагерц, та же регистровая арифметика .. ваще-то.
А имея значительно больше регистров код вычислений может быть куда как производительней. Но, чтобы получить "весь кайф", надо помнить что микропроцессор .. байтовый. В лучшем случае, 16-и разрядный. А соответственно, убирать по максиуму long, unsigned long, особенно из параметров функций (uint16 против uint32 экономит по 6 байт на параметр при каждом вызове). Из-за чего и сделал себе 8 и 16 разрядные delay(), millis() и micros() .. чего и вам настоятельно рекомендую. Для больших интервалов .. считайте секундами, минутами и часами .. :)