оптимизация c / c ++ для постоянной переменной в вызывающих функциях - PullRequest
6 голосов
/ 31 января 2011

Компиляторы C / C ++ оптимизируют однослойные функции с постоянными параметрами (известными во время компиляции) только при использовании -Os, -O1 и -O2.Они не оптимизируют все слои.Только -O3 может сделать это.gcc - это WinAVR 4.3.3, который не поддерживает атрибут «optimize».

void inner(double value)
{
    //operations using value
    //...
}

void outer(double value)
{
    //few operations using value
    //...
    inner(value);
}

int main()
{
    inner(1); //optimize
    outer(1); //only optimize by using -O3
}

Каковы возможные решения, кроме следующих?

  1. -O3 удерживать программу или файл (неправильное использование увеличит размер)
  2. атрибут optimize -O3 для функций (4.3.3 не поддерживает)
  3. макрос (подвержен ошибкам) ​​

Обновление:

//inner function
static inline void _delay_us(double __us) __attribute__((always_inline));
//outer function
void f(double);
inline f1(double);
static inline f2(double);
static f3(double);

f1 оптимизирован, но выдает предупреждение '_delay_us' является статическим, но используется во встроенной функции 'f1', которая не является статической из-за проблемы статической функции.Другие не оптимизированы.


Решение:

static inline void outer(double) __attribute__((always_inline));

Встроенный ключ.Моя внешняя функция слишком велика для inline.Атрибут always_inline заставляет функцию быть встроенной.Это позволяет компилятору оптимизировать функцию с меньшими затратами на компиляцию, чем пытаться выяснить оптимизацию.-O3 достаточно умен, чтобы выполнить оптимизацию, но не -Os.-О, возможно, понадобятся некоторые параметры компилятора.(Ключевое слово static требуется, потому что внутренняя функция также является статической inline.)

Ответы [ 4 ]

3 голосов
/ 31 января 2011

В некоторой степени похож на опцию макроса (3), но без недостатков макроса вы можете сделать определенные функции inline, что обычно приводит к желаемой постоянной оптимизации.Конечно, это помогает только в том случае, если вы вызываете соответствующие функции из одного места (или из нескольких мест), в противном случае проблема с раздуванием кода становится большой.быть встроенным (вместо того, чтобы оставить это на усмотрение компилятора): __attribute__ ((always_inline)).Другие компиляторы, как правило, имеют аналогичный механизм, хотя это может быть переключатель командной строки или прагма.

1 голос
/ 31 января 2011

В GCC, по крайней мере, флаги -O просто включают целую загрузку других флагов, см., Например, http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html.. Вы можете просто включить те из них, которые вас интересуют, хотя это обычно не рекомендуется.*

Обратите внимание, что я не уверен, что поведение, например, GCC при -O2 и -O3 обязательно является любым индикатором того, что будет делать совершенно другой компилятор.

0 голосов
/ 31 января 2011

Как насчет введения функции 'outerFast', определенной в собственном cpp, включая определения inner и outer, и компиляции только этого файла с -O3?

Однако у него есть свои недостатки.

0 голосов
/ 31 января 2011

В целом, если вы увеличите объем информации, которую вы предоставляете компилятору, он сможет выполнить лучшую оптимизацию.

Например, если предположить, что это единственные вызовы inner иouter тогда вы можете объявить их как static, чтобы ограничить их область действия и дать компилятору больше гибкости в том, как он их оптимизирует.

В зависимости от фактического содержимого функций вы могли бы также объявить их параметры как const, что позволяет компилятору немедленно узнать, что их нельзя изменить без анализа кода

static void inner(const double value)
{
    //operations using value
}

static void outer(const double value)
{
    //few operations using value
    //...
    inner(value);
}
...