x86_64 - Сборка - условия цикла и неисправность

Я не прошу о тесте.

(Если бы это было так, я бы сделал это сам.)


Мой вопрос:

Для удобства я стараюсь избегать режимов косвенной / индексной адресации.

В качестве замены я часто использую немедленную, абсолютную или регистровую адресацию.

Код:

; %esi has the array address. Say we iterate a doubleword (4bytes) array.
; %ecx is the array elements count
(0x98767) myloop:
    ... ;do whatever with %esi
    add $4, %esi
    dec %ecx
    jnz 0x98767;

Здесь у нас есть сериализованная комбинация (dec и jnz), которая предотвращает правильное выполнение вне очереди (зависимость).

Есть ли способ избежать этого / сломать деп? (Я не специалист по сборке).


person Kroma    schedule 02.08.2015    source источник
comment
Итак, позвольте мне сказать прямо: вы хотите, чтобы условный переход, который зависит от результата предыдущей инструкции, выполнялся вне очереди с этой инструкцией? Я считаю, что это невозможно по логике.   -  person davmac    schedule 02.08.2015
comment
Также обратите внимание, что dec не рекомендуется, потому что это вызывает частичную остановку обновления флагов.   -  person Jester    schedule 02.08.2015
comment
@Jester: Тогда я должен использовать сабвуфер?   -  person Kroma    schedule 02.08.2015
comment
@davmac: моя цель - не зависеть от предыдущей инструкции   -  person Kroma    schedule 02.08.2015
comment
@Kroma, ты хочешь сказать, что хочешь переупорядочить dec и add? В таком случае нельзя использовать jcxz? (Вы не можете сделать условный переход независимо от инструкции, которая создает условие).   -  person davmac    schedule 02.08.2015
comment
Вы можете использовать lea 4(%esi),%esi для добавления, это не влияет на флаги, поэтому вы можете вставить subl $1, %ecx выше. Как говорит @davmac, вы не можете избавиться от зависимости, если не используете инструкцию loop, что снова не рекомендуется.   -  person Jester    schedule 02.08.2015
comment
@Jester: :) спасибо за подсказку.   -  person Kroma    schedule 02.08.2015
comment
@davmac: да, я не чувствую себя обязанным использовать условные переходы, если есть лучшее решение   -  person Kroma    schedule 02.08.2015
comment
Также не забудьте развернуть цикл, если это возможно, чтобы амортизировать стоимость накладных расходов на цикл.   -  person Jester    schedule 02.08.2015
comment
@Jester: абсолютно, но длина переменная. Хороший совет. Необходимо позаботиться о длине строки кэша.   -  person Kroma    schedule 02.08.2015
comment
@davmac: Я бы не рекомендовал jcxz, если только это не позволит вам избежать инструкций test или cmp. В процессорах Intel это двухкомпонентная инструкция. (Меньше проблем, когда код находится в кэше uop, иначе это может замедлить декодирование, потому что с ним может справиться только сложный декодер.)   -  person Peter Cordes    schedule 03.08.2015
comment
@jester: dec в порядке, если он макрос-сливается со следующей ветвью (на процессорах Intel). Процессоры AMD также избегают срывов с частичным флагом, рассматривая отдельные биты флагов как независимые. (Тем не менее, я не тестировал AMD или корпус Intel, не связанный с макросами.)   -  person Peter Cordes    schedule 03.08.2015


Ответы (1)


При оптимизации для процессоров Intel всегда помещайте инструкцию установки флага прямо перед инструкцией условного перехода (если она одна из простых, перечисленных в таблице ниже), чтобы они могли объединиться в один муп в декодерах.

