Tempora mutantur, et nos mutamur in illis




НазваниеTempora mutantur, et nos mutamur in illis
страница1/9
Дата публикации09.03.2013
Размер1.08 Mb.
ТипДокументы
uchebilka.ru > Информатика > Документы
  1   2   3   4   5   6   7   8   9

ТЕХНИКА ОПТИМИЗАЦИИ ПРОГРАММ
ТОМ I
Подсистема оперативной памяти: основная оперативная память, контроллер памяти, кэш
Энциклопедия



Крис Касперски

kpnc@programme.ru

kpnc@itech.ru
TEMPORA MUTANTUR, ET NOS MUTAMUR IN ILLIS
(Времена меняются и мы меняемся с ними лат.)


Аннотация


Хотите заглянуть внутрь черного ящика подсистемы оперативной памяти? Хотите узнать: что чувствует, чем дышит и какими мыслями живет каждая микросхема вашего компьютера? Хотите научиться минимальными усилиями создавать эффективный программный код, исполняющийся вдвое – втрое быстрее обычного? Хотите использовать возможности современного оборудования на полную мощь? Тогда – вы не ошиблись в выборе книги!

Перед вами лежит уникальное практическое пособие по оптимизации программ под платформу IBM PC и операционные системы семейства Windows (UNIX), скрупулезно описывающее архитектуру, философию и принципы функционирования современных микропроцессоров, чипсетов, оперативной памяти, операционных систем, компиляторов и прочих компонентов ПК.

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

Здесь вы найдете и оригинальные приемы программирования, и недокументированные секреты, существование которых Intel и Microsoft хотели бы скрыть, и разъяснение туманных пунктов фирменной документации (включая указания на многочисленные ошибки и неточности!), и перечень типовых ошибок программистов, снижающих производительность системы, и вполне готовые к использованию решения, и…

Основной упор сделан на процессоры AMD Athlon, Intel Pentium-III и Intel Pentium-4 и языки программирования Си/Си ++ (впрочем, описываемые техники не привязаны ни к какому конкретному языку, и знание Си требуется лишь для чтения исходных текстов примеров, приведенных в книге).


^

Об авторе


Если говорить о себе кратко – "я просто познаю окружающий мир и получаю от этого удовольствие". Компьютерами одержим еще со старших классов средней школы (или еще раньше – уже, увы, не помню).

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

Из всех языков программирования больше всего люблю ассемблер, но при разработке больших проектов предпочитаю С (реже – C++). Для создания сетевых приложений прибегаю к помощи Perl и Java, ну а макросы в Word'e и Visual Studio пишу на Бейсике. Эпизодически балуюсь Forth'ом и всякими "редкоземельными" языками наподобие Python'a. Впрочем, важен не сам язык, а мысли, которые этим языком выражают.

Но все-таки, компьютеры – не единственное и, вероятно, даже не самое главное увлечение в моей жизни. Помимо возни с железом и блужданий в непроходимых джунглях защитного кода, я не расстаюсь с миром звезд и моих телескопов, много читаю, да и пишу тоже (в последнее время как-то больше пишу, чем читаю).

"^ Техника оптимизации программ" – уже седьмая по счету моя книга. Предыдущие: "Техника и философия хакерских атак", "Техника сетевых атак", "Образ мышления – дизассемблер IDA", "Укрощение Интернет", "Фундаментальные основы хакерства. Искусство дизассемблирования" и "Предсказание погоды по местным атмосферным признакам" были горячо одобрены читателями и неплохо расходились, несмотря на то, что ориентированы на очень узкий круг читателей (гораздо более узкий, нежели "Техника оптимизации программ").

Помимо этому моему перу принадлежит свыше двухсот статей, опубликованных в журналах "Программист", "Открытые системы", "Инфо - бизнес", "Компьютерра", "LAN", "eCommerce World", "Mobile", "Byte", "Remont & Service", "Astronomy", "Домашний компьютер", "Интерфейс", "Мир Интернет", "Магия ПК", "Мегабайт", "Полный ПК", "Звездочет" и др.

Хакерские мотивы моего творчества не случайны и объясняются по-детски естественным желанием заглянуть "под капот" компьютера и малость потыкать его "ломом" и "молоточком", разумеется, фигурально - а как же иначе понять как эта штука работает? Если людей, одержимых познанием окружающего мира, считать хакерами, то я – хакер.
Адреса электронной почты для связи с автором: kpnc@programme.ru

