Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: IAR Inline
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
pokk
Добрый день, подскажите как заставить компилятор проинлайнить функции.

Изначально у меня все функции было в одном модуле, и объявлены как static + inline, и компилятор их на самом деле инлайнил, но со временем модуль разросся, и теперь хочу некоторые выделить в отдельный модуль, но увы IAR 7.5 не хочит их инлайнить даже при "Multi-file Compilation"

Может не правильно их объявляю?

Код
#pragma inline=forced
inline float32_t Func1(float32_t Data1,float32_t Data2){
.........
}

и в хедере
Код
extern void Handler_adc(void);

При включенной галки "Multi-file Compilation" компилятор это все компилирует но вставление тела функции я не вижу =((
Obam
IAR C/C++ Development Guide
"Inlining is normally performed only on the High optimization level. Specifying
#pragma inline=forced will enable inlining of the function in question also on the
Medium optimization level."

Шикарный Index в этой DevGuide - много полезного и интересного (;

PS: о, прошу прощения, вы в курсе прагмы…
jcxz
Цитата(pokk @ Jul 18 2017, 12:52) *
Может не правильно их объявляю?
Код
#pragma inline=forced
inline float32_t Func1(float32_t Data1,float32_t Data2){
.........
}

Надеюсь это вынесено в хидер? И включена полная оптимизация? и галка с пункта "Function inlining" в свойствах проекта не снята? И нигде нет взятия адреса функции?

Цитата(pokk @ Jul 18 2017, 12:52) *
и в хедере
Код
extern void Handler_adc(void);

А это тут к чему???
pokk
Цитата
Надеюсь это вынесено в хидер?

Размещение всей функции в хидере? Остальное все да.

Цитата
А это тут к чему???

Ой прошу прошение не то указал, в общем, прерывания от АЦП разместил в модуле АЦП, а обработку самих данных завернул в функцию и решил вынести от туда в отдельный модуль, и при этом не хочу что бы это как-то влияло на быстродействие. Там функция получилась
Код
void  Handler_adc(void){
...
}

Нету ни входных ни выходных параметров, само то что бы её инлайнить, но увы sad.gif
jcxz
Цитата(pokk @ Jul 19 2017, 05:47) *
Размещение всей функции в хидере? Остальное все да.

Вызывается она из скольких мест? Попробуйте сделать её вызов только из одного места.

Цитата(pokk @ Jul 19 2017, 05:47) *
void Handler_adc(void)
Нету ни входных ни выходных параметров, само то что бы её инлайнить, но увы sad.gif

Это ISR что-ли? Если так, то естественно, что он не может быть заинлайнен.
pokk
Да вызывается в одном месте.
Код
void SAI1_IRQHandler(void){   // Прерывание приема АЦП
    TEST_ON
    Handler_adc();  
    SAI1_Block_A->CLRFR|=SAI_xCLRFR_CFREQ;
    TEST_OFF
    NOP;
}


Код
void Handler_adc(void){
.....
}
x893
Задайтесь вопросом - почему static inline ... функции размещают в .h файле.
Как ответите - сразу на свой вопрос ответ найдёте.
scifi
Цитата(x893 @ Jul 19 2017, 16:12) *
Задайтесь вопросом - почему static inline ... функции размещают в .h файле.
Как ответите - сразу на свой вопрос ответ найдёте.

Я бы другим вопросом тоже задался: а что вам эти инлайны, жизнь без них не мила что ли? Хотите "быстро-быстро" - дайте компилятору соответствующий ключик, чтобы оптимизировал. Ручками расставлять "инлайн" - это как помечать переменные "регистр", т.е. давно уже моветон.
Obam
Цитата(scifi @ Jul 19 2017, 20:46) *
Я бы другим вопросом тоже задался: а что вам эти инлайны, жизнь без них не мила что ли? Хотите "быстро-быстро" - дайте компилятору соответствующий ключик, чтобы оптимизировал. Ручками расставлять "инлайн" - это как помечать переменные "регистр", т.е. давно уже моветон.

В том-то и прикол: инлайны реализуются в IARе на максимальном уровне оптимизации (;
x893
Иногда бывает нужно.
На счет максимального уровня оптимизации - это правда (но есть ньюансы).
Но не только на максимальном уровне можно использовать inline.
Книжки написаны про это уже лет 40 - можно прочитать.
pokk
Цитата(scifi @ Jul 19 2017, 20:46) *
Я бы другим вопросом тоже задался: а что вам эти инлайны, жизнь без них не мила что ли? Хотите "быстро-быстро" - дайте компилятору соответствующий ключик, чтобы оптимизировал. Ручками расставлять "инлайн" - это как помечать переменные "регистр", т.е. давно уже моветон.

Да хочу "быстро-быстро", оптимизация и так максимальная стоит и все галочки включены, какие ешё ключи ему давать ?

k155la3
Цитата(pokk @ Jul 20 2017, 04:41) *
Да хочу "быстро-быстро", оптимизация и так максимальная стоит и все галочки включены, какие ешё ключи ему давать ?

Пардон что влез.
Может чевой наоборот, убрать ?
Не подерутся инлайновые галочки с галками оптимизации по размеру ? И кто победит ?

scifi
Цитата(pokk @ Jul 20 2017, 04:41) *
Да хочу "быстро-быстро", оптимизация и так максимальная стоит и все галочки включены, какие ешё ключи ему давать ?

И что, не успевает?
Obam
Цитата(x893 @ Jul 19 2017, 21:19) *
Иногда бывает нужно.
На счет максимального уровня оптимизации - это правда (но есть ньюансы).
Но не только на максимальном уровне можно использовать inline.
Книжки написаны про это уже лет 40 - можно прочитать.

И это ТС знает (про прагму).

IAR несколько лет назад всего лишь 20 лет отмечал: "In Code we trust". (;

Цитата
Да хочу "быстро-быстро", оптимизация и так максимальная стоит и все галочки включены, какие ешё ключи ему давать ?

Дык галочки это и есть ключи.
jcxz
Цитата(pokk @ Jul 20 2017, 04:41) *
Да хочу "быстро-быстро", оптимизация и так максимальная стоит и все галочки включены, какие ешё ключи ему давать ?

Если Вы действительно хотите "быстро-быстро", то во-первых - ассемблер.
Во-вторых: Всегда при оптимизации в первую очередь надо думать над алгоритмом. Наличие аргументов с плавающей точкой при обработке данных АЦП уже как бы даёт основания полагать, что у Вас там далеко не всё оптимально.
И когда избавитесь от float, увидите, что inline даёт сущие крохи по сравнению с float. И об inline надо думать уже в последнюю очередь (при оптимизации по скорости).

Цитата(x893 @ Jul 19 2017, 20:19) *
Иногда бывает нужно.

При оптимизации по скорости, об inline стоит думать в последнюю очередь. И то - если функция совсем простая - из пары действий.
inline, имхо, более полезен не для ускорения, а для например: уменьшения расхода стека на локальные переменные - вот это более важно. Вот в таком случае было бы очень полезно явно указывать компилятору, что функцию "обязательно inline-ить".
scifi
Цитата(jcxz @ Jul 20 2017, 11:22) *
И когда избавитесь от float, увидите, что inline даёт сущие крохи по сравнению с float. И об inline надо думать уже в последнюю очередь (при оптимизации по скорости).

+1. Если там плавучка не аппаратная, то все эти инлайны будут как мёртвому припарка.
pokk
float апаратный, а на инлайнах теряется около 500 тактов из всего 4700, хотя пока есть запас в 1700, но чем больше тем лучше.

scifi
Кстати, gcc с опцией -flto инлайнит направо и налево без всяких подсказок, ЕМНИП. В дизассемблере такое месиво получается, что ничего не понятно. Видимо, яр работает несколько иначе. Во всяком случае, обычно считалось, что компилятор может инлайнить только то, что видит в пределах компилируемого файла, что логично. И не факт, что multifile compilation отменяет это ограничение.
pokk
Цитата
Кстати, gcc с опцией -flto инлайнит направо и налево без всяких подсказок, ЕМНИП. В дизассемблере такое месиво получается, что ничего не понятно.

Да если все в одном модуле и объявлено как static то так же все получается. В дизассемблере сначала идет портянка сишного кода(ввиде коментарий) а потом голый ассемблер, что даже не понятно какая строчка СИ во что преобразовалась.

Цитата
Во всяком случае, обычно считалось, что компилятор может инлайнить только то, что видит в пределах компилируемого файла, что логично. И не факт, что multifile compilation отменяет это ограничение.

Ага увы, поспихал почти все обратно в один модуль, только что ещё раз отключил галку Function inlining ровно 500 тактов прибавилось.
jcxz
Цитата(pokk @ Jul 20 2017, 12:48) *
float апаратный

Даже если аппаратный. Вы как бы совсем не задумывались, что используя float внутри ISR, необходимо сохранить/восстановить контекст FPU на входе/выходе ISR? А например на Cortex-M этот контекст в разы больше чем стандартный сохраняемый контекст. Время этого сохранения/восстановления будет много больше чем выигрыш от inline вашей функции.
Да надеюсь у Вас этот контекст вообще - сохраняется/восстанавливается? biggrin.gif

Цитата(pokk @ Jul 20 2017, 13:08) *
Ага увы, поспихал почти все обратно в один модуль, только что ещё раз отключил галку Function inlining ровно 500 тактов прибавилось.

Да ладно здесь байки рассказывать! rolleyes.gif
На вызов/возврат из функции (две команды CALL/BX LR) тратится +500 тактов???
Здесь всё-таки не форум кухарок.... laughing.gif
scifi
Цитата(jcxz @ Jul 20 2017, 15:36) *
На вызов/возврат из функции (две команды CALL/BX LR) тратится +500 тактов???
Здесь всё-таки не форум кухарок.... laughing.gif

Рискуете прослыть кухаркой, уважаемый.
Если, скажем, вызовов штук 20, да ещё принять во внимание Wait States, то ничего невероятного тут нет.
jcxz
Цитата(scifi @ Jul 20 2017, 16:42) *
Если, скажем, вызовов штук 20, да ещё принять во внимание Wait States, то ничего невероятного тут нет.

См. сообщения #5 и #6.

PS: Не ну конечно можно предположить, что у ТС CPU выполняет код из внешней флешь, подключенной по SPI и работающей на низкой SCLK и без кеширования.
В случае такого изврата конечно - каждый такт на счету и может и всего один вход/выход в функцию потянуть на 500+ тактов biggrin.gif
pokk
Цитата(jcxz @ Jul 20 2017, 15:36) *
Да надеюсь у Вас этот контекст вообще - сохраняется/восстанавливается? biggrin.gif

Неа не сохраняется так как прием,обработка и выдача, сразу в прерывании, а маин пустой.



Цитата
См. сообщения #5 и #6.

Это был частный случий. Самый простой.
А так да всего около 20 вызовов функции wink.gif
Структура обработчика примерна такая:
Код
void Handler_adc(void){
    uint8_t i;
    uint32_t sample;
    float32_t Result;
    sample=ADC;  // Считали значение АЦП
    filtr1(sample);
    filtr3(sample);
    for(i=0;i<15;i++){
        Result=filtr4(sample);
        Result=calc(Result);            
        Result=convert(Result);
    }
    SendResult();  // Установка DMA
}


x893
А что бы не взять профайлер и посмотреть ?
pokk
Я через St-link программирую а он его кажись не поддерживает =(
Пробовал в симуляторе запускать, функцию Handler_adc закинул в while(1) до инициализации АЦП, но там мне он что-то от начала выдавал количество тактов, и в упор не хотел показывать сколько тактов выполняется каждая функция
scifi
Цитата(pokk @ Jul 21 2017, 07:31) *
Пробовал в симуляторе запускать, функцию Handler_adc закинул в while(1) до инициализации АЦП, но там мне он что-то от начала выдавал количество тактов, и в упор не хотел показывать сколько тактов выполняется каждая функция

У многих кортексов есть счётчик циклов. Поэтому можно тупо записать в массив засечки:
Код
timestamp[i++] = DWT->CYCCNT;
Obam
Цитата(pokk @ Jul 21 2017, 06:00) *
Структура обработчика примерна такая:
Код

Вот прям нужно ЦОС на скорости получения данных от АЦП?
А "заполнение буфера-->ЦОС в буфере" не вариант, да?
jcxz
Цитата(pokk @ Jul 21 2017, 05:00) *
Неа не сохраняется так как прием,обработка и выдача, сразу в прерывании, а маин пустой.

Ну ок. Конечно только если FPU используется только в одном ISR? Иначе - "Шеф, всё пропало!" biggrin.gif

Конечно странно - зачем запихивать фильтры (вроде оно там у Вас?) и прочее в ISR? У Вас есть уверенность, что данные успеют обработаться до следующего прерывания от АЦП? И обработаться при любом стечении обстоятельств (других обработчиков прерываний)?
Обычно в ISR просто кладут данные в кольцевой буфер, а обрабатывают их неспеша в менее приоритетном процессе (это может быть задача ОС или даже другое программно активизируемое прерывание с меньшим приоритетом (меньшим чем любое аппаратное прерывание)).
Я конечно делал так в одном проекте как-то давно, но там весь код обработчика (и ЦОС) был написан на ассемблере (а значит была уверенность в стабильности времени его работы). И там была острая нехватка ОЗУ в МК.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.