Это не намного хуже для старых процессоров, которые не поддерживают макрослияние. Установка флага раньше может сократить штраф за неверное предсказание ветвления на единицу для таких процессоров, но выполнение вне очереди означает, что перемещение dec на пару инструкций раньше не будет иметь реального значения. См. Также Избегайте остановки конвейера, вычисляя условное раннее. Чтобы действительно иметь значение, вы делаете такие вещи, как разворачивание цикла и / или ветвление на чем-то, что может быть вычислено более просто, в идеале без зависимости от медленного ввода, поэтому OoO exec может иметь ветвь, уже разрешенную во время работы над более старыми итерациями тело цикла. то есть счетчик циклов dep-chain может работать раньше основной работы.

У меня нет тестов, но я не думаю, что небольшой недостаток все более редких процессоров оправдывает упущение преимущества пропускной способности внешнего интерфейса (декодирование и выпуск) для процессоров, которые выполняют слияние. Общая пропускная способность uop часто может быть узким местом.

AMD Bulldozer / Piledriver / Steamroller может объединять test/cmp с любыми jcc, но только с test/cmp, а не с любыми другими инструкциями ALU. Так что однозначно ставлю сравнения с ветками. Для процессоров Intel по-прежнему полезно размещать другие вещи с ветвями, если они могут макросовкладывать семейство Sandybridge.

Из руководства по микроархитекту Агнера Фога, таблица 9.2 (для Sandybridge / Ivybridge):

First       | can pair with these  |  cannot pair with
instruction | (and the inverse)    |
---------------------------------------------
cmp         |jz, jc, jb, ja, jl, jg|   js, jp, jo
add, sub    |jz, jc, jb, ja, jl, jg|   js, jp, jo
adc, sbb    |none                  |
inc, dec    |jz, jl, jg            |   jc, jb, ja, js, jp, jo
test        | all                  |
and         | all                  |
or, xor, not, neg | none           |
shift, rotate     | none           |

Table 9.2. Instruction fusion

Таким образом, inc/dec может объединяться с jcc макросами, если условие зависит только от битов, измененных inc/dec.

(В противном случае они не сливаются с макросами, и вы получаете дополнительный uop, вставленный для слияния флагов (например, когда вы читаете eax после записи al). Или на более ранних процессорах, остановка частичных флагов.)

Core2 / Nehalem был более ограничен в возможностях макро-слияния (только для CMP / TEST с более ограниченными комбинациями JCC), а Core2 вообще не мог макрос-слияние в 64-битном режиме.

Прочтите также руководства Agner Fog по оптимизации asm и C, если вы еще этого не сделали. Они полны важных знаний.

person Peter Cordes    schedule 03.08.2015
comment
Большое спасибо Питеру, у меня уже были таблицы инструкций и оптимизация сборки от него. Я не прочитал последнее полностью (отсюда мое незнание), НО Я сделаю это сейчас. Спасибо, Питер :) - person Kroma; 03.08.2015
comment
@Kroma: Эта таблица взята из файла microarchitecture.pdf. Я забываю, упоминает ли он макрослияние в руководстве по оптимизации asm, но, вероятно, хотя бы упоминает об этом. - person Peter Cordes; 03.08.2015
comment
Вероятно, стоит упомянуть, что первая инструкция и вторая инструкция должны быть в одном и том же 16-байтовом сегменте декодирования, чтобы это работало (один и тот же адрес округлен до 16 байтов). Думаю, Агнер Фог где-то об этом упоминает. - person Noah; 14.01.2021
comment
@Noah: во-первых, группы декодирования не всегда выровнены. Во-вторых, семейство Sandybridge придерживается последней инструкции в группе, если она является кандидатом на слияние, если первая инструкция в следующей группе является ветвью. (Таким образом, он жертвует некоторой пропускной способностью устаревшего декодирования, возможно, для создания более компактных строк uop-cache и, возможно, для минимизации пространства ROB и других внутренних ресурсов на этот раз). Я думаю, что это обсуждалось где-то на SO, но ничего конкретного в голову не приходит. Тем не менее, вы можете найти что-нибудь с помощью Google. - person Peter Cordes; 14.01.2021