kpnc@itech.ru


^

Введение в книгу




О серии книг "Оптимизация"


Ну вот, – воскликнет, иной читатель, – опять серия! Да сколько же можно этому Касперски объявлять серий?! И что интересно: все серии разные! Выпущен первый том "Техники сетевых атак", но вот уже года три как нет второго. Объявлен трехтомник "Образ мышления – IDA", но до сих пор вышли только первый и третий тома книги, а второго по прежнему нет и в обозримом будущем даже и не предвидится. Наконец, "Фундаментальные Основы Хакерства. Искусство Дизассемблирования" – это вновь всего лишь первый том! Так не лучше ли автору сконцентрироваться на чем ни будь одном, а не метаться по всей предметной области?

Кто-то даже сравнил меня с Кнутом – мол обещал семь томов, а выпустил только три. Но если Кнут выпустил три тома одной книги, то Касперски – по одному тому трех разных. Ситуация осложняется тем, что мой издатель по маркетинговым соображением наотрез отказался называть настоящую книгу томом. Хорошо, пусть это будет не "том", пусть это будет "первая книга серия". (Суть дела от этого все равно меняется).

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

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


^

Том I
Оперативная память


Оптимизация на уровне структур данных и алгоритмов их обработки. Ориентирована на прикладных и системных программистов.

Настоящая книга включает лишь половину запланированного материала первого тома. Остающаяся либо выйдет отдельной книгой, либо (что более вероятно) появится во втором издании настоящей книги.

Предполагаемый срок выхода: начало 2003 года


^

Том II
Процессор


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

Предполагаемый срок выхода: начало 2004 года


^

Том III
Автоматическая кодогенерация


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

Предполагаемый срок выхода: начало 2005 года


^

Том IV
Ввод/вывод


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

Предполагаемый срок выхода: начало 2006 года


^

Том V
Параллельные вычисления и суперкомпьютеры


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

Предполагаемый срок выхода: не известен


^

Краткая история создания данной книги


Настоящая книга задумывалась отнюдь не ради коммерческого успеха (который вообще сомнителен – ну много ли людей сегодня занимаются оптимизацией?), а писалась исключительно ради собственного удовольствия (как говорится: ^ UTILE DULCI MISCEREсоединять приятно с полезным).

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

Вплотную столкнувшись с необходимостью оптимизации еще во времена древних и ныне скоропостижно почивших 8-рязрядных машин, я скорее по привычке, чем по насущной необходимости, сохранил преданность эффективному коду и настоящих дней. А потому, не без оснований считал, что "собаку съел" на оптимизации и искренне надеялся, что писать на эту тему мне будет очень легко. Вот только бы выяснить несколько "темных" мест и объяснить некоторые странности поведения процессора, до анализа которых раньше просто не доходили руки...

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

Поверьте! Я вовсе не мячик пинал и каждый день проводил за компьютером как минимум по 12 – 15 часов, благодаря чему большая часть прежде темных мест выступила из мрака и теперь ярко освещена! Быть может, это и не очень производительный труд (и вообще крайний низкий выход в пересчете на символ – в – час), тем не менее проделанной рабой в целом я остался доволен. И не удивительно! Изучать "железки" – это до жути интересно. Перед вами – черный ящик и все, что вы можете – планировать и осуществлять различные эксперименты, пытаясь описать их результаты некоторой математической моделью, проверяя и уточняя ее последующими экспериментами. И вот так из черного ящика постепенно начинают проступать его внутренности и Вы уже буквально "чувствуете" как он работает и "дышит"! А какое вселенское удовлетворение наступает, когда бессмысленная и совершенно нелогичная паутина результатов замеров наконец-то ложится в стройную картину! Чувство, охватывающее вас при этом, можно сравнить разве что с оргазмом!


^

Соглашения об условных обозначениях и наименованиях


