|
Много мелких функций или одна большая? |
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 44)
|
Feb 11 2011, 13:20
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
Эээ про Idle можно поподробнее?
ps эта функция исполняется раз в секунду но - ее исполнение может быть критичным по скорости ибо после нее идет обработка буфера uart (если он получил маркер - передача окончена) и посылка ответа
|
|
|
|
|
Feb 11 2011, 13:46
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(GYUR22 @ Feb 11 2011, 16:20)  Эээ про Idle можно поподробнее? Я обычно большую массивную функцию (например, обсчёт данных с логарифмами, фильтрацией и формулами на полстраницы) делю на множество мелких подзадач, вешаю их на стейт-машину и запускаю всё это в общем цикле. То есть, при каждой следующей итерации выполняется следующая подзадача, а в конце вся система переходит в IDLE. В результате время отклика в общем суперцикле существенно уменьшается, а требования к быстродействию вычислений снижаются. Естественно, это всё при отсутствии RTOS.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 11 2011, 13:52
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
богатая идея... надо обмуслить... тока общаяя схема у меня порушится т.к. 1 секундный маркер.... и втом теле еще несколько обработчиков...
|
|
|
|
|
Feb 11 2011, 14:19
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(GYUR22 @ Feb 11 2011, 16:52)  тока общаяя схема у меня порушится т.к. 1 секундный маркер.... Ничего не порушится. Маркер пусть запускает процесс. Вот для затравки: CODE void CalculateParameters(void) { static int stage = 0; if( TimeToCalc) { switch(stage++) { case 0: Calculate_T(); break;
case 1: Calculate_V(); break;
case 2: pH = GetpH(kappa, t); break;
case 3: Calculate_pNa(v); break;
case 4: Calculate_CNa(); break;
default: TimeToCalc = 0; stage = 0; if(state == NoMeas) { state = NormalWork; }
break; } } } CalculateParameters() вставляете в общий суперцикл, флажок TimeToCalc запускает процесс и обнуляется в конце. Хотя, можно его "вынести за скобки"... Вариаций множество.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 11 2011, 15:51
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(MrYuran @ Feb 11 2011, 17:19)  Вот для затравки: И нафига оно такое надо? Код #define run_app(name) do{static bool lock=false; if(!lock){ lock=true;name();lock=false;}}while(0); void idle(void) { run_app(func_app1); run_app(func_app1); run_app(CalculateParameters); } // где-то тама... void CalculateParameters(void) { if(!TimeToCalc) return; Calculate_T(); idle(); Calculate_V(); idle(); pH = GetpH(kappa, t); idle(); Calculate_pNa(v); idle(); Calculate_CNa(); idle(); TimeToCalc = 0; }  И где тут Protothreads, который я "при каждом удобном случае пиарю" ? ЫЫЫ!
|
|
|
|
|
Feb 12 2011, 07:53
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(Сергей Борщ @ Feb 11 2011, 15:46)  Если мелкие сделать принудительно встраиваемыми - то по скорости будет одинаково. А читаемость исходника повысится. Достаточно их сделать статическими и компилятор их сам встроит если они вызываются лишь по разу. 2ТС: Разбивайте всё по функциям на отдельные законченные логические блоки, чтобы была видна структура и прозрачны взаимосвязи. Размер кода при этом не увеличиться ни на йоту.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 12 2011, 09:40
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
размер кода пока не пугает ... оперативки уже мало 95% занято (структурой данных и 2мя буферами uart) ... тока на стэк как я понимаю осталось с ассемблером я практически не знаком - но каждый вызов функции это прыжок по коду - занимающий циклы процессора если я не ошибаюсь но если написать что она- inline без static то она интегрируется в то место где вызывается?
Сообщение отредактировал GYUR22 - Feb 12 2011, 09:46
|
|
|
|
|
Feb 12 2011, 14:03
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(GYUR22 @ Feb 12 2011, 12:40)  размер кода пока не пугает ... оперативки уже мало 95% занято (структурой данных и 2мя буферами uart) ... тока на стэк как я понимаю осталось с ассемблером я практически не знаком - но каждый вызов функции это прыжок по коду - занимающий циклы процессора если я не ошибаюсь но если написать что она- inline без static то она интегрируется в то место где вызывается? Не всегда, а по усмотрению компилятора. Для всех функций не представленных в интерфейсе модуля (использующихся внутри одного модуля, иначе говоря файла) считается правилом хорошего тона присваивать квалификатор static. Это сообщает компилятору о возможности встраивания кода функции при оптимальных на его взгляд условиях. А компиляторы нынче весьма и весьма умные. Использовать квалификатор inline имеет смысл лишь для замены макросов функциями по большей части в заголовочных файлах. Придерживаясь этих нехитрых правил можно получить не только оптимальный но и самодокументированный код. Для гарантированного встраивания функции при любых условиях можно использовать особенности различных компиляторов. В gcc например есть механизм атрибутов: Код #define INLINE __inline__ __attribute__((always_inline))
INLINE void vsegda_inline_func1(void); INLINE void vsegda_inline_func2(void); В других компиляторах используют механизм #pragma ... Альтернатива - вечно зелёные и неувядающие макросы на все времена года:-)
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 14 2011, 11:16
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
static inline - не компилируется... пишет что линкер не нашел функций... inline - все нормально работает в чем подвох?
|
|
|
|
|
Feb 14 2011, 11:25
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата static inline - не компилируется... 1. static inline функцию надо писать в h-файле, который надо подключить (#include) туда, где она будет вызываться 2. Пример написания static inline функции в h-файле (WinAVR) Код static inline void delay_10ms (byte ms) __attribute__((always_inline)); void delay_10ms (byte ms) { for(byte i=0; i<ms; i++) { wdt_reset (); _delay_ms (10); } }
|
|
|
|
|
Feb 14 2011, 11:36
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(_Pasha @ Feb 11 2011, 18:51)   И где тут Protothreads, который я "при каждом удобном случае пиарю" ? ЫЫЫ!  где-то валяется в пыльном углу, все никак руки не дойдут асилить...  Цитата(alexeyv @ Feb 14 2011, 14:25)  1. static inline функцию надо писать в h-файле, который надо подключить (#include) туда, где она будет вызываться Можно и в .c, но только "для внутреннего употребления" Короче говоря, static объявление действительно только внутри модуля, в котором оно объявлено.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 14 2011, 12:28
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
еще раз для тупого... чем лучше static inline по сравнению с просто inline?
|
|
|
|
|
Feb 14 2011, 13:56
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
меня интересует встроится ли код или нет если оставить просто inline ( все эти функции я вывел в отдельный файл и обозвал с inline)
ps про поверье это пять...
Сообщение отредактировал GYUR22 - Feb 14 2011, 13:57
|
|
|
|
|
Feb 14 2011, 15:47
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(GYUR22 @ Feb 14 2011, 16:56)  меня интересует встроится ли код или нет если оставить просто inline Встроится или нет. Я же Вам написал что нужно сделать чтобы всегда встраивалось. Вы что-то не смогли осознать? Цитата(_Pasha @ Feb 14 2011, 17:09)  Пока что с оптимизацией как раз "болезни роста" Думается что это бесконечная болезнь, во всяком случае хочется в это верить.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 14 2011, 17:27
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
C++, C99, and GNU C each have support for inline functions. Different compilers vary in how complex a function they can manage to inline. Mainstream C++ compilers like Microsoft Visual C++ and GCC support an option that lets the compilers automatically inline any suitable function, even those not marked as inline functions.
выдержка из википедии (может конечно врут...) но про static ни слова.... про статик более менее понятно стало из другой статья .....что это локальные функции но честно говоря все очень запутано.....
Сообщение отредактировал GYUR22 - Feb 14 2011, 19:33
|
|
|
|
|
Feb 14 2011, 20:22
|
Участник

Группа: Участник
Сообщений: 58
Регистрация: 16-02-09
Пользователь №: 44 931

|
честно говоря не собирался никого мучить, даже тема была другая просто возникший в процессе вопрос нов и непонятен - и как показало общественное мнение результат негарантирован. имхо: Результат в моем случае проверить сложно т.к. размер кода - будет один и тотже -функции используются по разу а скорость отклика - уарта мне точно померять пока не представляется возможным - точность +/- 1 ms уже не устроит а вот результат по разбиению исполнения массива данных - был виден и дал выигрыш как раз ~1ms - спасибо за наводку Всем спасибо дальше как говориться куда кривая выведет
|
|
|
|
|
Feb 15 2011, 04:56
|
Местный
  
Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940

|
Цитата чем лучше static inline по сравнению с просто inline? Просто инлайн ф-цию компилятор может вставить и как вызов, если сочтет это более подходящим, а статик инлайн он всегда вставляет как надо. Я это где-то прочитал в документации, не помню где.
|
|
|
|
|
Feb 15 2011, 17:43
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(sergeeff @ Feb 14 2011, 20:19)  В общем случае нет гарантированного способа "заставить" компилятор встроить inline функцию. Может встроить, а может - нет. Все пляски с прагмами и атрибутами повышают вероятность встраивания. С чего такой пессимизм? Насколько я знаю если в gcc дал атрибут, так он отрабатывает по полной. Не встречалось в моей практике исключений (я сейчас про gcc только говорю). Приведите примерчик кода с листингом для убедительности. Если разить вашу теорию, то и данные предназначенные для помещения в секции EEPROM (это при помощи атрибутов в gcc происходит) ИНОГДА могут оказаться в другой секции. Это абсурд!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 15 2011, 18:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(demiurg_spb @ Feb 15 2011, 20:43)  С чего такой пессимизм? ... Это абсурд! Поспокойнее сэр! Это не моя теория. Читаем, например, http://msdn.microsoft.com/en-us/library/z8...=vs.80%29.aspx:Цитата The insertion (called inline expansion or inlining) occurs only if the compiler's cost/benefit analysis show it to be profitable. Inline expansion alleviates the function-call overhead at the potential cost of larger code size. чуть ниже: Цитата The compiler treats the inline expansion options and keywords as suggestions. There is no guarantee that functions will be inlined. You cannot force the compiler to inline a particular function, even with the __forceinline keyword. When compiling with /clr, the compiler will not inline a function if there are security attributes applied to the function.
|
|
|
|
|
Feb 15 2011, 18:48
|
Профессионал
    
Группа: Свой
Сообщений: 1 453
Регистрация: 23-08-05
Пользователь №: 7 886

|
Цитата(sergeeff @ Feb 15 2011, 21:26)  Поспокойнее сэр!
Это не моя теория. ... У микрософта сносная документация, но не лучшие компиляторы. Если по теме, то надо приводить выдержки из "С99". В gcc насколько помню есть атрибут с говорящим названием always_inline. На моей практике при "-O3" даже inline в большинстве случаев указывать не надо, само автоматически встроится.
|
|
|
|
|
Feb 16 2011, 06:42
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Само указание ключевого слова inline в декларации функции является подсказкой/предложением компилятору встроить тело функции в точке вызова. Но компилятор имеет полное право сделать по своему усмотрению. Это стандартное поведение. Некоторые компиляторы вводят расширения (само собой нестандартные) для управления поведением компилятора. Про GCC уже сказали выше, у IAR в документации недвусмысленно сказано: Цитата #pragma inline[=forced]
Specifying #pragma inline=forced disables the compiler’s heuristics and forces inlining. If the inlining fails for some reason, for example if it cannot be used with the function type in question (like printf), an error message is emitted. Т.е. при использовании этой прагмы компилятор обязан встроить функцию. Если он не может по техническим причинам этого реализовать, он должен выдать сообщение об ошибке. Это весьма полезное свойство для embedded области применения.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Feb 16 2011, 08:55
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(_Pasha @ Feb 16 2011, 12:54)  Что характерно - чем вопрос элементарнее, тем дискуссия более оживленная  А это всё в точности по Паркинсону ("Законы Паркинсона", занятная книжка). Там был на эту тему пример про обсуждение на совете директоров трех вопросов: 1. про приобретение какого-то очень дорогостоящего оборудования (на миллионы); 2. строительство навеса для стоянки велосипедов сотрудников; 3. сколько стаканчиков для кофе класть в кофейный автомат. По первому вопросу затраты времени 10 минут, по второму - минут 40, и по третьему - три часа. Объяснение логичное: чем проще вопрос, тем больше народу в нём разбирается. И у каждого есть мнение.  Кстати, вопрос про инлайны не такой простой для начинающих, как может показаться. Инлайновые функции должны удовлетворять ряду требований, и для них делаются определённые послабления. Кроме того, обсуждаемые расширения тоже несут с собой часть нюансов использования. Поэтому я бы не считал обсуждение всего этого ненужным.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Feb 17 2011, 14:44
|

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(GYUR22 @ Feb 14 2011, 22:22)  имхо: Результат в моем случае проверить сложно т.к. размер кода - будет один и тотже -функции используются по разу а скорость отклика - уарта мне точно померять пока не представляется возможным - точность +/- 1 ms уже не устроит Ну так забейте на inline если оно настолько некритично для вашего проекта. Кстати inline'нинье функций далеко не гарантия наиболее высокой скорости исполнения. Например, в процессорах с кеш памятью команд - бездумное инлайнинье там и сям приведет только к замедлению за счет раздувания кода при константном объеме кеш памяти. Цитата(demiurg_spb @ Feb 15 2011, 19:43)  Если разить вашу теорию, то и данные предназначенные для помещения в секции EEPROM (это при помощи атрибутов в gcc происходит) ИНОГДА могут оказаться в другой секции. Это абсурд! обилие прагм и атрибутов в проекте - это говнокод, а не абсурд, и - кстати таки да данные могут оказаться совсем не в той секции где ожидаешь, при переносе такого проекта на другой проц.
|
|
|
|
|
Feb 17 2011, 19:18
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(defunct @ Feb 17 2011, 17:44)  Ну так забейте на inline если оно настолько некритично для вашего проекта. Кстати inline'нинье функций далеко не гарантия наиболее высокой скорости исполнения. Например, в процессорах с кеш памятью команд - бездумное инлайнинье там и сям приведет только к замедлению за счет раздувания кода при константном объеме кеш памяти. обилие прагм и атрибутов в проекте - это говнокод, а не абсурд, Идеологически согласен. Кстати, Вы видели в моём примере много прагм и атрибутов? Человек спросил как это сделать - я дал однозначный рецепт. Потом сюда приплели даже микрософтовский компилятор и кеш инструкций, хотя тема находится в подфоруме микроконтроллеры/AVRи вопрос касался avr-gcc... Цитата и - кстати таки да данные могут оказаться совсем не в той секции где ожидаешь, при переносе такого проекта на другой проц. Какие Ваши предложения на сей счёт? Отказаться от использования PROGMEM, EEMEM, ISR и вообще не включать компьютер? Атрибуты в gcc - это почти что основополагающий механизм в случае кросс-компиляции для avr. Если Вы внимательно читали мои посты, то могли бы подметить, что я рекомендовал оставить лишь квалификатор static, ибо это и необходимо и достаточно для локальных функций.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Feb 17 2011, 20:31
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(demiurg_spb @ Feb 17 2011, 22:18)  ... я рекомендовал оставить лишь квалификатор static, ибо это и необходимо и достаточно для локальных функций. Да static для локальных функций это просто "хороший тон", чтобы не "заси...ть" пространство имен большого проекта, а вовсе не какая-то необходимость. С одной стороны - хорошо, с другой, их не найдешь в map файле, если понадобится найти точку зависания программы. То, что static - помощь компилятору в деле инлайнинга, вопрос спорный. В одном компиляторе может так, в другом этак.
|
|
|
|
|
Feb 19 2011, 06:09
|
Местный
  
Группа: Участник
Сообщений: 406
Регистрация: 1-03-06
Пользователь №: 14 821

|
Цитата(GYUR22 @ Feb 11 2011, 13:39)  Есть одна большая функция в программе - которую можно поделить на много мелких ... Вопрос как выгоднее по скорости исполнения - разделить ее на 18 мелких (по смыслу) или оставить как есть? ИМХО Разделяется по функциональности. Например функция: check_port_a() { i2c_byte_read(); uart2_send_data(); } на мой взгляд выглядит не плохо. Что плохо бы смотрелось, это пример: check_port_a() { start_i2c_bit(); set_i2c_address(); set_i2c_cmd_byte(); get_i2c_byte(); stop_i2c_bit(); uart2_send_data(); } По скорости будет примерно одинаково.
Сообщение отредактировал andron86 - Feb 19 2011, 06:13
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|