Оптимизация на програмата
Оптимизацията на програмите е много обемна тема, по която са написани (и все още се пишат) много трудове. Тук само накратко засягаме този въпрос.
Има два основни вида оптимизация - машинно-зависима (MZO) и машинно-независима (MNZO):
MLO е свързано с вида на генерираните инструкции и е включено във фазата на генериране на код (т.е. машинните кодове подлежат на оптимизация). MLO пряко зависи от архитектурата на компютъра и затова няма да бъде разглеждан от нас.
За разлика от MLO, MLO е отделна фаза на компилатора, която предхожда генерирането на код. Той се включва на етапа на генериране на междинен код - вътрешната форма на представяне на програмата.
капацитивни ресурси (памет).
Има 4 основни типа машинно независима MNSO оптимизация.
I. Изключване на общи подизрази (оптимизиране на линейни секции)
Линейната оптимизация е процедура, която ви позволява да не оценявате един и същ израз няколко пъти, като изключите общи подизрази. Тази процедура е разделена на следните стъпки:
представя израза във форма, подходяща за откриване на общи подизрази;
определят еквивалентността на два или повече подизраза;
модифицирайте командите, за да отчетете това изключение.
Например, нека изразът A = c*d*(d*c+b) бъде записан като тетради:
Подредете операндите по азбучен ред (където е възможно):
След това дефинираме границите на операторите и намираме общите подизрази (това са (1) и (2)) и след това елиминираме подизраза (2). След това заместваме T2 с T1 навсякъде по-долу:
Тази техника е неудобна, тъй като има опции, когато или не е възможно веднага да се намерят общи изрази, или в случаите, когато b, c, d са функции, които имат страничен ефект; в този случай ниеможем да разбием цялата логика на изчисленията.
II. Изчисления по време на компилиране
Ако програмата има раздели, в които има подизрази, състоящи се от константи, тогава тези подизрази могат да бъдат изчислени на етапа на компилация. Например, напълно възможно е предварително да се изчисли дясната страна на израз на формата
III. Оптимизиране на булеви изрази
Методът се основава на използване на свойства на булеви изрази. Например, вместо
if (a и b и c) then endif
необходимо е да се генерират команди по такъв начин, че да се изключат ненужните проверки. Същността на метода е, че изграждаме разклонение на условието на оператора if. Така че вместо "if (a и b и c) then endif" получаваме:
ако не е тогава goto етикет
ако не b, отидете на етикет
ако не c, отидете на етикет
Етикет: //етикет за прескачане
Проблемите, свързани с използването на този метод са, че, първо, може да има странични ефекти в случаите, когато аргументите са функции, и второ, "оптимизираният" код може да се окаже по-тромав от оригинала.
IV. Преместване на инвариантни изчисления извън цикъла
Това е един от най-ефективните методи за оптимизация, който дава много осезаеми резултати.
За да приложите метода, трябва:
определяне на мястото на прехвърляне;
проследяването на инварианта не е лесно, защото аргументите могат косвено да зависят от променливата на цикъла;
страничните ефекти не се вземат предвид, ако аргументите на инварианта са функции (или зависими от тях).
Проблеми, свързани с оптимизацията
Така че е очевидно, че е необходимо да се сравни очакваната печалба от подобряване на ефективността на обектната програма с допълнителните режийни разходи, свързани с увеличаванетовреме за компилиране, надеждност и сложност на самия компилатор. Второ, такива „проблеми“ често са свързани с оптимизации, като дори влошаване на кода, сложността на проследяване на оптимизирани програми. В допълнение, може да бъде много трудно да се идентифицират и/или елиминират произтичащите от това "странични" ефекти.
Например, да приемем, че работим върху стек, като използваме функциитеpush(), за да избутаме число в стека иpop(), за да изхвърлим число. Ако трябва да извадим двойка числа от стека и да върнем логическата им сума обратно в стека, тогава можем да напишем нещо като
Освен това тази опция обикновено е по-предпочитана от компактната.
тъй като най-вероятно оптимизиращият компилатор ще превърне този израз вpush(pop()), считайки вторияpop()за излишен (честно ще използва логическата парадигма A AA). Това е типичен пример за странични ефекти от оптимизацията.
Необходимо е да се съпоставят разходите за оптимизация с очаквания ефект.
Оптимизацията не винаги води до подобряване на кода - могат да се появят странични ефекти. Или след оптимизация се получава по-тромав код.
Колкото повече изчислителна работа се прехвърля към етапа на компилиране, толкова по-ефективно ще работи програмата.
По-предпочитана за MNZO е вътрешната форма на представяне на програмата под формата на тетради.
Най-добрият метод за оптимизация е писането на добри (грамотни) програми.