Расшифровку всех непонятных терминов, если таковые встретятся вам по ходу чтения книги, можно узнать в глоссарии. Но, поскольку, в глоссарий по обыкновению все равно никто не заглядывает, ниже перечислены обозначения, которые с наибольшей степенью вероятности могут вызвать затруднение.
1) Под P6-процессорами понимаются все процессоры с ядром P6, построенные по архитектуре Pentium Pro. К ним принадлежат: сам Pentium Pro, Pentium-II и Pentium-III, а так же процессоры семейства CELERON.
2) Процессоры серии Pentium здесь сокращаются до первой буквы "P" и стоящей за ней суффиксом, уточняющим какая именно модель имеется ввиду. Например, "P Pro" обозначает "Pentium Pro", а "P 4" – "Pentium 4". Кстати, обратите особое внимание, что индексы "II" и "III" записываются римскими цифрами, а "4" – арабскими. Так хочет фирма Intel (она уже однажды сделала мне замечание по этому поводу), поэтому не будем ей противоречить. В конце концов, хозяин – барин.
3) Под "MS VC" или даже просто "VC" подразумевается Microsoft Visual C++ 6.0, а под "BC" – Borland C++ 5.5. Соответственно, "WPP" обозначает "WATCOM C++ 10.0".
4) Кабалистическое выражение наподобие "P-III 733/133/100/I815EP" расшифровывается так: "процессор Intel Pentium-III с тактовой частой 773 MHz, частой системной шины 133 MHz и частой памяти 100 MHz, установленный в материнскую плату, базирующуюся на чипсете Intel 815 EP".

Соответственно, "AMD Athlon 1050/100/100/VIA KT 133" обозначает: "процессор AMD Athlon с тактовой частотой 1050 MHz, частотой системной шины 100 MHz и частотой работы памяти 100 MHz, уставленный в материнскую плату, базирующуюся на чипсете VIA KT 133".
Да, чуть не забыл сказать. "^ Сверхоперативная память" – это русский эквивалент американского термина "cache memory". Здесь он будет использоваться вовсе не из-за самостийной гордости, а просто для того, чтобы избежать излишней тавтологии (частого повторения одних и тех же слов).


^

Введение в оптимизацию




pro et contra целесообразности оптимизации


Это в наше-то время говорить об оптимизации программ? Бросьте! Не лучше ли сосредоточиться на изучении классов MFC или технологии .NET? Современные компьютеры так мощны, что даже Windows XP оказывается бессильна затормозить их!

Нынешние программисты к оптимизации относятся более чем скептически. Позволю себе привести несколько типичных высказываний:
"…я применяю относительно медленный и жадный до памяти язык, Perl, поскольку на нем я фантастически продуктивен. В наше время быстрых процессоров и огромной памяти эффективность – другой зверь. Большую часть времени я ограничен вводом/выводом и не могу читать данные с диска или из сети так быстро, чтобы нагрузить процессор. Раньше, когда контекст был другим, я писал очень быстрые и маленькие программы на C. Это было важно. Теперь же важнее быстро писать, поскольку оптимизация может привести к столь малому росту быстродействия, что он просто не заметен" говорит Robert White;
"…а стоит ли тратить усилия на оптимизацию и чего этим можно достичь? Дело в том, что чем сильнее вы будете адаптировать вашу программу к заданной архитектуре, тем, с одной стороны, вы достигнете лучших результатов, а, с другой стороны, ваша программа не будет хорошо работать на других платформах. Более того, "глубокая" оптимизация может потребовать значительных усилий. Все это требует от пользователя точного понимания чего он хочет добиться и какой ценой" пишет в своей книге "Оптимизация программ под архитектуру CONVEX C" М. П. Крутиков;
"Честно говоря, я сам большой любитель "вылизывания" кода с целью минимизации используемой памяти и повышения быстродействия программ. Наверное, это рудименты времен работы на ЭВМ с оперативной памятью в 32 Кбайт. С тем большей уверенностью я отношу "эффективность" лишь на четвертое место в критериях качества программ" признается Алексей Малинин – автор цикла статей по программированию на Visual Basic в журнале "Компьютер Пресс".

С приведенными выше тезисами, действительно, невозможно не согласиться. Тем не менее, не стоит бросаться и в другую крайность. Начертавший на своем знамени лозунг "на эффективность – плевать" добьется только того, что плевать (причем дружно) станут не в эффективность, а в него самого. Не стоит переоценивать аппаратные мощности! И сегодня существуют задачи, которым не хватает производительности даже самых современных процессоров. Взять хотя бы моделирование различных физических процессов реального мира, обработку видео-, аудио- и графических изображений, распознавание текста… Да что угодно, вплоть до элементарного сжатия данных архиватором a la Super Win Zip!

