8.3. Низкоуровневая оптимизация
8.3.1. Основные принципы
Так как современные процессоры используют весьма сложный набор команд, большинство операций можно выполнить на низком уровне очень многими способами. При этом иногда оказывается, что наиболее очевидный способ – не самый быстрый. Часто простыми перестановками команд, зная механизм выполнения команд на современных процессорах, можно заставить ту же процедуру выполняться на 50–200% быстрее. Разумеется, переходить к этому уровню оптимизации можно только после того, как текст программы окончательно написан и максимально оптимизирован на среднем уровне.
Перечислим основные рекомендации.
Используйте регистр ЕАХ всюду, где возможно. Команды с непосредственным операндом, с операндом – абсолютным адресом переменной и команды XCHG с регистрами занимают на один байт меньше, если другой операнд – регистр ЕАХ.
Если к переменной в памяти, адресуемой со смещением, выполняется несколько обращений – загрузите её в регистр.
Не используйте сложные команды – ENTER, LEAVE, LOOP, строковые команды, если аналогичное действие можно выполнить небольшой последовательностью простых команд.
Не используйте умножение или деление на константу – его можно заменить другими командами (см. раздел 6.3).
Старайтесь программировать условия и переходы так, чтобы переход выполнялся по менее вероятному событию.
Следующее эмпирическое правило, относящееся к переходам и вызовам, очень простое: избавляться от них везде, где только можно. Для этого организуйте программу так, чтобы она исполнялась прямым, последовательным образом, с минимальным числом точек принятия решения. В результате очередь команд будет почти всегда заполнена, а вашу программу будет легче читать, сопровождать и отлаживать. Процедуры, особенно небольшие, нужно не вызывать, а встраивать. Это, конечно, увеличивает размер программы, но даёт существенный выигрыш во времени её исполнения.
Используйте короткую форму команды JMP, где возможно (jmp short <метка>).
Команда LEA быстро выполняется и имеет много неожиданных применений (см. раздел 8.3.2).
Многие одиночные команды, как это ни странно, выполняются дольше, чем две или три команды, приводящие к тому же результату. Это может быть связано с различными особенностями выполнения команд, в том числе, с возможностью/невозможность попарного выполнения команд в разных конвейерах (см. раздел 8.3.3).
Старайтесь выравнивать данные и метки по адресам, кратным 2/4/8/16 (см. раздел 8.3.4).
Если команда обращается к 32-битному регистру, например ЕАХ, сразу после команды, выполнявшей запись в соответствующий частичный регистр (АХ, AL, АН), может происходить пауза в один или несколько тактов.
Do'stlaringiz bilan baham: |