Чтоб оптимизатор не повырезал выполняемые команды, результат выполнения пишется в массив. Длина массива физически фиксирована, соответственно, количество элементов разных типов различно.
Не лучший подход. Я бы делал так. В измерительном цикле вызов функции через указатель на неё. И набор функций для тестирования операций плюс одна пустая функция, только с return;. Вначале указатель устанавливаем на пустую. Меряем время прохождения измерительного цикла. Затем ставим указатель на функцию с операцией. Снова мерим время, вычитаем из него первое время, для пустой и разность делим на кол-во циклов. Так и издержки на организацию учтутся и компилятор с своей оптимизацией не помешает.
long int tst(void (*Fn)(void), long int t)
{
long int m;
m=micros();
for(int i=0;i<10000;i++) {Fn();}
m=micros()-m-t;
if(t)
{
Serial.print(" t=");
Serial.print(m/10000.0);
Serial.print("usec ");
Serial.print(16*m/10000.0);
Serial.println("cycles");
delay(50);
}
return m;
}
void Fpusto(void){return;}
void FarduinoRead(void){digitalRead(5);return;}
void FarduinoWrite(void){digitalWrite(5, 0);return;}
void FarduinoPort(void){PORTB|=0x20;return;}
void setup()
{
Serial.begin(9600);
for(;;)
{
long int tb=tst(Fpusto, 0);
Serial.print("t0="); Serial.println(tb=tst(Fpusto, 0));
Serial.print("arduinoRead ");tst(FarduinoRead,tb);
Serial.print("arduinoWrite ");tst(FarduinoWrite,tb);
Serial.print("arduinoPort ");tst(FarduinoPort,tb);
delay(10000);
}
}
Выдало.
t0=9444
arduinoRead t=4.54usec 72.57cycles
arduinoWrite t=4.85usec 77.56cycles
arduinoPort t=0.13usec 2.07cycles
t0=9440
arduinoRead t=4.54usec 72.58cycles
arduinoWrite t=4.85usec 77.56cycles
arduinoPort t=0.13usec 2.08cycles
t0=9440
arduinoRead t=4.54usec 72.59cycles
arduinoWrite t=4.85usec 77.57cycles
arduinoPort t=0.13usec 2.09cycles
t0=9444
arduinoRead t=4.54usec 72.58cycles
arduinoWrite t=4.85usec 77.55cycles
arduinoPort t=0.13usec 2.08cycles
t0=9444
arduinoRead t=4.54usec 72.58cycles
arduinoWrite t=4.85usec 77.55cycles
arduinoPort t=0.13usec 2.09cycles
t0=9440
arduinoRead t=4.54usec 72.59cycles
arduinoWrite t=4.85usec 77.56cycles
arduinoPort t=0.13usec 2.09cycles
По крайней мере PORTB|=0x20 за 2 такта выдает.
Призадумавшись можна посчитать 2,09/2=1.045. Это коэффициент учитывающий прерывания. Т.е код на выполнение которого надо 1сек при запрещенных прерываниях будет выполнен за 1.045сек если их разрешить.
Меня больше смущает, что первая строчка Fill bytes дает примерно вдвое большее время, чем последующие.
Продублировал первый цикл перед первым измерением - время первого измерения снизилось до величины последующих.
Интересно было бы узнать о причине такого снижения производительности при первом проходе. На PC наблюдается похожее поведение, но там это связано с работой в защищенном режиме - под массив выделяется только первые 4к памяти, а последующие выделяются уже только в процессе реального обращения к этой памяти.
Вобще такое с кешем бывает. А у Дуо (Вы не указали у которого вдвое большее время, я вижу у Дуо) ядро ARM? а от этой херни любую подлянку можна ожидать.
И снова тестим железяку ардуиновскую. ESP8266-12E из IDE 1.6.5 по коду из #205. Только вместо прямой работы с портом сделал вызов милиса. Не умея я с портом работать у этой железки. Собственно основной вопрос теста и был, нужно ли напрямую с портом или итак сойдет. Заодно добавил + и * Имеем.
t0=1376
arduinoRead t=0.59usec 47.17cycles
arduinoWrite t=0.48usec 38.15cycles
millis() t=2.52usec 201.98cycles
i32+i32 t=0.34usec 27.05cycles
i32*i32 t=0.34usec 27.00cycles
t0=1376
arduinoRead t=0.59usec 46.99cycles
arduinoWrite t=0.48usec 38.02cycles
millis() t=2.52usec 201.54cycles
i32+i32 t=0.34usec 27.00cycles
i32*i32 t=0.34usec 27.00cycles
t0=1376
arduinoRead t=0.59usec 47.00cycles
arduinoWrite t=0.48usec 38.02cycles
millis() t=2.52usec 201.51cycles
i32+i32 t=0.34usec 27.00cycles
i32*i32 t=0.34usec 27.00cycles
Быстренько выводит. Про +и * - непонятно, думал быстрей. Про циклы - не уверен, реальную частоту железяки не знаю может 80МГц или 160МГц. Приведено для 80.
ПС.Глядя задумчиво на полученое кол-во циклов начинаю думать что частота таки 160МГц.
- ESP8266, пожалуй занимает одно из лучших мест по соотношению цена/производительность, где первое место, безусловно, у BluePill, однако, у последнего маловато памяти. ESP8266 почти за те же деньги предлагает в разы больше памяти.
- как и следовало ожидать, лидер по производительности stm32f407vet6 с частотой 168 МГц. Любопытно, что у него производительность выше, чем у stm32f103 даже на единицу тактовой частоты.
- еще одна непонятка с stm32f407: хотя у него заявлено FPU, на результатах этого не заметно. Одно из возможны объяснений - в нынешнем состоянии Arduino IDE эту возможность не поддерживает.
andriano, было бы очень здорово увидеть в общем зачете результаты ESP32. По идее, кроме повышенной частоты еще и обновленная архитектура ядер должны давать прирост в микрос, относительно 8266
Сразу видно - рост частоты в 2 раза не ускорил работу )))) Даже местами замедлил! Это не так.
Во первых, в том коде жестко забито соотношение времени и тактов 16, в стр.27. Т.к. на 16МГц за мксек 16 тактов. Потому на других частотах циклы заведомо не верны.
Ну и время мерить просто за счет измерения времени выполнения цикла - херня. Время на организацию цикла включается в время измеряемой команды. Более менее годится для сравнен разных команд на одной платформе (время на организацию цикла одинаково), но между разными платформами при коротких командах - отстой. Методику надо другую.
Ну и время мерить просто за счет измерения времени выполнения цикла - херня. Время на организацию цикла включается в время измеряемой команды. Более менее годится для сравнен разных команд на одной платформе (время на организацию цикла одинаково), но между разными платформами при коротких командах - отстой. Методику надо другую.
Утверждение во втором предложении не соответствует действительности.
Соответственно, остальные утверждения - херня и отстой. Где что - решайте сами.
PS. Да, опубликованный вариант теста привязан к тактовой частоте 16 МГц. В более поздних версиях от этого недостатка я избавился, заодно несколько изменив набор тестов. В планах - привести методику к виду более пригодному для адаптации к различным контроллерах. Но, увы, это не самые ближайшие планы.
PPS. На всякий случай напомню, что тест опубликован примерно через 3 месяца после моего первого знакомства с Ардуино. На тот момент я ни о чем кроме 16-мегагерцовых вариантов AVR просто не имел понятия. Но, с одной стороны, хотелось иметь какое-то общее представление, чего от этих контроллеров можно ожидать в плане производительности, а с другой - имелся некоторый опыт по написанию тестов для оценки этой самой производительности. Т.е. это довольно грубый инструмент, позволяющий тем не менее, получить некоторые рекомендации, на что обращать внимание при написании критичных участков программ.
Что там "не соответствует"? Там инкремент итератора есть, проверка его есть. И это на каждом проходе требует времени. Как и сама проверяемая команда. Сумму этих времён и имеем.
Про другие версии. Ну не знаю, люди из первого поста пользуют. Я про их результат отписался. Он очевидная лажа. Другие версии ни они ни я не знаю. Сам я по другому меряю, там выше код. ESP32 у меня нет, а то б посетил.
Пс. Ты так пишеш, как будто тя кто обвиняет в чем. Народ просто не понимает что к чему пригодно' вот и получают такие результаты. Я пояснил им.
А вот по принципу ax+b? Запускаем тест на 100- 1000-10000 проходов одной команды. Находим a b. Получи а - время выполнения команды - б накладные расходы. Позаботится что бы изменение количества проходов менять размеры вспомогательных переменных. Большим числом контрольных точек проверить линейность нарастания времени.
Если уж математически то измеренное время T=n*a+n*х+c где n-количество повторов, a-время организации одного прохода, инкремент счётчика, сравнение, переход...х-время на выполнение одной команды, его ищем, с-время инициализации цикла и на millis или что там есть. Влияние с уменьшаем увеличивая n. Если х>>а, то нормально и так, погрешность небольшая и для сравнения на одной платформе не существенна.
Это не скажи. Особенно в циклах. Заметь, циклы всегда должны быть цифрой целой. Ну такова природа процессора. Понятно погрешность есть. Но в любом случае результат должен быть близок к целому, по крайней мере на коротких операциях, немного более целого.
Ещё момент. Разница между результатами двух программ, из стартового и #205, по одной и той же функции 0.04мксек. Не много. И можно бы считать что это как раз и есть время на организацию цикла, вычесть ее из результатов первой проги, и бинго. Но длительнос коротких операций там и так 0.02мксек, значить по ним вообще непонятка, скорей всего число повторов цикла надо увеличивать для коротких операций.
Да, не стесняйтесь, дописуйте кому чего интересно, я синусы с умножениями в тест не вносил, т.к. меня интересовал только вопрос разницы между способами работы с портом.
Ещё , рассматривая результаты. digitalRead/Write у 328р - нормальные подпрограммы, имеют около сотни тактов, потому и вызывают желание прямой работы с портом. А у ESP 9-11 тактов.. Для подпрограммы мало, для прямого обращения многовато вроде.. Странно.
Да, всё странно, даже очень. И сам изначальный вопрос, и то что ты там пытаешься донести. А какой в этом смысл вообще... не пробовал задуматься? Даже теоретически - это всё блеф, а практически - просто лишено какого-либо смысла, как такового. Но тема живёт! )))
Пока опубликован только один - самый первый вариант. Увы, его зачастую приходится дорабатывать при тестировании новых плат. В планах сделать скетч, который бы был более или менее универсальным. Но пока такого нет.
Аддон фирмовый, через Board Manager ставленный. Несмотря на то, что сайт нам говорит о 20Mhz тактовой, в boards.txt имеем : nona4809.build.f_cpu=16000000L
Угу.
Чтоб оптимизатор не повырезал выполняемые команды, результат выполнения пишется в массив. Длина массива физически фиксирована, соответственно, количество элементов разных типов различно.
То есть, это не результат отдельной операции, а результат операции + вычисление индекса в массиве + запись в массив .. так? :)
Угу. Еще + организация цикла. Именно поэтому таблица начинается с проверки времени заполнения массива.
Не лучший подход. Я бы делал так. В измерительном цикле вызов функции через указатель на неё. И набор функций для тестирования операций плюс одна пустая функция, только с return;. Вначале указатель устанавливаем на пустую. Меряем время прохождения измерительного цикла. Затем ставим указатель на функцию с операцией. Снова мерим время, вычитаем из него первое время, для пустой и разность делим на кол-во циклов. Так и издержки на организацию учтутся и компилятор с своей оптимизацией не помешает.
Побаловался.
Выдало.
Меня больше смущает, что первая строчка Fill bytes дает примерно вдвое большее время, чем последующие.
Продублировал первый цикл перед первым измерением - время первого измерения снизилось до величины последующих.
Интересно было бы узнать о причине такого снижения производительности при первом проходе. На PC наблюдается похожее поведение, но там это связано с работой в защищенном режиме - под массив выделяется только первые 4к памяти, а последующие выделяются уже только в процессе реального обращения к этой памяти.
Так к автору теста обратитесь. Может разяснит.
Вобще такое с кешем бывает. А у Дуо (Вы не указали у которого вдвое большее время, я вижу у Дуо) ядро ARM? а от этой херни любую подлянку можна ожидать.
volatile разве не помогает в борьбе с компилятором?
И снова тестим железяку ардуиновскую. ESP8266-12E из IDE 1.6.5 по коду из #205. Только вместо прямой работы с портом сделал вызов милиса. Не умея я с портом работать у этой железки. Собственно основной вопрос теста и был, нужно ли напрямую с портом или итак сойдет. Заодно добавил + и * Имеем.
Что быстрее?
Или
i += a; // bool a
стандартом С не гарантируется, что a будет = 1, если true.
Допустим
Или вообще, а или 0 или 1.
Вопрос не об этом, а о том, что быстрее.
Допустим
Или вообще, а или 0 или 1.
Вопрос не об этом, а о том, что быстрее.
если a = digitalRead(pin); , то нет смысла заморачиваться о скорости исполнения
if
(a) i++;
// bool a
C if-ом быстрее.
если a = digitalRead(pin); , то нет смысла заморачиваться о скорости исполнения
if
(a) i++;
// bool a
А если так?
Это что было? Заявка на проведение работ по определению времени выполнения кода? Так иди пожалуйста в соответствующий раздел.
решил поднять старую тему, итак есть процедура вывода на 8и разрядный семисегментный led индикатор
с 8 ступенчатой ШИМ регулировкой яркостью, все работает, все хорошо.
но вторая часть данной процедуры - фактически говнокод, его задача погасить все индикаторы
на время примерное равное 540 микросекунд, какой одной командой можно реализовать задержку МК?
торможу, отмена вопросу
вот же есть команда delayMicroseconds
какой одной командой можно реализовать задержку МК?
если на сутки, то: гражданин, МК, вы задержаны за участие в несанкционированном путинге.
За прошедшее время пощупал еще несколько камешков:
(на каждый камень по два столбца: первый - время выполнения в мкс, второй - в тактах)
Из интересного следующее:
- ESP8266, пожалуй занимает одно из лучших мест по соотношению цена/производительность, где первое место, безусловно, у BluePill, однако, у последнего маловато памяти. ESP8266 почти за те же деньги предлагает в разы больше памяти.
- как и следовало ожидать, лидер по производительности stm32f407vet6 с частотой 168 МГц. Любопытно, что у него производительность выше, чем у stm32f103 даже на единицу тактовой частоты.
- еще одна непонятка с stm32f407: хотя у него заявлено FPU, на результатах этого не заметно. Одно из возможны объяснений - в нынешнем состоянии Arduino IDE эту возможность не поддерживает.
andriano, было бы очень здорово увидеть в общем зачете результаты ESP32. По идее, кроме повышенной частоты еще и обновленная архитектура ядер должны давать прирост в микрос, относительно 8266
Скетч из первопоста, ESP32 (WROOM-32) на двух частотах (выбираются в Arduino IDE):
40 MHz
80MHz
Да, с первым постом я знатно протупил
Спасибо
Скетч из первопоста, ESP32 (WROOM-32) на двух частотах (выбираются в Arduino IDE):
40 MHz
80MHz
Фигню намерил..
Сразу видно - рост частоты в 2 раза не ускорил работу )))) Даже местами замедлил! Это не так.
Во первых, в том коде жестко забито соотношение времени и тактов 16, в стр.27. Т.к. на 16МГц за мксек 16 тактов. Потому на других частотах циклы заведомо не верны.
Ну и время мерить просто за счет измерения времени выполнения цикла - херня. Время на организацию цикла включается в время измеряемой команды. Более менее годится для сравнен разных команд на одной платформе (время на организацию цикла одинаково), но между разными платформами при коротких командах - отстой. Методику надо другую.
Ну и время мерить просто за счет измерения времени выполнения цикла - херня. Время на организацию цикла включается в время измеряемой команды. Более менее годится для сравнен разных команд на одной платформе (время на организацию цикла одинаково), но между разными платформами при коротких командах - отстой. Методику надо другую.
Утверждение во втором предложении не соответствует действительности.
Соответственно, остальные утверждения - херня и отстой. Где что - решайте сами.
PS. Да, опубликованный вариант теста привязан к тактовой частоте 16 МГц. В более поздних версиях от этого недостатка я избавился, заодно несколько изменив набор тестов. В планах - привести методику к виду более пригодному для адаптации к различным контроллерах. Но, увы, это не самые ближайшие планы.
PPS. На всякий случай напомню, что тест опубликован примерно через 3 месяца после моего первого знакомства с Ардуино. На тот момент я ни о чем кроме 16-мегагерцовых вариантов AVR просто не имел понятия. Но, с одной стороны, хотелось иметь какое-то общее представление, чего от этих контроллеров можно ожидать в плане производительности, а с другой - имелся некоторый опыт по написанию тестов для оценки этой самой производительности. Т.е. это довольно грубый инструмент, позволяющий тем не менее, получить некоторые рекомендации, на что обращать внимание при написании критичных участков программ.
Что там "не соответствует"? Там инкремент итератора есть, проверка его есть. И это на каждом проходе требует времени. Как и сама проверяемая команда. Сумму этих времён и имеем.
Про другие версии. Ну не знаю, люди из первого поста пользуют. Я про их результат отписался. Он очевидная лажа. Другие версии ни они ни я не знаю. Сам я по другому меряю, там выше код. ESP32 у меня нет, а то б посетил.
Пс. Ты так пишеш, как будто тя кто обвиняет в чем. Народ просто не понимает что к чему пригодно' вот и получают такие результаты. Я пояснил им.
А вот по принципу ax+b? Запускаем тест на 100- 1000-10000 проходов одной команды. Находим a b. Получи а - время выполнения команды - б накладные расходы. Позаботится что бы изменение количества проходов менять размеры вспомогательных переменных. Большим числом контрольных точек проверить линейность нарастания времени.
Сам я по другому меряю, там выше код. ESP32 у меня нет, а то б посетил.
У меня есть, могу потестить. В каком сообщении код?
Если уж математически то измеренное время T=n*a+n*х+c где n-количество повторов, a-время организации одного прохода, инкремент счётчика, сравнение, переход...х-время на выполнение одной команды, его ищем, с-время инициализации цикла и на millis или что там есть. Влияние с уменьшаем увеличивая n. Если х>>а, то нормально и так, погрешность небольшая и для сравнения на одной платформе не существенна.
///В каком сообщении код?
В #205. Но он тоже на 16МГц заточен. Правь стр.12
В #205. Но он тоже на 16МГц заточен. Правь стр.12
Ок, в среду вечером выложу результат
Из 205. ESP32. 80 МГц.
Не радикальная разница по цифирям.
Это не скажи. Особенно в циклах. Заметь, циклы всегда должны быть цифрой целой. Ну такова природа процессора. Понятно погрешность есть. Но в любом случае результат должен быть близок к целому, по крайней мере на коротких операциях, немного более целого.
Ещё момент. Разница между результатами двух программ, из стартового и #205, по одной и той же функции 0.04мксек. Не много. И можно бы считать что это как раз и есть время на организацию цикла, вычесть ее из результатов первой проги, и бинго. Но длительнос коротких операций там и так 0.02мксек, значить по ним вообще непонятка, скорей всего число повторов цикла надо увеличивать для коротких операций.
Да, не стесняйтесь, дописуйте кому чего интересно, я синусы с умножениями в тест не вносил, т.к. меня интересовал только вопрос разницы между способами работы с портом.
Ещё , рассматривая результаты. digitalRead/Write у 328р - нормальные подпрограммы, имеют около сотни тактов, потому и вызывают желание прямой работы с портом. А у ESP 9-11 тактов.. Для подпрограммы мало, для прямого обращения многовато вроде.. Странно.
Странно.
Да, всё странно, даже очень. И сам изначальный вопрос, и то что ты там пытаешься донести. А какой в этом смысл вообще... не пробовал задуматься? Даже теоретически - это всё блеф, а практически - просто лишено какого-либо смысла, как такового. Но тема живёт! )))
Есть на руках Nano Every с ATMega4809 (20MHz). Каким скетчем промер сделать (если надо, конечное), чтобы академических споров не возникло?
Пока опубликован только один - самый первый вариант. Увы, его зачастую приходится дорабатывать при тестировании новых плат. В планах сделать скетч, который бы был более или менее универсальным. Но пока такого нет.
Итак, скетчем с первопоста протестирована такая штука: https://store.arduino.cc/usa/nano-every (натуральная, не с алиэкспресса).
Аддон фирмовый, через Board Manager ставленный. Несмотря на то, что сайт нам говорит о 20Mhz тактовой, в boards.txt имеем : nona4809.build.f_cpu=16000000L
Моя Nano Every купленная на Али, но в упаковке с голограммой и брошюркой внутри. И я за 18 баксов брал в декабре.