Чтение онлайн

на главную - закладки

Жанры

Шрифт:

46. Оптимизация переходов и вызовов подпрограмм

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

Быстродействие данных процессоров в значительной мере зависит от их архитектуры, основанной на простой конвейерной схеме, которая содержит три компоненты: шинный интерфейс (BIU – Bus Interface Unit), очередь упреждающей выборки и исполнительный модуль (EU – Execution Unit). Если шина памяти в нерабочем состоянии, например в случае выполнения команды из многих циклов, с операндами, находящимися в регистрах, шинный интерфейс получает байты команд из памяти и располагает их в очередь упреждающей выборки, последовательно продвигаясь дальше от текущего расположения командного счетчика центрального процессора. Когда исполнительный модуль заканчивает выполнение очередной команды, он ищет следующую команду в ряде упреждающей выборки: если она есть, к ее расшифровке можно приступать непосредственно, не обращаясь лишний раз к памяти.

Каждый раз, когда исполнительный модуль уточняет команду перехода или вызова, он аннулирует теку46б щее содержимое очереди упреждающей выборки и определяет новый счетчик команд. Затем шинный интерфейс снова выбирает байты команд, начиная при этом с нового адреса, и заносит их в очередь. Исполнительный модуль в это время должен «простаивать», пока не будет определена полная команда. При этом все обращения к памяти, необходимые для исполнения команды перехода по новому адресу, тоже влияют на выборку следующих команд из памяти. Может пройти много времени, прежде чем шина опять заполнит очередь упреждающей выборки, так, чтобы применяемый модуль мог работать с наибольшей скоростью. Кроме того, размер очереди командных байтов не одинаков для разных моделей центральных процессоров. Он составляет только 4 байта в ранних моделях и 32 байта в современных компьютерах. Таким образом, крайне сложно предсказать время исполнения для данных последовательностей команд исходя из количества тактов и длин в байтах. Также состояние очереди команд для разных типов центральных процессоров определяется «выравниванием» команд. Шинный интерфейс обязан выбирать команды по разрядности адресной и информационной частей шины.

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

47. Оптимизация циклов

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

1. Никогда не следует делать в цикле ничего такого, что можно сделать вне его.

2. Где это можно, следует избавиться от передач управления внутри циклов.

Первое правило следует из истины, по которой 90 % времени исполнения программы приходится на 10 % ее кода. Эти 10 % чаще всего оказываются циклами того или иного рода. Таким образом, первое, что необходимо сделать для ускорения выполнения программы, – это определить в ней «горячие точки» и проверить все циклы в них в качестве потенциальных объектов оптимизации. Цикл далеко не всегда представляет собой изящную конструкцию, которая завершается командами LOOP, LOOPZ или LOOPNZ; часто это просто серия команд, выполнение которых повторяется в зависимости от величины некоторой управляющей переменной или флажка.

Циклы можно разделить на два вида: к первому относятся циклы со временем исполнения, которое определяется некоторыми внешними механизмами синхронизации, ко второму – те, в которых участвует только процессор. Примером первого вида цикла служит такой, в котором набор символов передается на параллельный порт. Скорость выполнения программы никогда не будет выше темпа приема байтов параллельным портом, а быстродействие данного порта на два порядка ниже, чем время выполнения любой приемлемой кодовой последовательности управления портом. Оптимизация подобных циклов с внешней синхронизацией не часто применяется. Циклы второй категории – свободные от взаимодействия с «внешним миром».

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

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

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

48. Управляющие таблицы

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

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

Покажем прикладную систему, в которой удобнее всего применять управляющие таблицы. Это программа, в которой необходимо поворачивать и перемещать отрезки линий, чтобы создавать у пользователя иллюзию объемного изображения. Подобная программа должна определять синусы и косинусы углов. Для вычисления данных функций обычно используют числа с плавающей точкой и разложение в ряды, расчет которых влечет за собой множественные умножения и деления, а эти операции по времени счета «дорогостоящие». При этом получаемые величины обладают значительно большей точностью, чем это реально необходимо для обычных графических адаптеров персональных компьютеров: даже цифры с плавающей точкой одинарной точности (32 разряда) вычисляются до 8 десятичных знаков, из которых необходимы только 4 или 5. В подобной задаче и можно пользоваться преимуществами таблицы, в которую можно занести синусы углов с шагом в 1 градус и с точностью до 4 десятичных знаков.

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

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

Поделиться:
Популярные книги

Возвращение

Кораблев Родион
5. Другая сторона
Фантастика:
боевая фантастика
6.23
рейтинг книги
Возвращение

Вперед в прошлое 9

Ратманов Денис
9. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 9

Кукловод

Майерс Александр
4. Династия
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Кукловод

Господин Хладов

Шелег Дмитрий Витальевич
4. Кровь и лёд
Фантастика:
аниме
5.00
рейтинг книги
Господин Хладов

Мужчина моей судьбы

Ардова Алиса
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Мужчина моей судьбы

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Последний Паладин. Том 6

Саваровский Роман
6. Путь Паладина
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 6

Первый среди равных. Книга VIII

Бор Жорж
8. Первый среди Равных
Фантастика:
аниме
фантастика: прочее
эпическая фантастика
попаданцы
5.00
рейтинг книги
Первый среди равных. Книга VIII

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

Звездная Кровь. Экзарх I

Рокотов Алексей
1. Экзарх
Фантастика:
боевая фантастика
рпг
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Экзарх I

Дракон

Бубела Олег Николаевич
5. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.31
рейтинг книги
Дракон

Девяностые приближаются

Иванов Дмитрий
3. Девяностые
Фантастика:
попаданцы
альтернативная история
7.33
рейтинг книги
Девяностые приближаются

Точка Бифуркации IV

Смит Дейлор
4. ТБ
Фантастика:
героическая фантастика
городское фэнтези
попаданцы
5.00
рейтинг книги
Точка Бифуркации IV

Эволюционер из трущоб. Том 4

Панарин Антон
4. Эволюционер из трущоб
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Эволюционер из трущоб. Том 4