задержка для 'pcmpeqb' - память против регистра xmm - PullRequest
0 голосов
/ 28 февраля 2020

у меня есть эти 2 варианта:

вариант 1:

loop:
...
     movdqu   xmm0, [rax]
     pcmpeqb  xmm0, [.zero_table]
...
...

align 16
.zero_table:
    DQ 0, 0

вариант 2:

pxor xmm1, xmm1
loop:
  ...
    movdqu   xmm0, [rax]
    pcmpeqb  xmm0, xmm1
  ...
  ...

, так как у нас есть все oop, и я думаю, что память Операнды имеют большую стоимость задержки, поэтому я задаю этот вопрос ... какой вариант лучше и имеет меньшую стоимость задержки?

1 Ответ

3 голосов
/ 28 февраля 2020

Второй вариант довольно очевиден: в l oop меньше мопов с неиспользованным доменом. Таким образом, вышедший из строя exe c может работать вперед и не нуждаться в таком количестве физических регистров или буферов загрузки (или что бы то ни было, точно сохраняющее эти результаты загрузки до тех пор, пока ALU uop их не прочитает). Вы почти всегда хотите поднять константы из циклов. Это стоит 1 дополнительного мопа и небольшого размера L1i / uop-cache дополнительной инструкции.

(Nehalem и более ранние Intel (P6- семейство) имеют киоски для чтения регистров, если вы прочитали слишком много «холодных» регистров в одной группе инструкций по выпуску, но это только 10-летние процессоры Intel, а не AMD и не более поздняя версия Intel.)

pcmpeqb xmm, [mem] - это 1 uop с плавким доменом (с этим режимом адресации) для ROB, но он принимает две записи RS (как отдельная загрузка, а затем pcmpeqb reg, reg). Конечно, постоянная загрузка не имеет входных зависимостей, поэтому может выполняться сразу, но очевидно стоит затрат на чтение и загрузку ресурсов кэша.

Единственный вопрос будет, если это не было внутри всех oop.


Микроплавкая нагрузка ALU + по-прежнему имеет только обычную задержку срабатывания ALU от своего регистрового входа до его регистрового выхода. Превышение порядка exe c может выполнить загрузку как угодно, потому что адрес не имеет зависимостей. https://uops.info/ содержит подробные данные по этому вопросу.

Но если rax (указатель) может быть не сразу готов, тогда да, задержка при использовании нагрузки становится частью критического пути. (Генерация адреса занимает время.)


Кстати, первый вариант плох; Ноль регистров XMM с xorps или pxor xmm0,xmm0, не загружая константу.

    xorps    xmm0, xmm0    ; as cheap as a NOP on Sandybridge-family, or one ALU uop on Zen
    pcmpeqb  xmm0, [rax]   ; requires alignment unless you can use vpcmpeqb

За пределами al oop Я думаю, вы могли бы рассмотреть возможность использования нулей в качестве операнда источника памяти, если вы были уверены, что интерфейс всегда был узким местом и что ваша константа очень редко будет пропускать кэш . Тогда вы могли бы уменьшить его до 2-х инструкций даже с невыровненным [rax]. Но это стоит затрат на кэш данных для чего-то, что вы могли сгенерировать с помощью 3-байтовой или 4-байтовой инструкции.


Но если у вас была какая-то другая константа, для которой требовалось более 1 или 2 инструкций создать на лету, я не могу придумать ни одной реальной причины, по которой было бы лучше сначала загрузить константу или разорвать регистр. Режимы относительного копирования и [register] могут оставаться микросинтегрированными в серверной части семейства Sandybridge. Конечно, без AVX операнд памяти для pcmpeqb должен быть выровнен, так что это может заставить вас работать, если вы хотите сэкономить пропускную способность внешнего интерфейса, сложив одну нагрузку в операнд источника памяти для ALU op.

    movdqu  xmm0, [rax]
    pcmpeqb xmm0, [rel some_constant]
...