Специфично оптимизиране

Специализираните неща обикновено са по-добри в работата си от нещата с общо предназначение. Типичното швейцарско ножче с няколко десетки остриета става за какво ли не, но е по-неудобно като нож от прост нож (произведен от същата фирма – нека тръгнем от еднаква база). Печат, който отпечатва един точно определен надпис, е много по-прост и удобен (а най-често и по-здрав и с по-качествен отпечатък) от универсален печат, на който можеш да си наредиш произволен надпис. Специализираните автомобили имат по-висока ефективност в своята област от универсален автомобил… Но за по-редки употреби не си струва да се произвежда специализиран автомобил, или надпис на печат – ще е толкова скъпо спрямо използването, че е по-добре да се използва универсалната техника.

В изчислителната техника положението е сходно. Интегрална схема, предназначена да изчислява един точно определен алгоритъм, е много по-бърза и ефективна като консумация от процесор с общо предназначение плюс програма за смятане на алгоритъма. Цяла операционна система е чудесно нещо с купища възможности, но ефективността й често е далеч по-ниска от тази на специализиран софтуерен модул, който включва от интерфейса за потребителя до управлението на хардуера… Но пък създаването на специализираната интегрелна схема, или софтуерен модул, е много по-скъпо, отколкото на потребителско приложение, което работи върху стандартен процесор или операционна система.

Задачата се затруднява и от още един елемент – неангажираността на купувача, и последващото от нея изкривяване на предлагането. Пазарът е универсален регулатор единствено когато потребителите внимателно пазят интересите си. Престанат ли те да са внимателни, информирани и придирчиви, регулационната роля на пазара отпада. Вместо нея влиза в сила правилото на Франсиско Гойя – “Когато разумът спи, се раждат чудовища.”… Нека обаче, за опростяване на разсъждението, да допуснем, че купувачите си пазят интересите и смятат внимателно баланса между цена и ефективност на техниката, която купуват. (И да игнорираме още един огромен брой други начини ефективността да се покачи или цената на разработката да се намали.)

В този случай за всеки вид техника ще се установява баланс между цената за разработка и икономиите от ефективност. Като правило двете са свързани – колкото по-внимателно и специализирано се разработи модул, толкова по-ефективен и икономичен би могъл да бъде той. В крайните случаи малко печели или губи много – ако модулът е напълно неспециализиран, малко специализиране печели доста ефективност, но ако е много добре специализиран, дори много още доизкусуряване печели съвсем малко ефективност. Така че балансът се оказва някъде по средата.

В картинката обаче има един интересен елемент. Проектирането на специализирани модули е интелектуална работа, тоест теоретично може да бъде “механизирана” и оптимизирана чрез употребата на компютри. В някои случаи, например писането на софтуер, добре премислена оптимизираща програма принципно би могла да елиминира големи количества излишен код, и така да намали обема на крайния софтуер, и да увеличи скоростта му – тоест, да го направи по-икономичен и по-ефективен.

Начален опит за такова оптимизиране прави всеки компилатор. Средствата за оптимизация са много – елиминиране на ненужни инструкции, стриймлайнване на цикли, премахване на излишни подпрограми… Почти всички оптимизации на съвременните компилатори обаче работят на “ниско ниво” – микромениджват нещата, без да преценяват големите модули. Причината е, че просто нямат средствата за това. Почти всички реално използвани съвременни програмни езици описват процедурния ход на нещата в детайли, а блоковата функционална структура на програмата остава неизяснена (освен каквито изводи могат да се направят на базата на процедурния изходен код от ниско ниво). Така че имам предвид програми, различни от типичните компилаторни оптимизатори.

В най-простия случай такава програма би могла да работи чрез изчерпващ анализ на комбинацията от софтуери. Да вземем например един чест вариант – рутер с вградена ОС, върху която вървят инструменти за управление на рутинга и неголяма програма за интерфейс към тях. Ако се знае, че това е единственият приложен софтуер, който ще върви на устройството, изчерпващият анализ би могъл да установи кои функции на файъруола, програмките за поддръжка на системата, и т.н. биват използвани от приложния софтуер, и кои – не. Като резултат, излишните възможности могат да бъдат премахнати, и да се създаде облекчена версия на тези програми, специализирана за въпросния рутер. След това, на свой ред, може да се установи кои функции на ядрото на операционната система се използват реално от софтуера, и излишните също да бъдат премахнати. Най-сетне, ако изходният код е свободен, и може спокойно да бъде манипулиран, може целият необходим софтуер да бъде компилиран на единен блок, което ще намали сериозно обема му и ще увеличи скоростта му.

