Как раз таки эти флаги только загромождают код. Нежелательно, если считывание идет непосредственно после изменением сигнала на выходе. Хотя, при использовании digitalRead это не важно.)
Конденсаторы на аналоговых входах точно не помешают.
Переменные резисторы штука таинственная, контакт бегунка с подковкой ненадёжен, а кручение рукой процесс неторопливый. Дребезжат так, что кнопки позавидуют. Я как-то забыл в регуляторе яркости светодиодной ленты поставить, при первом же включении вспомнил!
а по Вашему опыту какую лучше емкость кондеев взять - 0.01 или 0.1? Потенциометры на 10 кОм.
Использовать digitalRead() для вывода, настроенного на выход тоже не лучшая идея. Лучше использовать переменные-флаги, получится и быстрее и экономнее по памяти. И скетч будет короче и понятнее.
экономичнее по памяти, чем в случае с флагами.
Флаг занимает один байт. Сколько занимает каждый вызов digitalRead? Сэкономить не поучится.
Флаг занимает один байт. Сколько занимает каждый вызов digitalRead?
Ноль байт.
Цитата:
Сэкономить не поучится.
Почему?
И давно функции перестали место занимать? И вызов любой функции? Получается если написать скетч из одних функций, то он будет нулевого размера? Поинтересуйтесь как осуществляется вызов/выполнение/возврат из функции и сравните с несчастным байтом на флаг.
Поинтересуйтесь как осуществляется вызов/выполнение/возврат из функции и сравните с несчастным байтом на флаг.
Вам тонко намекают, что флаг занимает место в той памяти, которой всего 2К, а вызовы функции живут в той, которой 32К. Поинтересуйтесь как устроена память в этой архитектуре.
Поэтому 32К и не хватает. Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18. Если в скетче 10 лишних вызовов это 180 байт. Продолжаем экономить 1 байт в 2К.
apg_777, чего закусился-то? Вопрос того, что экономим, зависит от критериев оптимизации. Их тут нет. Кто как хочет, так и пишет.
Дело, конечно, хозяйское. Вариантов решения конкретных задач много, что даже здесь видно — есть любители millis, я предпочитаю подобные задачи решать через прерывания. Вариант через millis 86 строк, а я лентяй, у меня получилось 36 строк :)
Есть такие люди.
А с меньшим размером программы можно контроллер попроще и подешевле взять. Например светильник от AlexGyver (который без Wi-Fi и на ленте, а не матрице) можно запросто переделать на ATtiny85, запускал на 240 светодиодов. Поправил одну строку и скетч уместился в 8К. И вместо платы nano одна микросхема 4x4 кв.мм.
Вывод какой? Чем меньше строк, тем лучше? А тогда зачем флаги - лишние строки ведь?
А вообще, оптимизация по размеру памяти последнее дело, для этого должна быть причина, а не просто так.
Вывод какой? Чем меньше строк, тем лучше? А тогда зачем флаги - лишние строки ведь?
А вообще, оптимизация по размеру памяти последнее дело, для этого должна быть причина, а не просто так.
Лишняя строка одна при объявлении, дальше наоборот меньше получается.
Оптимизация никогда не повредит. Привычка вырабатывается сразу и потом переделать себя очень сложно. У меня выработалась привычка писать максимально оптимальный код, а кому-то главное чтобы работало, не хватит, возьмём что-нибудь помощнее.
Просто в 1981 году у меня была машина с 4К, а втиснуть надо было общение с нехилым аппаратным комплексом и при этом довольно быстро производить массу расчётов. Зато память там была на ферритовых кольцах!
Пример второго подхода — игра Syberia 3. 20 ГБ установщик и тормоза даже на супер-пупер игровых компьютерах.
Но это общение лучше перенести куда-нибудь в отвлечённые темы. Здесь не по теме больше не комментирую.
И давно функции перестали место занимать? И вызов любой функции? Получается если написать скетч из одних функций, то он будет нулевого размера? Поинтересуйтесь как осуществляется вызов/выполнение/возврат из функции и сравните с несчастным байтом на флаг.
Занимать где?
Вы не путайте, в Гарвардской архитектуре код располагается не в ОЗУ и, соответственно, места там не занимает.
apg_777 пишет:
Поэтому 32К и не хватает. Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18. Если в скетче 10 лишних вызовов это 180 байт. Продолжаем экономить 1 байт в 2К.
Вам не хватает 32К для мигания трех светодиодов? Или Вы надеетесь сэкономленную в одном проекте флеш-память перенести в другой проект?
Старой гвардии кажется что они пишут "максимально оптимальный код".))) На самом деле с этим и без них вполне справляется компилятор. Зато все эти их извращения с оптимизацией по размеру только ухудшают читаемость исходного текста и вносят возможность дополнительных ошибок. Со всеми вытекающими из всего этого временными затратами.
Старой гвардии кажется что они пишут "максимально оптимальный код"...
На самом деле намного смешнее.
Меняется аппаратура, меняются соотношения, и то, что раньше было верхом оптимальности вдруг оказывается очень далеким от нового оптимума.
Просто парочка примеров применительно ПК.
Первые VGA адаптеры подключались по ISA. Соответственно, обмен между процессором и видеопамятью был во много раз медленнее, чем с ОЗУ. В некоторых случаях более чем в 10 раз. Потом появилась AGP, а на видеокартах стали ставить GDRAM, которая была быстрее DRAM, в результате обмен с видеопамятью уже раза в 2-3 превосходил по скорости обмен с основным объемом ОЗУ. Соответственно, те способы работы с графикой, которые применялись, ориентируясь на ISA, стали совершенно неоптимальными.
С появлением FPU и суперскалярных процессоров, опять же, существенно (на порядки, причем более, чем на один) изменилось соотношение времени на выполнение вычислений с плавающей точкой ко времени выполнения ветвления. Те алгоритмы, которые учебники предлагали в качестве оптимальных, перестали быть таковыми.
Да даже на AVR много тонкостей. В частности, "оптимизаторы" обычно знают, что использование float ведет к существенному увеличению времени выполнения, но, зачастую, им невдомек, что целочисленное деление long занимает гораздо больше времени, чем любая арифметическая операция с плавающей точкой.
Да даже на AVR много тонкостей. В частности, "оптимизаторы" обычно знают, что использование float ведет к существенному увеличению времени выполнения, но, зачастую, им невдомек, что целочисленное деление long занимает гораздо больше времени, чем любая арифметическая операция с плавающей точкой.
Что-то я засомневался в этом утверждении и решил проверить:
#define NN 10000
volatile long int a, b, c;
volatile float af, bf, cf;
uint32_t Tstart, Tstop;
void setup()
{
Serial.begin(115200);
Serial.println("Start");
randomSeed(80000);
Tstart = millis();
for (int i = 0; i < NN; i++)
{
a = random(100000);
b = random(100000);
c = a / b;
}
Tstop = millis() ;
Serial.println((String) "Long T=" + (Tstop - Tstart));
randomSeed(80000);
Tstart = millis();
for (int i = 0; i < NN; i++)
{
af = random(100000);
bf = random(100000);
cf = af / bf;
}
Tstop = millis();
Serial.println((String) "Float T=" + (Tstop - Tstart));
}
void loop()
{
}
Результат:
Long T=2181
Float T=2163
То есть да, флоат чуть быстрее, но вовсе не гораздо. Зато флоат требует больше места во флеше
Long only
Sketch uses 3852 bytes (12%) of program storage space. Maximum is 30720 bytes.
Global variables use 232 bytes (11%) of dynamic memory,
Float only
Sketch uses 4376 bytes (14%) of program storage space. Maximum is 30720 bytes.
Global variables use 232 bytes (11%) of dynamic memory,
А если в цикл добавить одно сложение 2х чисел, то флоат уже и по времени проигрывать начинает
Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18. Если в скетче 10 лишних вызовов это 180 байт.
Попробовал проверить этот факт. Чёт не сходится, то ли я тупой, то ли в консерватории что-то :-(, но почему-то получается 24, а не 180 :-( Наверное потому, что у меня калькулятор китайский :-(
#define DUCK 10
//Скетч использует 2078 байт (6%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 188 байт (9%) динамической памяти, оставляя 1860 байт для локальных переменных. Максимум: 2048 байт.
//#define DUCK digitalRead(8)
//Скетч использует 2102 байт (6%) памяти устройства. Всего доступно 30720 байт.
//Глобальные переменные используют 188 байт (9%) динамической памяти, оставляя 1860 байт для локальных переменных. Максимум: 2048 байт.
void setup(void) {
Serial.begin(9600);
// Один вызов есть в любом случае
Serial.println(digitalRead(10));
// Добавляем (или не добавляем)
// "10 лишних вызовов"
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
Serial.println(DUCK);
}
void loop(void) {}
Там подсчет осуществлен более или менее корректно - без привлечения лишних функций и даже с учетом времени выполнения операторов, задающих цикл.
И еще: квалификатор volatile отключает оптимизацию. Не факт, что таким способом можно оценивать скорость выполнения "нормально скомпилированного" (т.е. с оптимизацией) кода.
Калькулятор китайский, это только у китайцев 24 нацело делится на 10!
Так вот и я ж про тоже говорю!
А у нормальных пацанов 2102 - 2078 равно, как известно, 180!
А теперь меняем первую строку на
byte DUCK = 10;
и получаем "Скетч использует 1998 байт (6%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 188 байт (9%) динамической памяти, оставляя 1860 байт для локальных переменных. Максимум: 2048 байт."
И вот вместо 2078 получается 1998, а вместо доступных 30720 байт оказывается 32256.
Не очень понятно зачем, но поменял. Получил правда, не 1998, а 2014, но готов списать это на разницу в версиях IDE (и соответственно компилятора и его настроек).
А вот если поменять не на переменную, как у Вас, а на такую же константу времени компиляции, но байтовую. Например,
#define DUCK ((byte)10)
или, что практически тоже самое
constexpr byte DUCK=10;
то у меня получилось 1994 (попробуйте, сколько будет у Вас).
Только вот до сих пор не понял зачем Вы это написали? Это должно как-то подтвердить тезис о том, что 10 вызовов digitalRead == -180 байтов? Так, вроде, не подтверждает! Да и получившееся число опять на 10 не делится :-( Тогда зачем было это писать?
А мне нет. Мне через час выступать на заключительном круглом столе НСКФ, а текста выступления нет. Я сначала написал текст как я его понимаю, потом стал прилизывать - убирать матерные слова. В итоге получилс чистый лист с горсткой предлогов и междометий. С чем выступать не знаю, а доклад через час :-(
Мне интересно только каким образом каждый вызов digitalRead стоит 18 байтов программной памяти. Я пытаюсь это понять, но Вы почему-то не можете мне этого продемонстрировать. Сделайте пожалуйста, будьте так добры. Не с потолка же Вы это число назвали, правда?
for (long i = 0; i < 10000000; i++) {
tmp = flag;
}
выполнялся всего 4 микросекунды? Нет, Вы этому верите?
При тактовой частоте 16М четыре микросекунды это 64 такта. Т.е. каждый проход Вашего цикла выполнялся за 6,4 микротакта! Вы правда в это верите? Честно скажите!
А если этот цикл был "соптимизирован нахрен", то какова цена Вашему сравнению? Что и с чем Вы сравниваете?
Использование digitalRead всего-то в 9 миллионов раз медленнее!
Любой вменяемый человек, получив такой результат, пришел бы к выводу, что эксперимент составлен некорректно, и задался бы вопросом "А что я не так делаю?".
Но нет, здесь безапелляционное: "в 9 миллионов раз медленнее!".
А если этот цикл был "соптимизирован нахрен", то какова цена Вашему сравнению? Что и с чем Вы сравниваете?
да тут все выводы об "оптимальности " не основаны ни на чем..
Уже в тот момент,, когда товарищ заявил, что если один вызов функции запимает 18 байт, то 10 вызовов = 180 - можно было перестать спорить. Сразу очевидно, что человек мыслит категориями ассемблера и ничего не понимает в современных компиляторах...
Можете не комментировать. Но если очень хочется использовать digitalRead вместо дополнительной переменной, то хотя бы воспользуйтесь прямым чтением регистров, а не стандартной функцией. Поверьте, разница по скорости впечатляет.
В любом случае использование digitalRead вместо дополнительной переменной увеличивает используемую память и уменьшает скорость работы. Оптимальным кодом это точно не назовёшь.
В любом случае использование digitalRead вместо дополнительной переменной увеличивает используемую память и уменьшает скорость работы. Оптимальным кодом это точно не назовёшь.
ну да, только между этим утверждением и вашими прежними криками о 180 байтах и 9 миллионах раз - дистанция огромного размера.
Лучше бы признали, что ваши выводы основаны на свершенно неверных предпосылках.
А мне нет. Мне через час выступать на заключительном круглом столе НСКФ, а текста выступления нет. Я сначала написал текст как я его понимаю, потом стал прилизывать - убирать матерные слова. В итоге получилс чистый лист с горсткой предлогов и междометий. С чем выступать не знаю, а доклад через час :-(
Знакомая ситуация...
Сидит поручик Ржевский, что-то пишет... Входит полковник:
- Поручик, что вы пишете?
- Да вот, сочиняю гимн нашего полка..
- Неужели?! Дайте-ка почитать... Да тут же сплошной мат!!!
- Ну почему сплошной... Вот, во втором куплете, слово "знамя"...
Я думаю, что apg_777 увлекся сражением и забыл о топикстартере, для которого был написан пример. Ему в задаче скоростей прямого доступа к регистрам не требуется, а запутаться с ними он сумеет и без нашей помощи, если будет нужда в том.
Можете не комментировать. Но если очень хочется использовать digitalRead вместо дополнительной переменной, то хотя бы воспользуйтесь прямым чтением регистров, а не стандартной функцией. Поверьте, разница по скорости впечатляет.
В любом случае использование digitalRead вместо дополнительной переменной увеличивает используемую память и уменьшает скорость работы. Оптимальным кодом это точно не назовёшь.
Ох уж эти мне "оптимизаторы"...
Оптимальный код или нет, сказать нельзя до тех пор, пока не сформулированы критерии оптимальности.
Думаю, если код безукоризненно выполняет возложенные на него задачи, не требуя дополнительных ресурсов (или требует минимум таких ресурсов - это отдельный критерий), и при этом обеспечивает достаточную легкость поддержки, то его можно считать оптимальным.
Соответственно, если характерное время отклика составляет единицы или десятки миллисекунд, совершенно безразлично, будет затрачено 5 мкс на digitalRead или 0.2 мкс на непосредственное чтение из порта. Если прошивка помещается в отведенное ей место в памяти, и при этом остается место на случай изменений, связанных с поддержкой, безразлично, занимает она 2% или 20% - все равно "сэкономленную" память в другой проект не перенесешь.
Я, например, прямо сейчас работаю над проектом, в котором рядышком используются digitalWrite и прямое чтение из порта, и я могу объяснить, почему именно так - оптимально.
PS. После всего написанного Вами на слово я Вам, естественно, не верю, но когда в начале моего знакомства с Ардуино я решил узнать, сколько же выполняются digitalRead/digitalWrite, результат меня действительно впечатлил.
Можете не комментировать. Но если очень хочется использовать digitalRead вместо дополнительной переменной, то хотя бы воспользуйтесь прямым чтением регистров, а не стандартной функцией. Поверьте, разница по скорости впечатляет.
это для задачки с тремя реле и тремя потенциометрами? нечему там впечатлять, никакой разницы не увидите.
Скорость выполнения random() и в том и другом случае абсолютно одинакова. Так что нужно смотреть на разность. А она составляет 18мс на 10000 циклов или около 30 тактов (при 16MHz) на одно деление.
Что дает те же 18 мс разницы. Получается 627 тактов на лонг и 496 на флоат. Что опять же не очень совпадает с вашими цифрами. При этом сюда включены такты на организацию цикла, так что чисто деление делается еще быстрее.
Но даже если взять ваши цифры, то разницу в скорости выполнения деления меньше чем на 20% все равно нельзя назвать "гораздо большим временем". А с учетом того, что флоат сложение/вычитание намного медленее (тут уже действительно намного) общий подход избегать флоат является абсолютно разумным.
Цитата:
И еще: квалификатор volatile отключает оптимизацию. Не факт, что таким способом можно оценивать скорость выполнения "нормально скомпилированного" (т.е. с оптимизацией) кода.
Это в корне неверное утверждение. volatile не отключает оптимизацию per se. Он только говорит компилятору не использовать прежне вычисленное значение для данной переменной.
Скорость выполнения random() и в том и другом случае абсолютно одинакова.
А вот скорость присваивания в первом случае и преобразования типа во втором - может сильно отличаться.
asam пишет:
...общий подход избегать флоат является абсолютно разумным.
Разве с этим кто-то спорит?
Не следует приписывать собеседнику заведомо абсурдные утверждения.
Цитата:
Цитата:
И еще: квалификатор volatile отключает оптимизацию. Не факт, что таким способом можно оценивать скорость выполнения "нормально скомпилированного" (т.е. с оптимизацией) кода.
Это в корне неверное утверждение. volatile не отключает оптимизацию per se. Он только говорит компилятору не использовать прежне вычисленное значение для данной переменной.
Так прямо в стандарте языка и написано?
В любом случае, квалификатор используется не по прямому назначению, а значит, делать обобщения результатов, полученных с помощью этого квалификатора, на общий случай неправомерно.
А вот скорость присваивания в первом случае и преобразования типа во втором - может сильно отличаться.
Как уже сказал выше - без рандом разница в выполнении осталось ровно той-же 18мс на 10000 делений.
Цитата:
Не следует приписывать собеседнику заведомо абсурдные утверждения.
Про то что "что целочисленное деление long занимает гораздо больше времени, чем любая арифметическая операция с плавающей точкой." утверждали? А это и есть, ну если не абсурдное, то уж точно неверное утверждение.
Я думаю, что apg_777 увлекся сражением и забыл о топикстартере, для которого был написан пример. Ему в задаче скоростей прямого доступа к регистрам не требуется, а запутаться с ними он сумеет и без нашей помощи, если будет нужда в том.
Если Вы соизволите прочитать начало ветки, то Вы найдёте отзыв топикстартера на мой ответ. Мой ответ #5, который какая-то добрая душа не забыла заминусовать, и отзыв ТС #10.
Всё остальное — флуд, который я предложил перенести в другую ветку. Но, судя по всему, данный форум не имеет никакого отношения к реальному программированию, это просто секта "ни строки без millis"!
Нормальные программисты прекрасно делятся своими наработками и им наплевать на каком языке и как это написано, главное написать максимально эффективный код. Лет 35 назад я писал программы на Паскале, в других лабораториях писали на C, начальник писал на Фортране и при этом мы прекрасно делились наработками, не было никакой ругани.
Здесь же табу на всё, что не подходит под некий, никому не известный, стандарт.
В этом форуме нет программистов!
Добавьте к этому то, что я достаточно хорошо знаком со схемотехникой (50 лет радиолюбительства даром не проходят), в состоянии прочитать datasheet и написать программу практически под любое устройство. Ещё раз скажу — здесь нет программистов. Есть дети, которые научились моргать светодиодом без delay и на основании этого считают что они круты до безобразия.
Меня здесь обвиняли про 9 миллионов, но никому в голову не пришло, что это было сделано специально. Результат был реальный, поэтому нормальный программист, получив те же результаты задумался бы. Ан нет, дедок облажался! Вы правда считаете что человек не в состоянии разделить 4 микросекунды на миллион циклов? Это вы лохи, из-за вас нынешние программы образец тормознутости.
В завершение повторю свою любимую фразу "Программистов нужно сажать за самые тормозные машины".
И ещё раз повторю — в этом форуме программистов нет.
Либо вы реально делитесь информацией, либо вы напишите что здесь просто детский сад, который не имеет никакого отношения к программированию.
Меня здесь обвиняли про 9 миллионов, но никому в голову не пришло, что это было сделано специально. Результат был реальный, поэтому нормальный программист, получив те же результаты задумался бы.
Поясните пожалуйста что было сделано специально и о чем должен был задуматься нормальный программист?
Меня здесь обвиняли про 9 миллионов, но никому в голову не пришло, что это было сделано специально. Результат был реальный, поэтому нормальный программист, получив те же результаты задумался бы.
Поясните пожалуйста что было сделано специально и о чем должен был задуматься нормальный программист?
задумайтесь. 4 микросекунды на кучу циклов. Ясное дело что что-то не так, однако это реальный ответ ардуины. Я просто скопипастил результат.
задумайтесь. 4 микросекунды на кучу циклов. Ясное дело что что-то не так, однако это реальный ответ ардуины. Я просто скопипастил результат.
Включите голову если вы программисты!
Ну вам уже ответили - "этот цикл был "соптимизирован нахрен"". Т.е. в реальности ардуина вовсе не делала 1000000 чтений флага, а сделала это всего один раз.
Как раз таки эти флаги только загромождают код. Нежелательно, если считывание идет непосредственно после изменением сигнала на выходе. Хотя, при использовании digitalRead это не важно.)
Конденсаторы на аналоговых входах точно не помешают.
Переменные резисторы штука таинственная, контакт бегунка с подковкой ненадёжен, а кручение рукой процесс неторопливый. Дребезжат так, что кнопки позавидуют. Я как-то забыл в регуляторе яркости светодиодной ленты поставить, при первом же включении вспомнил!
а по Вашему опыту какую лучше емкость кондеев взять - 0.01 или 0.1? Потенциометры на 10 кОм.
В регуляторе яркости у меня 10 мкФ, при 10 кОм постоянная времени максимум 0.1 сек. И ещё 0.1 у входа контроллера — провод относительно длинный.
Использовать digitalRead() для вывода, настроенного на выход тоже не лучшая идея. Лучше использовать переменные-флаги, получится и быстрее и экономнее по памяти. И скетч будет короче и понятнее.
экономичнее по памяти, чем в случае с флагами.
Флаг занимает один байт. Сколько занимает каждый вызов digitalRead? Сэкономить не поучится.
Флаг занимает один байт. Сколько занимает каждый вызов digitalRead?
Ноль байт.
Сэкономить не поучится.
Почему?
Флаг занимает один байт. Сколько занимает каждый вызов digitalRead?
Ноль байт.
Сэкономить не поучится.
Почему?
И давно функции перестали место занимать? И вызов любой функции? Получается если написать скетч из одних функций, то он будет нулевого размера? Поинтересуйтесь как осуществляется вызов/выполнение/возврат из функции и сравните с несчастным байтом на флаг.
Поинтересуйтесь как осуществляется вызов/выполнение/возврат из функции и сравните с несчастным байтом на флаг.
Вам тонко намекают, что флаг занимает место в той памяти, которой всего 2К, а вызовы функции живут в той, которой 32К. Поинтересуйтесь как устроена память в этой архитектуре.
Поэтому 32К и не хватает. Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18. Если в скетче 10 лишних вызовов это 180 байт. Продолжаем экономить 1 байт в 2К.
apg_777, чего закусился-то? Вопрос того, что экономим, зависит от критериев оптимизации. Их тут нет. Кто как хочет, так и пишет.
Поэтому 32К и не хватает.
Кому?
Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18.
Точно? Ну, тогда ладно.
Дело, конечно, хозяйское. Вариантов решения конкретных задач много, что даже здесь видно — есть любители millis, я предпочитаю подобные задачи решать через прерывания. Вариант через millis 86 строк, а я лентяй, у меня получилось 36 строк :)
Поэтому 32К и не хватает.
Кому?
Есть такие люди.
А с меньшим размером программы можно контроллер попроще и подешевле взять. Например светильник от AlexGyver (который без Wi-Fi и на ленте, а не матрице) можно запросто переделать на ATtiny85, запускал на 240 светодиодов. Поправил одну строку и скетч уместился в 8К. И вместо платы nano одна микросхема 4x4 кв.мм.
Вывод какой? Чем меньше строк, тем лучше? А тогда зачем флаги - лишние строки ведь?
А вообще, оптимизация по размеру памяти последнее дело, для этого должна быть причина, а не просто так.
Да, Господь с Вами, зачем переделывать что-то от AlexGyver? Похоже у меня понималка не доросла понимать Ваши мысли.
Вывод какой? Чем меньше строк, тем лучше? А тогда зачем флаги - лишние строки ведь?
А вообще, оптимизация по размеру памяти последнее дело, для этого должна быть причина, а не просто так.
Лишняя строка одна при объявлении, дальше наоборот меньше получается.
Оптимизация никогда не повредит. Привычка вырабатывается сразу и потом переделать себя очень сложно. У меня выработалась привычка писать максимально оптимальный код, а кому-то главное чтобы работало, не хватит, возьмём что-нибудь помощнее.
Просто в 1981 году у меня была машина с 4К, а втиснуть надо было общение с нехилым аппаратным комплексом и при этом довольно быстро производить массу расчётов. Зато память там была на ферритовых кольцах!
Пример второго подхода — игра Syberia 3. 20 ГБ установщик и тормоза даже на супер-пупер игровых компьютерах.
Но это общение лучше перенести куда-нибудь в отвлечённые темы. Здесь не по теме больше не комментирую.
И давно функции перестали место занимать? И вызов любой функции? Получается если написать скетч из одних функций, то он будет нулевого размера? Поинтересуйтесь как осуществляется вызов/выполнение/возврат из функции и сравните с несчастным байтом на флаг.
Занимать где?
Вы не путайте, в Гарвардской архитектуре код располагается не в ОЗУ и, соответственно, места там не занимает.
Поэтому 32К и не хватает. Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18. Если в скетче 10 лишних вызовов это 180 байт. Продолжаем экономить 1 байт в 2К.
Вам не хватает 32К для мигания трех светодиодов? Или Вы надеетесь сэкономленную в одном проекте флеш-память перенести в другой проект?
Выражаю Вам свое сочувствие.
Вариант через millis 86 строк,
Аргументируйте.
а я лентяй, у меня получилось 36 строк :)
У меня выработалась привычка писать максимально оптимальный код...
Это утверждение требует подтверждения.
А, учитывая, что критерии оптимальности бывают совершенно различные, о чем Вы забыли упомянуть, это Ваше утверждение вызывает обоснованные сомнения.
Старой гвардии кажется что они пишут "максимально оптимальный код".))) На самом деле с этим и без них вполне справляется компилятор. Зато все эти их извращения с оптимизацией по размеру только ухудшают читаемость исходного текста и вносят возможность дополнительных ошибок. Со всеми вытекающими из всего этого временными затратами.
Старой гвардии кажется что они пишут "максимально оптимальный код"...
На самом деле намного смешнее.
Меняется аппаратура, меняются соотношения, и то, что раньше было верхом оптимальности вдруг оказывается очень далеким от нового оптимума.
Просто парочка примеров применительно ПК.
Первые VGA адаптеры подключались по ISA. Соответственно, обмен между процессором и видеопамятью был во много раз медленнее, чем с ОЗУ. В некоторых случаях более чем в 10 раз. Потом появилась AGP, а на видеокартах стали ставить GDRAM, которая была быстрее DRAM, в результате обмен с видеопамятью уже раза в 2-3 превосходил по скорости обмен с основным объемом ОЗУ. Соответственно, те способы работы с графикой, которые применялись, ориентируясь на ISA, стали совершенно неоптимальными.
С появлением FPU и суперскалярных процессоров, опять же, существенно (на порядки, причем более, чем на один) изменилось соотношение времени на выполнение вычислений с плавающей точкой ко времени выполнения ветвления. Те алгоритмы, которые учебники предлагали в качестве оптимальных, перестали быть таковыми.
Да даже на AVR много тонкостей. В частности, "оптимизаторы" обычно знают, что использование float ведет к существенному увеличению времени выполнения, но, зачастую, им невдомек, что целочисленное деление long занимает гораздо больше времени, чем любая арифметическая операция с плавающей точкой.
Да даже на AVR много тонкостей. В частности, "оптимизаторы" обычно знают, что использование float ведет к существенному увеличению времени выполнения, но, зачастую, им невдомек, что целочисленное деление long занимает гораздо больше времени, чем любая арифметическая операция с плавающей точкой.
Что-то я засомневался в этом утверждении и решил проверить:
Результат:
То есть да, флоат чуть быстрее, но вовсе не гораздо. Зато флоат требует больше места во флеше
Long only
А если в цикл добавить одно сложение 2х чисел, то флоат уже и по времени проигрывать начинает
Меня больше вот это заинтересовало
Каждый вызов digitalRead это 10 байт, возврат ещё 8, итого 18. Если в скетче 10 лишних вызовов это 180 байт.
Попробовал проверить этот факт. Чёт не сходится, то ли я тупой, то ли в консерватории что-то :-(, но почему-то получается 24, а не 180 :-( Наверное потому, что у меня калькулятор китайский :-(
Что-то я засомневался в этом утверждении и решил проверить:
Позвольте полюбопытствовать, а что именно Вы решили проверить, операцию деления или функцию random()?
Посмотрите для примера эту тему: http://arduino.ru/forum/obshchii/vremya-vypolneniya-otdelnykh-komand-arduino
Там подсчет осуществлен более или менее корректно - без привлечения лишних функций и даже с учетом времени выполнения операторов, задающих цикл.
И еще: квалификатор volatile отключает оптимизацию. Не факт, что таким способом можно оценивать скорость выполнения "нормально скомпилированного" (т.е. с оптимизацией) кода.
почему-то получается 24, а не 180 :-( Наверное потому, что у меня калькулятор китайский :-(
Калькулятор китайский, это только у китайцев 24 нацело делится на 10!
Калькулятор китайский, это только у китайцев 24 нацело делится на 10!
Так вот и я ж про тоже говорю!
А у нормальных пацанов 2102 - 2078 равно, как известно, 180!
А у нормальных пацанов 2102 - 2078 равно, как известно, 180!
а Пятница? где Пятница в расчётах... ;-)
Калькулятор китайский, это только у китайцев 24 нацело делится на 10!
Так вот и я ж про тоже говорю!
А у нормальных пацанов 2102 - 2078 равно, как известно, 180!
А теперь меняем первую строку на
и получаем "Скетч использует 1998 байт (6%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 188 байт (9%) динамической памяти, оставляя 1860 байт для локальных переменных. Максимум: 2048 байт."
И вот вместо 2078 получается 1998, а вместо доступных 30720 байт оказывается 32256.
А мне весело! Слежу за развитием... ;)))
Раз опять втянули в этот бардак сравним скорострельность.
Результат:
Start
t2 - t1 = 4
t3 - t2 = 36470464
А теперь меняем первую строку на
и получаем "Скетч использует 1998 байт (6%)
Не очень понятно зачем, но поменял. Получил правда, не 1998, а 2014, но готов списать это на разницу в версиях IDE (и соответственно компилятора и его настроек).
А вот если поменять не на переменную, как у Вас, а на такую же константу времени компиляции, но байтовую. Например,
или, что практически тоже самое
то у меня получилось 1994 (попробуйте, сколько будет у Вас).
Только вот до сих пор не понял зачем Вы это написали? Это должно как-то подтвердить тезис о том, что 10 вызовов digitalRead == -180 байтов? Так, вроде, не подтверждает! Да и получившееся число опять на 10 не делится :-( Тогда зачем было это писать?
А мне весело! Слежу за развитием... ;)))
А мне нет. Мне через час выступать на заключительном круглом столе НСКФ, а текста выступления нет. Я сначала написал текст как я его понимаю, потом стал прилизывать - убирать матерные слова. В итоге получилс чистый лист с горсткой предлогов и междометий. С чем выступать не знаю, а доклад через час :-(
сравним скорострельность.
А давайте не будем. Мне неинтересно.
Мне интересно только каким образом каждый вызов digitalRead стоит 18 байтов программной памяти. Я пытаюсь это понять, но Вы почему-то не можете мне этого продемонстрировать. Сделайте пожалуйста, будьте так добры. Не с потолка же Вы это число назвали, правда?
Таки глянул на Ваш пример, не удержался. Ужос!
Вы правда думаете, что цикл
выполнялся всего 4 микросекунды? Нет, Вы этому верите?
При тактовой частоте 16М четыре микросекунды это 64 такта. Т.е. каждый проход Вашего цикла выполнялся за 6,4 микротакта! Вы правда в это верите? Честно скажите!
А если этот цикл был "соптимизирован нахрен", то какова цена Вашему сравнению? Что и с чем Вы сравниваете?
Start
t2 - t1 = 4
t3 - t2 = 36470464
Любой вменяемый человек, получив такой результат, пришел бы к выводу, что эксперимент составлен некорректно, и задался бы вопросом "А что я не так делаю?".
Но нет, здесь безапелляционное: "в 9 миллионов раз медленнее!".
Что тут еще комментировать...
А если этот цикл был "соптимизирован нахрен", то какова цена Вашему сравнению? Что и с чем Вы сравниваете?
да тут все выводы об "оптимальности " не основаны ни на чем..
Уже в тот момент,, когда товарищ заявил, что если один вызов функции запимает 18 байт, то 10 вызовов = 180 - можно было перестать спорить. Сразу очевидно, что человек мыслит категориями ассемблера и ничего не понимает в современных компиляторах...
Что тут еще комментировать...
Можете не комментировать. Но если очень хочется использовать digitalRead вместо дополнительной переменной, то хотя бы воспользуйтесь прямым чтением регистров, а не стандартной функцией. Поверьте, разница по скорости впечатляет.
В любом случае использование digitalRead вместо дополнительной переменной увеличивает используемую память и уменьшает скорость работы. Оптимальным кодом это точно не назовёшь.
В любом случае использование digitalRead вместо дополнительной переменной увеличивает используемую память и уменьшает скорость работы. Оптимальным кодом это точно не назовёшь.
ну да, только между этим утверждением и вашими прежними криками о 180 байтах и 9 миллионах раз - дистанция огромного размера.
Лучше бы признали, что ваши выводы основаны на свершенно неверных предпосылках.
Три топора в пятницу до добра не доведуть.
А мне весело! Слежу за развитием... ;)))
А мне нет. Мне через час выступать на заключительном круглом столе НСКФ, а текста выступления нет. Я сначала написал текст как я его понимаю, потом стал прилизывать - убирать матерные слова. В итоге получилс чистый лист с горсткой предлогов и междометий. С чем выступать не знаю, а доклад через час :-(
Сидит поручик Ржевский, что-то пишет... Входит полковник:
- Поручик, что вы пишете?
- Да вот, сочиняю гимн нашего полка..
- Неужели?! Дайте-ка почитать... Да тут же сплошной мат!!!
- Ну почему сплошной... Вот, во втором куплете, слово "знамя"...
Я думаю, что apg_777 увлекся сражением и забыл о топикстартере, для которого был написан пример. Ему в задаче скоростей прямого доступа к регистрам не требуется, а запутаться с ними он сумеет и без нашей помощи, если будет нужда в том.
Можете не комментировать. Но если очень хочется использовать digitalRead вместо дополнительной переменной, то хотя бы воспользуйтесь прямым чтением регистров, а не стандартной функцией. Поверьте, разница по скорости впечатляет.
В любом случае использование digitalRead вместо дополнительной переменной увеличивает используемую память и уменьшает скорость работы. Оптимальным кодом это точно не назовёшь.
Ох уж эти мне "оптимизаторы"...
Оптимальный код или нет, сказать нельзя до тех пор, пока не сформулированы критерии оптимальности.
Думаю, если код безукоризненно выполняет возложенные на него задачи, не требуя дополнительных ресурсов (или требует минимум таких ресурсов - это отдельный критерий), и при этом обеспечивает достаточную легкость поддержки, то его можно считать оптимальным.
Соответственно, если характерное время отклика составляет единицы или десятки миллисекунд, совершенно безразлично, будет затрачено 5 мкс на digitalRead или 0.2 мкс на непосредственное чтение из порта. Если прошивка помещается в отведенное ей место в памяти, и при этом остается место на случай изменений, связанных с поддержкой, безразлично, занимает она 2% или 20% - все равно "сэкономленную" память в другой проект не перенесешь.
Я, например, прямо сейчас работаю над проектом, в котором рядышком используются digitalWrite и прямое чтение из порта, и я могу объяснить, почему именно так - оптимально.
PS. После всего написанного Вами на слово я Вам, естественно, не верю, но когда в начале моего знакомства с Ардуино я решил узнать, сколько же выполняются digitalRead/digitalWrite, результат меня действительно впечатлил.
Что тут еще комментировать...
Можете не комментировать. Но если очень хочется использовать digitalRead вместо дополнительной переменной, то хотя бы воспользуйтесь прямым чтением регистров, а не стандартной функцией. Поверьте, разница по скорости впечатляет.
Позвольте полюбопытствовать, а что именно Вы решили проверить, операцию деления или функцию random()?
Посмотрите для примера эту тему: http://arduino.ru/forum/obshchii/vremya-vypolneniya-otdelnykh-komand-arduino
Скорость выполнения random() и в том и другом случае абсолютно одинакова. Так что нужно смотреть на разность. А она составляет 18мс на 10000 циклов или около 30 тактов (при 16MHz) на одно деление.
Что не очень бьется с вашими цифрами
long
DIV - 670-680 тактов
float
DIV - 550-560 тактов
(больше 100 тактов разницы)
Более того убрав random() я получил
Это в корне неверное утверждение. volatile не отключает оптимизацию per se. Он только говорит компилятору не использовать прежне вычисленное значение для данной переменной.
Скорость выполнения random() и в том и другом случае абсолютно одинакова.
...общий подход избегать флоат является абсолютно разумным.
Разве с этим кто-то спорит?
Не следует приписывать собеседнику заведомо абсурдные утверждения.
Это в корне неверное утверждение. volatile не отключает оптимизацию per se. Он только говорит компилятору не использовать прежне вычисленное значение для данной переменной.
Так прямо в стандарте языка и написано?
В любом случае, квалификатор используется не по прямому назначению, а значит, делать обобщения результатов, полученных с помощью этого квалификатора, на общий случай неправомерно.
А вот скорость присваивания в первом случае и преобразования типа во втором - может сильно отличаться.
Как уже сказал выше - без рандом разница в выполнении осталось ровно той-же 18мс на 10000 делений.
Не следует приписывать собеседнику заведомо абсурдные утверждения.
Про то что "что целочисленное деление long занимает гораздо больше времени, чем любая арифметическая операция с плавающей точкой." утверждали? А это и есть, ну если не абсурдное, то уж точно неверное утверждение.
Если Вы соизволите прочитать начало ветки, то Вы найдёте отзыв топикстартера на мой ответ. Мой ответ #5, который какая-то добрая душа не забыла заминусовать, и отзыв ТС #10.
Всё остальное — флуд, который я предложил перенести в другую ветку. Но, судя по всему, данный форум не имеет никакого отношения к реальному программированию, это просто секта "ни строки без millis"!
Нормальные программисты прекрасно делятся своими наработками и им наплевать на каком языке и как это написано, главное написать максимально эффективный код. Лет 35 назад я писал программы на Паскале, в других лабораториях писали на C, начальник писал на Фортране и при этом мы прекрасно делились наработками, не было никакой ругани.
Здесь же табу на всё, что не подходит под некий, никому не известный, стандарт.
В этом форуме нет программистов!
Добавьте к этому то, что я достаточно хорошо знаком со схемотехникой (50 лет радиолюбительства даром не проходят), в состоянии прочитать datasheet и написать программу практически под любое устройство. Ещё раз скажу — здесь нет программистов. Есть дети, которые научились моргать светодиодом без delay и на основании этого считают что они круты до безобразия.
Меня здесь обвиняли про 9 миллионов, но никому в голову не пришло, что это было сделано специально. Результат был реальный, поэтому нормальный программист, получив те же результаты задумался бы. Ан нет, дедок облажался! Вы правда считаете что человек не в состоянии разделить 4 микросекунды на миллион циклов? Это вы лохи, из-за вас нынешние программы образец тормознутости.
В завершение повторю свою любимую фразу "Программистов нужно сажать за самые тормозные машины".
И ещё раз повторю — в этом форуме программистов нет.
Либо вы реально делитесь информацией, либо вы напишите что здесь просто детский сад, который не имеет никакого отношения к программированию.
Меня здесь обвиняли про 9 миллионов, но никому в голову не пришло, что это было сделано специально. Результат был реальный, поэтому нормальный программист, получив те же результаты задумался бы.
Поясните пожалуйста что было сделано специально и о чем должен был задуматься нормальный программист?
Меня здесь обвиняли про 9 миллионов, но никому в голову не пришло, что это было сделано специально. Результат был реальный, поэтому нормальный программист, получив те же результаты задумался бы.
Поясните пожалуйста что было сделано специально и о чем должен был задуматься нормальный программист?
задумайтесь. 4 микросекунды на кучу циклов. Ясное дело что что-то не так, однако это реальный ответ ардуины. Я просто скопипастил результат.
Включите голову если вы программисты!
задумайтесь. 4 микросекунды на кучу циклов. Ясное дело что что-то не так, однако это реальный ответ ардуины. Я просто скопипастил результат.
Включите голову если вы программисты!
Ну вам уже ответили - "этот цикл был "соптимизирован нахрен"". Т.е. в реальности ардуина вовсе не делала 1000000 чтений флага, а сделала это всего один раз.