- Межпроцедурная оптимизация
-
Межпроцедурная оптимизация (англ. Interprocedural Optimization, IPO) или полнопрограммная оптимизация — оптимизация компилятора, которая затрагивает несколько процедур, зачастую находящихся в разных модулях. Такую оптимизацию можно применить, лишь проанализировав всю программу целиком.
С ростом объёма программ разработчики стали делать свой код всё более удобочитаемым и повторно используемым. Зачастую это приводит к тому, что процедуры становятся предельно общими, в то время как в конкретной программе можно обойтись и частным случаем. Задача межпроцедурной оптимизации — именно генерация таких частных случаев.
Интерпроцедурная оптимизация выполняется компилятором автоматически (иногда с указанием специальных директив). Ее активация может приводить к существенному увеличению времени компиляции. К компиляторам, умеющим выполнять указанную оптимизацию, относится Intel C++ Compiler. Компилятор Delphi не умеет выполнять подобную оптимизацию.
Содержание
Примеры
Замена параметра функции константой
Пройдя по коду, компилятор убеждается, что один из параметров всегда константа, и уничтожает его.
Было
void DoSomething(Object* aObj, int aParam) { if (aObj==NULL) throw logic_error("aObj==NULL"); cout << "DoSomething(" << aObj->name() << "," << aParam << ")" << endl; } int main() { Object obj1, obj2; DoSomething(&obj1, 1); DoSomething(&obj2, 1); return 0; }
Стало
void DoSomething(Object* aObj) { if (aObj==NULL) throw logic_error("aObj==NULL"); cout << "DoSomething(" << aObj->name() << "," << 1 << ")" << endl; } int main() { Object obj1, obj2; DoSomething(&obj1); DoSomething(&obj2); return 0; }
Замена виртуального вызова статическим
Здесь компилятор убеждается, что все реально выполняющиеся виртуальные вызовы ведут к вызову одной и той же функции. Вместо того, чтобы обращаться к таблице виртуальных методов, компилятор делает прямой вызов функции.
В том же примере, если
Object::name()
— виртуальный метод, оптимизированная функция будет выглядеть так.void DoSomething(Object* aObj) { if (aObj==NULL) throw logic_error("aObj==NULL"); cout << "DoSomething(" << Object::name(aObj) << "," << 1 << ")" << endl; }
Удаление незадействованного кода
После удаления получится:
void DoSomething(Object* aObj) { cout << "DoSomething(" << Object::name(aObj) << "," << 1 << ")" << endl; }
Заодно может происходить чистка таблиц виртуальных методов.
Инлайнинг
Если функция используется однократно, она напрямую включается в то место, из которого она вызывается.
Небольшие функции также можно напрямую включать в вызывающий код.
Многие языки программирования (Паскаль, Java, D) не имеют ключевого слова
inline
, и решение инлайнировать функцию принимается оптимизатором (в случае Java — обфускатором).Это заготовка статьи о компьютерах. Вы можете помочь проекту, исправив и дополнив её.
Это примечание по возможности следует заменить более точным.Категория:- Оптимизации
Wikimedia Foundation. 2010.