Оптимизация умножения на константу на Ассемблере
В предыдущей статье по оптимизации мы рассматривали замену команд деления, как это описано в "AMD Athlon Processor x86 Code Optimization Guide". Но в этом же мануале описана оптимизация умножения на константу. Тут нет универсальных алгоритмов, по которым можно было бы однозначно определить нужную последовательность команд замены, как в случае с делением. Для каждой константы набор команд определяется на основании их "весовых коэффициентов" и количества тактов процессора, необходимых для их выполнения. В качестве примера приведена вот такая табличка оптимизации умножения с 2 до 32. Ее всегда можно посмотреть и в самом мануале, но лучше пусть будет под рукой.Code (Assembler) : Убрать нумерацию
- ; Умножение на 2
- add reg1, reg1 ; 1 такт процессора
- ; Умножение на 3
- lea reg1, [reg1+reg1*2] ; 2 такта процессора
- ; Умножение на 4
- shl reg1, 2 ; 1 такт процессора
- ; Умножение на 5
- lea reg1, [reg1+reg1*4] ; 2 такта процессора
- ; Умножение на 6
- lea reg1, [reg1+reg1*2] ; 3 такта процессора
- add reg1, reg1
- ; Умножение на 7:
- mov reg2, reg1 ; 2 такта процессора
- shl reg1, 3
- sub reg1, reg2
- ; Умножение на 8:
- shl reg1, 3 ; 1 такт процессора
- ; Умножение на 9:
- lea reg1, [reg1+reg1*8] ; 2 такта процессора
- ; Умножение на 10:
- lea reg1, [reg1+reg1*4] ; 3 такта процессора
- add reg1, reg1
- ; Умножение на 11:
- lea reg2, [reg1+reg1*8] ; 3 такта процессора
- add reg1, reg1
- add reg1, reg2
- ; Умножение на 12:
- lea reg1, [reg1+reg1*2] ; 3 такта процессора
- shl reg1, 2
- ; Умножение на 13:
- lea reg2, [reg1+reg1*2] ; 3 такта процессора
- shl reg1, 4
- sub reg1, reg2
- ; Умножение на 14:
- lea reg2, [reg1+reg1] ; 3 такта процессора
- shl reg1, 4
- sub reg1, reg2
- ; Умножение на 15:
- lea reg1, [reg1+reg1*2] ; 4 такта процессора
- lea reg1, [reg1+reg1*4]
- ; Умножение на 16:
- shl reg1, 4 ; 1 такт процессора
- ; Умножение на 17:
- mov reg2, reg1 ; 2 такта процессора
- shl reg1, 4
- add reg1, reg2
- ; Умножение на 18:
- lea reg1, [reg1+reg1*8] ; 3 такта процессора
- add reg1, reg1
- ; Умножение на 19:
- lea reg2, [reg1+reg1*2] ; 3 такта процессора
- shl reg1, 4
- add reg1, reg2
- ; Умножение на 20:
- lea reg1, [reg1+reg1*4] ; 3 такта процессора
- shl reg1, 2
- ; Умножение на 21:
- lea reg2, [reg1+reg1*4] ; 3 такта процессора
- shl reg1, 4
- add reg1, reg2
- ; Умножение на 22:
- lea reg2, [reg1+reg1*4] ; 4 такта процессора
- add reg1, reg1
- lea reg1, [reg1+reg2*4]
- ; Умножение на 23:
- lea reg2, [reg1+reg1*8] ; 3 такта процессора
- shl reg1, 5
- sub reg1, reg2
- ; Умножение на 24:
- lea reg1, [reg1+reg1*2] ; 3 такта процессора
- shl reg1, 3
- ; Умножение на 25:
- lea reg1, [reg1+reg1*4] ; 4 такта процессора
- lea reg1, [reg1+reg1*4]
- ; Умножение на 26:
- lea reg2, [reg1+reg1*2] ; 4 такта процессора
- add reg1, reg1
- lea reg1, [reg1+reg2*8]
- ; Умножение на 27:
- lea reg1, [reg1+reg1*2] ; 4 такта процессора
- lea reg1, [reg1+reg1*8]
- ; Умножение на 28:
- lea reg2, [reg1*4] ; 3 такта процессора
- shl reg1, 5
- sub reg1, reg2
- ; Умножение на 29:
- lea reg2, [reg1+reg1*2] ; 3 такта процессора
- shl reg1, 5
- sub reg1, reg2
- ; Умножение на 30:
- lea reg2, [reg1+reg1] ; 3 такта процессора
- shl reg1, 5
- sub reg1, reg2
- ; Умножение на 31:
- mov reg2, reg1 ; 2 такта процессора
- shl reg1, 5
- sub reg1, reg2
- ; Умножение на 32:
- shl reg1, 5 ; 1 такт процессора
Но в процессе поисков информации я наткнулся на интересную статью "Integer multiplying by constants" на сайте программиста Paul Hsieh. Там приведена расширенная таблица оптимизированного умножения на константу. Кроме самой таблицы выложены исходники программы "MULTOPP5", которая ищет оптимальный алгоритм умножения. Из-за особенностей работы, максимальное значение константы, которое сможет оптимизировать эта программа, немногим превышает 2000. Я не силен в C, но может быть как-нибудь можно ее модифицировать, чтобы расширить диапазон поиска. Авторский исходник, скомпилированный консольный вариант и листинг результатов ее работы находятся в приложении к статье.
Просмотров: 8293 | Комментариев: 7
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(14.08.2013 в 11:58):
Добавил, спасибо!
anonym
(14.08.2013 в 11:42):
http://www.wasm.ru/forum/viewt...p?pid=366853
есть за что зацепится
из хорошо гуглящегося только файлик
multiply_constants.txt
с который был с утилитой findmul
есть за что зацепится
из хорошо гуглящегося только файлик
multiply_constants.txt
с который был с утилитой findmul
user
(06.08.2013 в 22:47):
Grey,
думаю, если реализовать таким образом
умножение на 22'222'222, уже будет проигрыш.
Ну, а на 2,4,..32 - да, выигрыш будет по-любому.
Вот что я хотел сказать.
думаю, если реализовать таким образом
умножение на 22'222'222, уже будет проигрыш.
Ну, а на 2,4,..32 - да, выигрыш будет по-любому.
Вот что я хотел сказать.
Grey
(05.08.2013 в 10:15):
В больших матрицах, особенно если они многократно перемножаются, обращаются и т.п. выигрыш полюбому будет.
user
(04.08.2013 в 20:36):
Ну - с этой точки зрения да.
Да и просто - красивое решение.
Да и просто - красивое решение.
ManHunter
(04.08.2013 в 20:33):
user, полностью согласен. Но всегда же может появиться необходимость обратной совместимости, или та же обфускация/метаморфирование с заменой команд. Знаний много не бывает :)
user
(04.08.2013 в 20:26):
Позволю себе высказать предположение,
что подобная оптимизация умножения "на любое число"
вряд-ли целесообразна. На старых процессорах это ещё
имело бы смысл (8086 - MUL r16 - до 133 тактов).
Но уже на P5 она же - 11 тактов.
Видимо, главное - это обеспечить нахождение операндов
в регистрах, т.е. применять высокоуровневую оптимизацию,
пренебрежение которой способно многократно снизить выигрыш
от низкоуровневых изощрений...
что подобная оптимизация умножения "на любое число"
вряд-ли целесообразна. На старых процессорах это ещё
имело бы смысл (8086 - MUL r16 - до 133 тактов).
Но уже на P5 она же - 11 тактов.
Видимо, главное - это обеспечить нахождение операндов
в регистрах, т.е. применять высокоуровневую оптимизацию,
пренебрежение которой способно многократно снизить выигрыш
от низкоуровневых изощрений...
Добавить комментарий
Заполните форму для добавления комментария