За много цели обаче не е реално излишните неща да бъдат надеждно установени чрез автоматичен анализ. Този рутер, за който говорим, само IPv4 ли ще търкаля (и можем спокойно да махнем IPv6 функционалността), или засега ще е само с IPv4, но в някой момент ще му се наложи да поддържа и IPv6? (Или ще работи само с IPv6, и v4-функционалността може да бъде махната?) Това е нещо, което софтуерът обикновено няма как да знае – знаят го единствено част от хората, които проектират рутера. Това повдига необходимостта от софтуери, чрез които да може да се укаже изрично на “блоково” ниво какво е необходимо, и какво – не.

Най-груби, специализирани версии на подобни софтуери всъщност вече съществуват. Който е компилирал собствено ядро Линукс, знае – достатъчно е да имаш принципна представа какъв хардуер има машината, и горе-долу какво вършат големите блокове в ядрото, и можеш да си направиш ядро с една трета от обема на “стандартното”, а често и осезаемо по-пъргаво. Предполагам, че скоро ще започнат да се появяват подобни конфигуратори и за други софтуери.

Тези конфигуратори съществено снижават бариерата, която пречи на оптимизирането на софтуера. Без тях например създаването на специализирани версии на ядрото Линукс би било много трудно, или дори невъзможно – твърде малко са хората, които познават ядрото толкова добре, че да могат на ръка да изрежат от него точно каквото е излишно за конкретния случай. Проблемът с тях е, че са съобразени за настройване от човек, а не за автоматично напасване на софтуери един към друг.

Описание, което би позволило автоматично оптимизиране например на ядрото Линукс, вероятно може да бъде реализирано като надстройка или разширение на механизма за ръчно конфигуриране при компилиране. Вероятно би представлявало поблоково описание на структурата на ядрото. За всеки блок би имало описание:

– кои други блокове в ядрото са нужни за неговата работа (от кои блокове зависи)
– какво е необходимо да се направи, за да се включи или изключи блокът от компилиране (напр. какви промени в .config да се направят)
– какви функционалности предлага съответният блок за използващи го външни програми
– евентуално колко “тежи” блокът като консумация на памет, изчислителни ресурси и т.н. (полезно при решения “или-или” при оптимизирането)

Подобно описание във вид, удобен за машинно разчитане, би позволило автоматично конфигуриране и компилиране на софтуера. Създаването на описанието за всеки отделен блок ще е сравнително лесно, ако блоковете са разбити на достатъчно малки елементи. (Подходящ софтуер би могъл автоматично да агрегира малките елементи в по-големи блокове, и да прави агрегирани описания. Това би намалило ресурсите, използвани за оптимизирането на всеки различен билд на софтуера, но ако той не е достатъчно добре проектиран, би намалило и оптимизацията му. В крайна сметка ще може да се подбере ниво на оптимизация, което дава оптимален компромис.)

Мисля си – чудесна идея е да се създаде формат (или протокол) за такива описания. Ако се прилагат към изходния код на свободни софтуери, това би позволило много лесно да бъдат създавани цели системи, оптимизирани за конкретни задачи, хардуери или условия. Чрез тях може да се постигне оптимизация далеч свръх даваната от съвременните портажни системи като тези на OpenBSD или Gentoo.

Пълната модулност на идеята, и възможността специализиран софтуер да обработва модулите, дава едно голямо предимство. Най-големите софтуери стават все по-сложни, и е напълно възможно да се стигне скоро до положението, при което ще е все по-трудно да се поддържат актуални и ефективни ръчни конфигуратори, подобни на menuconfig и xconfig за Линукс. Ще е нужно да се търси компромис между актуалност и ефективност. Създаването на подобни машинно-ориентирани описания (те биха могли да включват и ориентиран към човек елемент, например дескриптивен текст) би отложило този компромис за на практика неограничено време.

