Опубликован: 10.10.2011 | Доступ: свободный | Студентов: 1428 / 454 | Оценка: 4.31 / 4.16 | Длительность: 05:32:00
Специальности: Программист
Лекция 4:

Глобальные и локальные оптимизации

< Лекция 3 || Лекция 4: 123 || Лекция 5 >

Анализ совмещений (alias analysis)

  • анализ совмещения через параметры
  • анализ совмещения указателей для глобальных и статических указателей (Local point to analysis - LPT)

Важная часть механизма определения зависимостей.

В случае с анализом совмещения указателей с каждым указателем связывается множество возможных значений. Два указателя могут ссылаться на одну область памяти, если пересечение множеств их допустимых значений не пусто.

Пример на LPT анализ


Можно ли осуществлять цикловые оптимизации с циклом for?

Межпроцедурный анализ используется для протяжки атрибутов функций. Например, есть атрибуты no_side_effect, always_return и т.д.

IPA используется для протяжки атрибутов переменных. Например, переменные помеченные атрибутом "адрес был взят" исключаются из многих оптимизаций. Этот атрибут для глобальных переменных устанавливает IPA.

Продвижение данных (Data promotion). Каждая переменная имеет свою область видимости (scope). IPA позволяет протягивать данные, которые используются только в определенной процедуре, на уровень этой процедуры, что сразу позволяет включить их во многие оптимизации.

Функции, используемые только в одной программе получают атрибут static.

Удаление неиспользуемых глобальных переменных.

Удаление мертвого кода.

В данном случае, функция не будет включаться в исполняемый модуль, если она не входит в граф вызовов или все ее вызовы были подставлены (inline). (Вывод – для улучшения размеров кода и времени компиляции используйте атрибут static).

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

Межпроцедурные оптимизации

Используются связи, возникающие при вызовах процедур, для того, чтобы оптимизировать одну или несколько процедур или выяснить, как они соотносятся друг с другом.

Протяжка константных аргументов

Если при каждом вызове процедуры f(i,j,k) в программе в качестве аргумента i всегда передается некая константа, то это позволяет присвоить первому формальному аргументу значение этой константы в коде процедуры f().

Протяжка возвращаемых значений

Если процедура всегда возвращает константное значение, то возможно протянуть это значение наружу.

То же самое касается передаваемых в процедуру аргументов. Если перед выходом из процедуры значение аргумента константа, то ее также можно протянуть наружу.

Пример. Константа протягивается в функцию через аргумент. Константа протягивается в вызывающую функцию.

Таким образом, протянув константу удалось избавиться от ветвления.

Чтобы не быть голословным можно рассмотреть простенький пример.

Подстановка (inlining)

Подстановка удаляет накладные расходы связанные с подготовкой к вызову функции, удаляет переходы, которые могут быть источниками неэффективной работы памяти, позволяет эффективнее применять скалярные и оптимизации циклов. Недостаток оптимизации – увеличение размера приложения. Как следствие – увеличение времени компиляции и необходимых для компиляции ресурсов.

Эвристики для подстановок пытаются выбрать наиболее выгодные для подстановки функции с тем, чтобы получить максимальный эффект для производительности, не выходя за пределы допустимого увеличения кода.

Атрибут функции inline

inline int exforsys(int x1) {
  return 5*x1;
 }
    

Программист "рекомендует" компилятору сделать подстановку такой функции.

Управление подстановкой

Синтаксис:

#pragma inline[recursive]
#pragma forceinline[recursive]
#pragma noinline
    

Аргумент Recursive

требует чтобы данная директива применялась ко всем вызовам, которые осуществляются данным вызовом.

Директива

inline рекомендует инлайнить
noinline требует не инлайнить
forceinline требует инлайнить

Аналоги для языка Фортран

cDEC$ ATTRIBUTES INLINE :: procedure
cDEC$ ATTRIBUTES NOINLINE :: procedure
cDEC$ ATTRIBUTES FORCEINLINE :: procedure

Компиляторные опции подстановки

/Ob<n>    control inline expansion:
            n=0  disable inlining
            n=1  inline functions declared with __inline, and perform C++ inlining
            n=2  inline any function, at the compiler's discretion 
/Qinline-min-size:<n>
          set size limit for inlining small routines
/Qinline-min-size-
          no size limit for inlining small routines
/Qinline-max-size:<n>
          set size limit for inlining large routines
/Qinline-max-size-
          no size limit for inlining large routines
/Qinline-max-total-size:<n>
          maximum increase in size for inline function expansion
/Qinline-max-total-size-
          no size limit for inline function expansion
    

Компилятор имеет массу опций, которые управляют инлайнингом, но как легко убедится в основном это опции регулирующие допустимое увеличение размера кода.

/Qinline-max-per-routine:<n>
          maximum number of inline instances in any function
/Qinline-max-per-routine-
          no maximum number of inline instances in any function
/Qinline-max-per-compile:<n>
          maximum number of inline instances in the current compilation
/Qinline-max-per-compile-
          no maximum number of inline instances in the current compilation
/Qinline-factor:<n>
          set inlining upper limits by n percentage
/Qinline-factor-
          do not set set inlining upper limits
/Qinline-forceinline
          treat inline routines as forceinline
/Qinline-dllimport
          allow(DEFAULT)/disallow functions declared __declspec(dllimport) to be inlined
/Qinline-calloc           directs the compiler to inline calloc() calls as malloc()/memset()
    

Клонирование функций

Если в функцию f(x,y,x) передается x=2 в одном случае и x=3 в другом, то возможно заменить вызов функции f на вызовы f2 и f3.

Частичная подстановка

Если в функции f содержится вначале функции код, зависящий только от формальных аргументов, то этот код может быть подставлен в вызывающую функцию и удален из функции f.

Девиртуализация для C++

Вызов функций через указатели дороже простого вызова.

C++ - объектно-ориентированный язык поддерживающий высокий уровень абстракции.

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

A => B => C

Все наследуемые классы переопределяют virtual int foo()

int process(class A *a) {
      return(a->foo());
   }
    

Еще один пример полезной IP оптимизации

Одной из проблем затрудняющей работу IPA является вызов функций через указатели. Это значительно усложняет построение графа вызовов и затрудняет все оптимизации. Например, при объектно-ориентированном программировании используются виртуальные функции. Виртуальные функции реализуют динамическое выполнение метода класса в зависимости от типа объекта. Каждый вызов виртуальной функции имеет несколько возможных целей. В объекте класса существует таблица, в которой лежат указатели на эти функции.

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


< Лекция 3 || Лекция 4: 123 || Лекция 5 >