Пока я работал над своим быстрым циклом ADD (Ускорить цикл ADID ассемблера x64), я тестировал доступ к памяти с помощью инструкций SSE и AVX. Чтобы добавить, мне нужно прочитать два входа и произвести один вывод. Поэтому я написал манекенную процедуру, которая считывает два значения x64 в регистры и записывает их обратно в память без какой-либо операции. Это, конечно, бесполезно, я только делал это для бенчмаркинга.
Я использую развернутый цикл, который обрабатывает 64 байта за цикл. Он состоит из 8 блоков:
mov rax, QWORD PTR [rdx+r11*8-64]
mov r10, QWORD PTR [r8+r11*8-64]
mov QWORD PTR [rcx+r11*8-64], rax
Затем я обновил его до SSE2. Теперь я использую 4 блока следующим образом:
movdqa xmm0, XMMWORD PTR [rdx+r11*8-64]
movdqa xmm1, XMMWORD PTR [r8+r11*8-64]
movdqa XMMWORD PTR [rcx+r11*8-64], xmm0
И позже я использовал AVX (256 бит на регистр). У меня есть 2 блока:
vmovdqa ymm0, YMMWORD PTR [rdx+r11*8-64]
vmovdqa ymm1, YMMWORD PTR [r8+r11*8-64]
vmovdqa YMMWORD PTR [rcx+r11*8-64], ymm0
Пока, так не очень-очень-эффектно. Интересным является результат бенчмаркинга: когда я запускаю три разных подхода к 1k + 1k = 1k 64-битным словам (т.е. Два раза 8 kb ввода и один раз 8kb вывода), я получаю странные результаты. Каждый из следующих таймингов предназначен для обработки двухкратных 64 байтов ввода в 64 байта вывода.
- Метод регистрации x64 работает примерно в 15 циклах /64 байта.
- Метод SSE2 работает примерно в 8,5 циклах /64 байта.
- Метод AVX работает примерно в 9 циклах /64 байта.
Мой вопрос: почему метод AVX работает медленнее (хотя и не много), чем метод SSE2? Я ожидал, что это будет хотя бы на уровне. Использует ли использование регистров YMM столько дополнительного времени? Память была выровнена (вы получаете GPF в противном случае).
Есть ли у кого есть объяснение?