Да, мощности процессоров растут, но ведь параллельно с этим растут и требования к ним. Если раньше считалось нормальным, поставив программу на выполнение, уйти пить пиво, то сегодняшний пользователь хочет, чтобы все операции выполнялись мгновенно, ну если не мгновенно, то с задержкой не превышающей нескольких минут. Не стоят на месте и объемы обрабатываемых данных. Признайтесь, доводилось ли вам находить на своем диске файл размером в сотню-другую мегабайт? А ведь буквально вчера емкость целого жесткого диска была на порядок меньше!!!

^ Цель – определяет средства. Вот из этого, на протяжении всей книги, мы и будем исходить. Ко всем оптимизирующим алгоритмам будут предъявляется следующие жесткие требования:

а) оптимизация должна быть максимально машинно-независимой и переносимой на другие платформы (операционные системы) без дополнительных затрат и существенных потерь эффективности. То есть никаких ассемблерных вставок! Мы должны оставаться исключительно в рамках целевого языка, причем, желательно использовать только стандартные средства, и любой ценой избегать специфичных расширений, имеющихся только в одной конкретной версии компилятора;
б) оптимизация не должна увеличивать трудоемкость разработки (в т.ч. и тестирования) приложения более чем на 10%-15%, а в идеале, все критические алгоритмы желательно реализовать в виде отдельной библиотеки, использование которой не увеличивает трудоемкости разработки вообще;
с) оптимизирующий алгоритм должен давать выигрыш не менее чем на 20%-25% в скорости выполнения. Приемы оптимизации, дающие выигрыш менее 20% в настоящей книге не рассматриваются вообще, т.к. в данном случае "овчинка выделки не стоит". Напротив, основной интерес представляют алгоритмы, увеличивающие производительность от двух до десяти (а то и более!) раз и при этом не требующие от программиста сколь ни будь значительных усилий. И такие алгоритмы, пускай это покажется удивительным, в природе все-таки есть!
d) оптимизация должна допускать безболезненное внесение изменений. Достаточно многие техники оптимизации "умерщвляют" программу, поскольку даже незначительная модификация оптимизированного кода срубает всю оптимизацию на корню. И пускай все переменные аккуратно распределены по регистрам, пускай тщательно распараллелен микрокод и задействованы все функциональные устройства процессора, пускай скорость работы программы не увеличить и на такт, а ее размер не сократить и на байт! Все это не в силах компенсировать утрату гибкости и жизнеспособности программы. Поэтому, мы будем говорить о тех, и только тех приемах оптимизации, которые безболезненно переносят даже кардинальную перестройку структуры программы. Во всяком случае, грамотную перестройку. (Понятное дело, что кривые руки угробят что угодно – против лома нет приема).

Согласитесь, что такая постановка вопроса очень многое меняет. Теперь никто не сможет заявить, что, дескать, лучше прикупить более мощный процессор, чем тратить усилия на оптимизацию. Ключевой момент предлагаемой концепции состоит в том, что никаких усилий на оптимизацию тратить как раз не надо. Ну… почти не надо, – как минимум вам придется прочесть эту книжку, а это какие – ни какие, а все-таки усилия. Другой вопрос, что данная книга предлагает более или менее универсальные и вполне законченные решения, не требующие индивидуальной подгонки под каждую решаемую задачу.

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

И в заключении позвольте привести еще одну цитату:
"^ Я программирую, чтобы решать проблемы, и обнаружил, что определенные мысли блокируют все остальные мысли и творческие цели, которые у меня есть.
Это
 – мысли об эффективности в то время, когда я пытаюсь решить проблему. Мне кажется, что гораздо логичнее концентрироваться полностью на проблеме, решить ее, а затем творчески запрограммировать, затем, если решение медленное (что затрудняет работу с ним), то..."

Gary Mason.


^

О чем и для кого предназначена эта книга


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

Она ориентирована на прикладных программистов, владеющих (хотя бы в минимальном объеме) языком Си, а так же на системных программистов, знающих ассемблер. Описываемые техники не привязаны ни к какому языку и знание Си требуется лишь для чтения исходных текстов примеров, приведенных в книге.

