Я работаю над арифметикой умножения очень длинных целых чисел (около 100 000 десятичных цифр). В рамках моей библиотеки я добавил два длинных числа.
Профилирование показывает, что мой код работает до 25% своего времени в процедурах add() и sub(), поэтому важно, чтобы они выполнялись как можно быстрее. Но я пока не вижу большого потенциала. Может быть, вы можете дать мне некоторую помощь, совет, понимание или идеи. Я протестирую их и вернусь к вам.
Пока что моя процедура добавления выполняет некоторую настройку, а затем использует 8-кратный развернутый цикл:
mov rax, QWORD PTR [rdx+r11*8-64]
mov r10, QWORD PTR [r8+r11*8-64]
adc rax, r10
mov QWORD PTR [rcx+r11*8-64], rax
Далее следуют еще 7 блоков с разными смещениями, а затем цикл.
Раньше я пытался загрузить значения из памяти, но это не помогло. Я думаю, это из-за хорошей предварительной выборки. Я использую 4-ядерный процессор Intel i7-3770 Ivy Bridge. Но я хотел бы написать код, который хорошо работает на любом современном процессоре.
Редактировать: я сделал некоторые тайминги: он добавляет 1 тыс. слов примерно за 2,25 цикла на слово. Если я уберу АЦП, и останутся только MOV, это все равно займет около 1,95 цикла на слово. Таким образом, основным узким местом является доступ к памяти. Библиотека memcpy()
работает примерно за 0,65 цикла/слово, но имеет только один вход, а не два. Тем не менее, я думаю, он намного быстрее из-за использования регистров SSE.
Некоторые вопросы:
- Полезно ли использовать структуру «загрузка, загрузка, добавление, сохранение» или поможет «загрузка, добавление в память»? Пока мои тесты не показали никаких преимуществ.
- Как обычно, помощи от SSE(2,3,4) ждать не приходится?
- Плохо ли влияет адресация (масштабированный индекс плюс база плюс смещение)? Вместо этого я мог бы использовать
ADD r11, 8
. - А как насчет разворачивания цикла? Я читал, что развертывание плохо для архитектуры Sandy Bridge (Agner Fog http://www.agner.org/optimize/). Его следует предпочесть или избегать?
- (Правка) Могу ли я использовать регистры SSE для загрузки и хранения слов большими порциями из памяти и эффективного обмена словами с помощью регистров общего назначения и регистров SSE?
Я высоко ценю любые комментарии.