К. Касперски - Техника оптимизации программ, Эффективное использование памяти (1127752), страница 19
Текст из файла (страница 19)
Совет номер четыре и снова этот несчастный цикл подсчета контрольной суммы. Ну, понравился он Инструктору — что поделаешь! Что же ему не понравилось на этот раз? Читаем 121 Гоч (Ь = 0] Ь <= 1еьдбь( Ьчм 122 х ~ *((лФ. *] ((1ьь]рьча ь Ь] 123 рамо(р]=' у=О] 124 125 125 ] // еьв иь~1е(рва(] (15Е йЕ 1п(е! С/С++ Согпрйег чес(ог12ет (о ац(огиайсайу пепе(а(е 111яЬ(у орбп]12е(1 ЯМ 0 со(1е. ТЬе 5(а(еп]еп( оп Ппе 122 ап(1 ойегз! Йе и (чй1 Ье чес(оггвед (Т йе Гойо(ч(пя ргоягапт сйапяеб аге п]аде ГдоцЫе-сйс1( оп апу Ппе Гог гпоге 1пГогшайоп): ==> ЯгпрПГу йе ро!п(ег ехргезгйоп (о!пгйса(е соп(1яцопб апау ассеззез.
==> Кез(гцс(цге йе 1оор (о ьзо!а(е йе з(а(егпеп( ог сопз(гцс( йа( 1п(егГегез (ч!й чес(оптабоп. ==> Тгу!оор 1п(егсйапя!пя (о оЬ(а!п чес(ог со((е 1п йе (ппеппоа(!оор. ==> ЯгпрПТу йе ро(п(ег ехргезгйоп (о 1псйса(е соп(!яцоцз аггау ассеззез. Используйте векторизатор компилятора 1пге! С/С++ для автоматической генерации высоко оптимизированного Б1МР-кода. Оператор, находящийся в линни !22, и остальные подобные ему операторы будут векторизованы при условии следующих из (енений програл(мыг ==> упростите выражение указателя для индикации смежных доступов к массиву; ==> реструктурируйте цикл для отделения выражения или логической конструкции, препятствующей векторизации; ==> попытайтесь перестроить цикл для получения векторного кода во вложенном цикле; ==> упрости/пе выражение указателя для индикации смежных доступов к л(ас- сиву; 82 Глава Г Хорошие, однако, советы! А рекомендация упростить и без того примитивную форму адресации повторяется аж два раза! И это при том, что эффективно векторизовать данный цикл все равно не получится даже на 1пге! С/С+-р, а уж про все остальные компиляторы я и вовсе промолчу.
Тем не менее, все-таки заглянем за помощью — может быть что-нибудь интересное скажут!? 1пге! С++ Согврйег ч'ес1опаег ТЬе соасЬ Ьаз !депг1Тгед ап аза!цпшепг ог ехргеаз!оп йаг !з а санд!даге Гог ц[МР гесйпо1оцу соде цепегабоп ца!пц 1пге! С++ Сошр!!ег чесгог!аег. Адч!се чае йе 1пге! С++ Сошр!1ег чесгопаег го ашоптабса!!у цепегаге Ь!цИу орг!ш!аед Ц1МР соде ууйегечег арргорпаге 1п уоцг арр1!саг!оп. Рае йе Го!1оуч!пц зупгах го !пуп!ге йе чесгопаег Ггогп йе согшпапд йпе: ргоптрг>!с! -02 -Ях% шургоц.срр. ТЬе -9х% сопнпапд епаЫез чесгог!таг!оп оГ зоцгсе соде апд ргоч!дев асеева го огЬег чесгопгаг!оп-ге1агег1 орцопя Кави!1 ТЬе 1пге! С++ Сошр!1ег чесгог!аег орг!гп!аез уоцг арр!!сагюп Ьу ргосеаяпц дага ш рага11е1, цяпц йе Цггеаш!пц ЯМР Ехгепа!опа оГ йе 1пге1 ргосеьаогя Ц!псе йе Яггеагпшц Б1МР Ехгепа!опз гйаг г11е с1ааз 1!Ьгагу !гпр!ешепгз ассезз апд орегасе оп 2, 4, 8, ог 1б аггау е!егпепьз аг опе бизе, йе ргоцгаш ехесцгез пшсЬ Гаагег.
Вектаризатор компилятора 1пге1 С++ Инструктор идентифицировал присвоение или выражение, являющееся кандидатом для генерации кода по Б!МР-технологии, используемой векторизатором компилятора 1пге1 С++. Совету Используйте векторизатор колгпилятора 1пге1 С++ для автоматической генерации вьюокооптимизированного ПМР-кода, подходящего к вашему прилозкению.
Используйте следующий синтаксис для вызова векторизатора из колгандной строки: гст — 02 охи туреод. срр. Ключ "-охв" разрешает векторизацию исходного кода и предоставляет доступ к остальным векторным опциям. Профипировка программ 83 Результат: Векториэатор компилятора (п(еГ С++ оптимизирует ваше приложение путем параллельной обработки данных с использованием паточного ЯМ0-расширения команд процессоров Гп(ей С тех пор, как потоковые ЯМ!9-расширения библиоте- ки классов осуществляют доступ и обработку 2, 4, 8 или Гб элементов массива за один раэ, скорость выполнения программы весьиа значительно возрастает. Бесспорно, векторизация — полезная штука, действительно позволяющая многократно увеличить скорость работы программы, но ее широкому внедрению в массы препятствует, по меньшей мере, два минуса: во-первых, подавляюшее большинство х86-компиляторов не умеют векторизовать код, а перехол на компилятор 1п(е! не всегда приемлем.
Во-вторых, векторизация будет по настоящему эффективна лишь в том случае, если программа изначально спроектирована под эту технологию. И хотя в мире "больших" машин векторизация кода известна уже давно, для х86-программистов это еше тот конек! Совет номер пять или еще один просчет Инструктора. Так, посмотрим, что за перл выдал Инструктор на этот раз. 1( (х --ча11беае) 91 92 (( копируем шифрованные во временнвм буфер 93 Ьнгг (сьев *) ша)1ос (вев1еп (свтрееббаса) ) аьвсру(ьп((, спурсеббапа)( 94 95 98 О Расшифровываем Эебкурб(ранб, Ьп(Г)( 97 98 99 Вообше-то, формально Инструктор прав. Вынос инвариантных функций из тела цикла — это хороший тон программирования, поскольку, находясь в теле цикла, функция вызывается множество раз, но, в силу своей независи- ТЬе а(8шпеп( йв( Гог йе Гппсйоп сай (о гпа!!ос оп 1)пе 94 арреа(9 го Ье !оор(пуапап(.
1Гйеге аге по сопй(с(9 (ч!й ойег уапаЫез (и йе 1оор, апд !Г йе Гппсйоп Ьаз по 5!де ейес(5 апд по ех(егпа1 дерен(!епс(ез, пюуе г!)е са1! оп( оГ йе !оор. ГСписок аргументов функции 11, находящейся в строке 94„вероятно, инвприантен относительно цикла. Если это не вызовет конфликта с остальными переменными цикла, и если не будет иметь посторонних эффектов и внеи(них зависимостей, вынесите ее эа пределы цикла.) 84 Глава Г мости от параметров цикла, при каждом вызове она дает один и тот же результат. Действительно, не проще ли, единожды выделив память при входе в функцию, просто сохранить возрашенный указатель функции иьшьс в специальной переменной, а затем использовать его по мере необходимости? Возражение номер один: ну и что мы в результате этого получим? Данная ветка вызывается лишь при совпадении контрольной суммы текущего перебираемого пароля с эталонной контрольной суммой, что происходит крайне редко — в лучшем случае несколько раз за все время выполнения программы.
Возражение номер два: перефразируя известный анекдот "я девушку кормил-поил, я ее и танцевать буду"„можно сказать "та ветвь программы, которая выделила блок памяти, сама же его и освобождает, конечно, если это не приводит к неоправданному снижению производительности". Таким образом, ничего за пределы цикла мы выносить не будем, что бы там нам не советовал Инструктор. Совет номер шесть. Данный совет практически полностью повторяет предыдуший, однако, на этот раз. Инструктор посоветовал вынести за прелелы цикла функцию сь с~зрю Да, да! Счел ее инвариантом и посоветовал вынести куда подальше, и это не смотря на то, что: а) код самой функции в принципе был в его распоряжении ("в принципе" потому, что мы приказали Инструктору анализировать только функцию ч р с); б) функции сь сезрс передается указатель р щ который явным образом изменяется в цикле! А раз так, то инвариантом функция сь с~зр~ быть ну никак не может! И как только Инструктору не стыдно давать такие советы? Или все-таки стыдно— а вы думали, почему он красный такой? Совет номер семь.
Сейчас Инструктор обращает наше внимание на то, что: "ТЬе ча!пе гегпгпед Ьу Ре Сгург!) оп !!пе 98 !з по! пзед" (' Значение, возвращаемое функцией ое сгурс ы, расположенной в строке 98, не используется„,'9 и дает следуюший совет "1!' гйе гегигп ча!це !з Ье!пя !япогед, мт!ге ап а!гегпаге чеггйоп оГ гйе !ппсг!оп ччЬ!сЬ гегпгпз чо1д" (" Если возвращенное значение игнорируется, создайте альтернативную версию данной функции, возвращающей значение а".) В основе данного совета лежит допушение Инспектора, что функция, не возврашаюшая никакого значения, будет работать быстрее функции, такое значение возврашаюшей. На самом же деле это более чем спорно. Возврат значения занимает не так уж много времени, и создание двух экземпляров одной функции реально обходится много дороже, чем накладные расходы на возврат никому ненужного значения.
Так что игнорируем этот совет и идем дальше. Профипнровка программ Совет номер восемь. Теперь Инспектор принял за инвариант функцию о»г, распечатываюшую содержимое буфера ьигс, только что возвращенного функцией ов с»эре, Ну, неужели разработчикам профилировщика '»Типе было трудно заложить в "голову" Инспектора смысловое значение хотя бы основных библиотечных функций? Функция р» пег независимо от того, является ли оиа инвариантом или нет, никогда ие может быть выиесеиа за пределы цикла! И вряд ли стоит объяснять почему. Совет номер девять. Значение, возвращаемое функций р» п»г, не испоаьзуетсн, поэтому...
Что ж! Результатами такого инструктажа трудно остаться удовлетворенным. Из девяти советов мы ие воспользовались ии одним, поскольку это все равно бы не увеличило скорость выполнения программы. Тем ие менее, Ииструктора не стоит считать совсем уж никчемным чукчей. Во всяком случае, ои рассказывает о действительно интересных и эффективных приемах оптимизации, ие все из которых известны новичкам. Возможно, мие возразят, что такая непроходимая тупость Инструктора объясняется тем, что мы подсунули ему уже до предела оптимизированную программу и ему ничего ие осталось, как придираться к второстепенным мелочам.
Хорошо, давайте напустим Инструктора иа самый первый вариант программы, заставив его проанализировать весь код целиком. Он сделает иам 33 замечания, из которых полезиых по-прежиему ие окажется ии одного! Шаг десятый. Заключительный Все оставшиеся ) 7 "горячих" точек представляют собой издержки обращения к кэш-памяти и штрафные такты ожидания за неудачную с точки зрения процессора группировку комаид. Ладно, оставим обращения к памяти в стороне, вернее отдадим эту задачу на откуп неутомимым читателям (задумайтесгк зачем вообще теперь генерировать пароли, если их контрольная сумма считается без обращения к иим?) и займемся оптимальным планированием потока команд. Обратимся к другому мощному средству профилировщика 1ггцпе — автоматическому оптимизатору, по праву поевшему гордое имя "АяещЫу Соасй" (Ассемблерный Тренер — ие путайте его с Инструктором!).
Выделим, удерживая нажатой левую кнопку мыши, все тело функции дел рзио и найдем иа панели инструментов кнопку с изображением учителя (почему-то ярко- красного цвета), держащего указку наперевес. Нажмем ее. Глава ! На выбор нам предоставляются три варианта оптимизации, представленные в раскрываюшемся списке Мойе 01' Орегайоп, расположенном в верхнем левом углу окна программы: гз АвготаИс Орйшха1юв (Автоматическая оптимизация); гз В1вя1е Вгер Орйп(хайов (Пошаговая оптимизация); С) 1п1егас11зе Орйп(хаг(оп (Интерактивная оптимизация). Первые два режима не представляют особого интереса, а вот качество инте- рактивной оптимизации — выше всяческих похвал.