В не меньшей степени "Техника оптимизации" будет интересна и лицам, занимающимся сборкой и настройкой компьютеров, поскольку подробно описывает устройство "железа" и разбирает "узкие места" распространенных моделей комплектующих.

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

Материал книги в основном ориентирован на микропроцессоры AMD Athlon и Intel Pentium-II, Pentium-III и Pentium-4, но местами описываются и более ранние процессоры.


^

Что нам понадобится




Как учатся оптимизации


Было бы слишком наивно ожидать от книги, что она научит вас писать эффективный код. Нет! По этому поводу уместно вспоминать детский анекдот, когда верзила-двоечник говорит своему "очкаристому" однокласснику "Дай мне твою самую толстую книгу – я ее прочитаю и буду таким же умным как ты". Книгу – извольте, но


^

Семь китов оптимизации или
Жизненный цикл оптимизации


Часто программист (даже высококвалифицированный!) обнаружив профилировщиком "узкие" места в программе, автоматически принимает решение о переносе соответствующих функций на ассемблер. А напрасно! Как мы еще убедимся (см. "Часть III. Ассемблер vs компилятор"), разница в производительности между ручной и машинной оптимизацией в подавляющем большинстве случаев очень невелика. Очень может статься так, что улучшать уже нечего, – за исключением мелких, "косметических" огрехов, результат работы компилятора идеален и никакие старания не увеличат производительность, более чем на 3%–5%. Печально, если это обстоятельство выясняется лишь после переноса одной или нескольких таких функций на ассемблер. Потрачено время, затрачены силы… и все это впустую. Обидно, да?

Прежде, чем приступать к ручной оптимизации не мешало бы выяснить: насколько не оптимален код, сгенерированный компилятором, и оценить имеющийся резерв производительности. Но не стоит бросаться в другую крайность и полагать, что компилятор всегда генерирует оптимальный или близкий к тому код. Отнюдь! Все зависит от того, насколько хорошо вычислительный алгоритм ложиться в контекст языка высокого уровня. Некоторые задачи решаются одной машинной инструкцией, но целой группой команд на языках Си и Паскаль. Наивно надеяться, что компилятор поймет физический смысл компилируемой программы и догадается заменить эту группу инструкций одной машинной командой. Нет! Он будет тупо транслировать каждую инструкцию в одну или (чаще всего) несколько машинных команд, со всеми вытекающими отсюда последствиями…


^

Правило I


