задержка для 'pcmpeqb' - память против регистра xmm

у меня есть эти 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
  ...
  ...

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


person ELHASKSERVERS    schedule 28.02.2020    source источник


Ответы (1)


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

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

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

Единственный вопрос был бы, если бы это не было внутри цикла.


Загрузка ALU с микрослиянием по-прежнему имеет только обычную задержку uop ALU от входа регистра до выхода регистра. Exec exec может выполнять загрузку так рано, как он хочет, потому что адрес никаких зависимостей. 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

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


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

    movdqu  xmm0, [rax]
    pcmpeqb xmm0, [rel some_constant]
person Peter Cordes    schedule 28.02.2020