Пока я работал над своим быстрым циклом ADD (Ускорение цикла ADD на ассемблере 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 КБ на входе и один раз на 8 КБ на выходе), я получаю странные результаты. Каждый из следующих моментов времени предназначен для обработки двукратного ввода 64 байта в 64 байта вывода.
- Метод регистра x64 работает примерно с 15 циклами / 64 байта.
- Метод SSE2 работает примерно с 8,5 циклами / 64 байта.
- Метод AVX работает примерно с 9 циклами / 64 байта.
У меня вопрос: почему метод AVX работает медленнее (хотя и не намного), чем метод SSE2? Я ожидал, что будет как минимум на уровне. Стоит ли использовать регистры YMM так много дополнительного времени? Память была выровнена (иначе вы получите GPF).
У кого-нибудь есть объяснение этому?