Някои езици за програмиране се опитват да включват елементи от подобни описания в структурата на езика. Немалко време се прехласвах по Ада именно защото в нея има подобни наченки – от сорса може да бъде извлечена повече информация за бъдещата работа на програмата, отколкото от сорс на ANSI C++, и съответно да бъде генерирана по-оптимизирана програма. Машинно-ориентираните описания на функционалности обаче позволяват да се дава информация за работата на програмата, която обикновено няма как да бъде изразена чрез езика за програмиране (касае цели програмни модули, а не отделни конструкции), а също е полезна при оптимизирането й. Също, те могат да бъдат използвани заедно с програмни модули, писани на произволни езици. Така че е напълно реално за сериозни проекти, особено в областта на свободния софтуер, да се окажат полезно решение.

Уви, надали ще ми стигне времето да се занимая и с това. Прекалено много идеи, прекалено малко време и сили…

Но нищо не ми пречи поне да си помечтая. 🙂

4 Responses to 'Специфично оптимизиране'

  1. Longanlon Says:

    хм, не че разбирам много от програмиране, ама не е ли идеята на модулно базирания софтуер точно да обедини силните страни на специализираното и общото? това го има и в бизнеса, производството и т.н. – специализирани модули, които правят нещо строго специфично, но които могат да се комбинират почти произволно за изпълнение на широк кръг задачи

  2. Петър Петров Says:

    @Longanlon: Какви са тия бизнес модули, как се свързват един с друг?

    При програмирането на модули главният проблем е, че няма (и не може да има) универсалност на комуникацията между тях. Затова два модула работят заедно само ако поне единият изрично е проектиран да работи с другия. Все пак има известна стандартизация, например как трябва да си комуникират един USB драйвер и ядрото на дадена операционна система. Но това е пак специфична за ядрото комуникация, например един драйвер е или за Линукс, или за Уиндоус, не е универсален.

    @Григор: “Най-големите софтуери стават все по-сложни, и е напълно възможно да се стигне скоро до положението, при което ще е все по-трудно да се поддържат актуални и ефективни ръчни конфигуратори” Аз работя във фирма, където софтуерът от много години е невъзможно да бъде настроен ръчно от един човек. Решението и до момента е армия от хора — скъпо платени консултанти, всеки от които има познания по група от модули. Тези хора нерядко дописват някоя и друга конвертираща програма да преобразува данни от един формат в друг. Това се води нормално, неизбежно и приемливо, нарича се “интегриране” и някои хора съвсем сериозно си извършват суеверни ритуали, за “да стане” (няма да давам примери, че не е смешно).

    Определянето на настройките, което включва кои модули изобщо да ги има, би могла да се направи само след като са ясни изискванията към системата. Например ако компютърът е сървър в шкаф, очевидно няма да му трябва модулът за уеб-камери или за флопита. Но дали ще му трябват USB устройства? Може би никога, освен веднъж, когато сървърът е бил хакнат и свален, и се налага възстановяване на данни, които данни е най-удобно да се пренесат през USB flash памет.

    Решението дали даден модул да присъства заради консумацията му (памет или др. ресурси) може да се определи по обективен количествен критерий, т.е. да се автоматизира. Но присъствието на модул му заради потребността от функциите му не може да бъде определена от машина, понеже полезността на функциите му не може да се измери количествено.

  3. Longanlon Says:

    бизнес модулите са различните фирми за услуги, които могат да работят с много други фирми и да им предоставят услугите си. така може да произвеждаш коли, но счетоводните и правни услуги да ти ги вършат други фирми, ако ти потрябва нещо за строителство – има фирми предлагащи това и т.н.

    част от работата ми е да организирам точно такива “модули” заедно по различни проекти. тъй като проектите са с много различна насоченост, за всеки отделен си построявам дейността на база на различни фирми, които ми осигуряват различни услуги, които заедно водят до някаква цел, произвеждане на някакъв продукт (физически или не)

  4. Петър Петров Says:

    Мда, така си и помислих. Не може без “ръчен труд”, т.е. човешка преценка.

Leave a Reply