Прежде, чем оптимизировать код, обязательно следует иметь надежно работающий не оптимизированный вариант или "...put all your eggs in one basket, after making sure that you've built a really *good* basket" ("…прежде, чем класть все яйца [не обязательно именно свои яйца – прим. КК] в одну корзину – убедись, что ты построил действительно хорошую корзину). Т.е. прежде, чем приступать к оптимизации программы, убедись, что программа вообще-то работает.

Создание оптимизированного кода "на ходу", по мере написания программы, невозможно! Такова уж специфика планирования команд – внесение даже малейших изменений в алгоритм практически всегда оборачивается кардинальными переделками кода. Потому, приступайте к оптимизации только после тренировки на "кошках", – языке высокого уровня. Это поможет пояснить все неясности и темные места алгоритма. К тому же, при появлении ошибок в программе подозрение всегда падает именно на оптимизированные участки кода (оптимизированный код за редкими исключениями крайне ненагляден и чрезвычайно трудно читаем, потому его отладка – дело непростое), – вот тут-то и спасает "отлаженная кошка". Если после замены оптимизированного кода на не оптимизированный ошибки исчезнут, значит, и в самом деле виноват оптимизированный код. Ну, а нет, – ищите их где-нибудь в другом месте.


^

Правило II


Помните, что основой прирост оптимизации дает не учет особенностей системы, а алгоритмическая оптимизация. Никакая, даже самая "ручная" оптимизация не позволит существенно увеличить эффективность пузырьковой сортировки или процедуры линейного поиска. Правильное планирование команд и прочите программистские трюки ускорят программу в лучшем случае в несколько раз. Переход к быстрой сортировке (quick sort) и двоичному поиску сократят время обработки данных как минимум на порядок, – как бы криво ни был написан программный код. Поэтому, если ваша программа выполняется слишком медленно, лучше поищите более эффективные математические алгоритмы, а не выжимайте из изначально плохого алгоритма скорость по капле.


^

Правило III


Не путайте оптимизацию кода и ассемблерную реализацию. Обнаружив профилировщиком узкие места в программе, не торопитесь переписывать их на ассемблер. Сначала убедитесь, что все возможное для увеличения быстродействия кода в рамках языка высокого уровня уже сделано. В частности, следует избавиться от прожорливых арифметических операций (особенно обращая внимание на целочисленное деление и взятие остатка), свести к минимуму ветвления, развернуть циклы с малым количеством итераций… в крайнем случае, попробуйте сменить компилятор (как было показано выше – качество компиляторов очень разниться друг к другу). Если же все равно останетесь недовольны результатом тогда…


^

Правило IV


Прежде, чем порываться переписывать программу на ассемблер, изучите ассемблерный листинг компилятора на предмет оценки его совершенства. Возможно, в неудовлетворительной производительности кода виноват не компилятор, а непосредственно сам процессор или подсистема памяти, например. Особенно это касается наукоемких приложений, жадных до математических расчетов и графических пакетов, нуждающихся в больших объемах памяти. Наивно думать, что перенос программы на ассемблер увеличит пропускную способность памяти или, скажем, заставит процессор вычислять синус угла быстрее. Получив ассемблерный листинг откомпилированной программы (для Microsoft Visual C++, например, это осуществляется ключом "/FA"), бегло просмотрите его глазами на предмет поиска явных ляпов и откровенно глупых конструкций наподобие: "MOV EAX,[EBX]\MOV [EBX],EAX". Обычно гораздо проще не писать ассемблерную реализацию с чистого листа, а вычищать уже сгенерированный компилятором код. Это требует гораздо меньше времени, а результат дает ничуть не худший.


^

Правило V


Если ассемблерный листинг, выданный компилятором, идеален, но программа без видимых причин все равно исполняется медленно, не отчаивайтесь, а загрузите ее в дизассемблер. Как уже отмечалось выше, оптимизаторы крайне неаккуратно подходят к выравниванию переходов и кладут их куда глюк на душу положит. Наибольшая производительность достигается при выравнивании переходов по адресам, кратным шестнадцати, и будет уж совсем хорошо, если все тело цикла целиком поместиться в одну кэш-линейку (т.е. 32 байта). Впрочем, мы отвлеклись. Техника оптимизации машинного кода – тема совершенно другого разговора. Обратитесь к документации, распространяемой производителями процессоров – Intel и AMD.


^

Правило VI


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


^

Правило VII


Если уж взялись писать на ассемблере, пишите максимально "красиво" и без излишнего трюкачества. Да, недокументированные возможности, нетрадиционные стили программирования, "черная магия", – все это безумно интересно и увлекательно, но… плохо переносимо, непонятно окружающим (в том числе и себе самому после возращения к исходнику десятилетней давности) и вообще несет в себе массу проблем. Автор этих строк неоднократно обжигался на своих же собственных трюках, причем самое обидное, что трюки эти были вызваны отнюдь не "производственной необходимостью", а… ну, скажем так, "любовью к искусству". За любовь же, как известно, всегда приходится платить. Не повторяете чужих ошибок! Не брезгуйте комментариями и непременно помещайте все ассемблерные функции в отдельный модуль. Никаких ассемблерных вставок – они практически непереносимы и создают очень много проблем при портировании приложений на другие платформы или даже при переходе на другой компилятор.

Единственная предметная область, не только оправдывающая, но, прямо скажем, провоцирующая ассемблерные извращения, это – защита программ, но это уже тема совсем другого разговора…


^

Несколько общих советов по оптимизации




Совет 1. Избегайте рекурсии



Совет 2. Избегайте операций деления и взятия остатка



Совет 3. Избегайте ветвлений



…а тем более в циклах

^

Совет 4. Устраняйте устраняемые зависимости по данным



…а особенно адресные


Совет 4. Разворачивайте компактные циклы



Совет 5. Используйте библиотеки от Intel



^

Вредные советы по оптимизации


В духе Остера позволим себе

Вредный совет 1
Используйте табличные вычисления вместо расчетов


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

Рассмотрим пример с вычислением синуса угла. Пусть нам необходимо знать его с точностью до одной угловой минуты, тогда в худшем случае таблица займет: 90*60*sizeof(float) = 21.6 Kb, что совсем немного даже по понятиям восьмидесятых. Используя же простейшие алгоритмы интерполяции мы, не сильно проиграв в производительности и точности, уменьшим этот размер минимум раза в два, а то и в четыре. А теперь вспомним, что вы
не выполнять вычисления каждый раз

"на лету
Вредные советы и

^

Распространенные заблуждения


Оптимизация овеяна многочисленными заблуждениями, которые вызывают снисходительную улыбку у профессионалов, но зачастую необратимо уродуют психику и калечат мировоззрение новичков. Я думаю, профессионалы не обидятся на меня за то, что я потратил несколько страниц книги, чтобы их развеять (естественно, заблуждения, а не самих профессионалов):


^

Заблуждение I
За меня все оптимизирует мой компилятор!


Вера в могущество компиляторов в своем коре счету абсолютно безосновательна. Хороший оптимизирующий компилятор по большому счету может похвастаться лишь своим умением эффективно транслировать грамотно спроектированный код, т.е. если он не сильно ухудшает исходную программу – уже за это его разработчикам следует сказать "спасибо".

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


^

Заблуждение II
Максимальная эффективность достижима лишь при программировании на чистом ассемблере, но отнюдь не языке высокого уровня


Перенос программы на ассемблер только в исключительных случаях увеличивает ее эффективность. При трансляции качественного исходного кода, оптимизирующие компиляторы отстают от идеальной ручной оптимизации не более чем на 10%-20%. Конечно, это весьма ощутимая величина, но все же не настолько, чтобы оправдать трудоемкость программирования на чистом ассемблере!

Подробнее о сравнении качества машинной и ручной оптимизации см. "Часть III. Ассемблер vs Компилятор".


^

Заблуждение III
Человек, в отличии от оптимизирующего компилятора, просто физически не способен учесть все архитектурные особенности процессора


Вообще говоря, кроме компиляторов, разрабатываемых Intel, никакие другие компиляторы не умеют генерировать оптимальный с точки зрения процессора код. Несколькими страницами позднее (см. "Практический сеанс профилировки с VTune") вы собственноручно сможете убедиться в этом, а пока же просто поверьте автору на слово.

Тем не менее, современные процессоры с одной стороны достаточно умны и самостоятельно оптимизируют переданный им на выполнение код, а с другой – кода, оптимального для всех процессоров, все равно не существуют и архитектурные особенности процессоров P-II, P-4, AMD K6 и Athlon отличаются друг от друга столь разительно, что все позывы к ручной оптимизации гибнут прямо на корю.

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


^

Заблуждение IV
Процессоры семейства x86 – полное дерьмо, вот на PowerPC, например, действительно есть место, где развернуться!


Как гласит народная мудрость "Хорошо там – где нас нет" Сам я, правда, ничего не оптимизирую под PowerPC, но знаком с людьми, разрабатывающими под него оптимизирующие компиляторы. И могу сказать, что они далеко не в восторге от его "закидонов", коих у него, поверьте уж, предостаточно.

Да, у серии x86 присущи многие проблемы и ограничения. Но это ничуть не оправдывает программистов, пишущих уродливых код и палец о палец не ударяющих, чтобы хоть как-то его улучшить.

А "язык" x86 процессоров между прочим очень интересен. На сегодняшний день они имеют едва ли не самую сложную систему команд, дающую системным программистам безграничные возможности для самовыражения. Прикладные программисты даже не догадываются сколько красок мира у них украли компиляторы!


  1   2   3   4   5   6   7   8   9

Добавить документ в свой блог или на сайт

Похожие:

Tempora mutantur, et nos mutamur in illis iconНовикова Михаила Петровича Gaudeamus tffttur Juvenes dum sunuts!...
Учебное пособие предназначено для студентов вузов и учащихся колледжей, гимназий, школ

Tempora mutantur, et nos mutamur in illis iconРеферат скачан с сайта allreferat wow ua
Возжелавшие ауспиций: «другие семьи» 7 Перспективы 8Раздел II. 10 “O tempora! O mores!” 10 Биология открытого брака 12 Моногамия...

Вы можете разместить ссылку на наш сайт:
Школьные материалы


При копировании материала укажите ссылку © 2013
контакты
uchebilka.ru
Главная страница


<