Оптимизация на програмата

Оптимизацията на програмите е много обемна тема, по която са написани (и все още се пишат) много трудове. Тук само накратко засягаме този въпрос.

Има два основни вида оптимизация - машинно-зависима (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 AA). Това е типичен пример за странични ефекти от оптимизацията.

Необходимо е да се съпоставят разходите за оптимизация с очаквания ефект.

Оптимизацията не винаги води до подобряване на кода - могат да се появят странични ефекти. Или след оптимизация се получава по-тромав код.

Колкото повече изчислителна работа се прехвърля към етапа на компилиране, толкова по-ефективно ще работи програмата.

По-предпочитана за MNZO е вътрешната форма на представяне на програмата под формата на тетради.

Най-добрият метод за оптимизация е писането на добри (грамотни) програми.