Почему нарушение «выходной зависимости» LZCNT имеет значение?

В то время, когда я сравнивал что-то, я измерил гораздо более низкую пропускную способность, чем я вычислил, и я сужусь до инструкции LZCNT (это также происходит с TZCNT), как показано в следующих тестах:

xor ecx, ecx _benchloop: lzcnt eax, edx add ecx, 1 jnz _benchloop 

А также:

  xor ecx, ecx _benchloop: xor eax, eax ; this shouldn't help, but it does lzcnt eax, edx add ecx, 1 jnz _benchloop 

Вторая версия намного быстрее. Этого не должно быть. Нет причин, по которым LZCNT должен иметь входную зависимость от своего вывода. В отличие от BSR / BSF, инструкции xZCNT всегда перезаписывают свой вывод.

Я запускаю это на 4770K, поэтому LZCNT и TZCNT не выполняются как BSR / BSF.

Что тут происходит?

Это просто ограничение в микро-архитектуре вашего процессора Intel Haswell и нескольких предыдущих 1 CPU. Он был исправлен для tzcnt и lzcnt как и для Skylake, но проблема остается для popcnt .

На этих микроструктурах операнд назначения для tzcnt , lzcnt и popcnt рассматривается как входная зависимость, хотя семантически это не так. Теперь я сомневаюсь, что это действительно «ошибка»: если бы это был просто надзор, я ожидал, что это будет исправлено в одной из нескольких новых микро-архитектур, выпущенных с момента ее появления.

Скорее всего, это компромисс дизайна, основанный на одном или обоих из следующих двух факторов:

  • Аппаратное обеспечение для popcnt , lzcnt и tzcnt , скорее всего, используется совместно с существующими bsf и bsr . Теперь bsf и bsr действительно зависели от предыдущего значения назначения на практике 2 для особого случая ввода всех бит-ноль, поскольку в этом случае чипы Intel оставили цель немодифицированной. Поэтому вполне возможно, что простейшая конструкция комбинированного оборудования привела к тому, что другие аналогичные инструкции выполнялись в одном и том же подразделении, наследующем одну и ту же зависимость.

  • Подавляющее большинство инструкций ALU из двух операндов x86 зависят от операнда-адресата, поскольку он также используется как источник. Три затронутые инструкции несколько уникальны тем, что они являются унарными операторами, но в отличие от существующих унарных операторов, таких как not и neg которые имеют один операнд, используемый в качестве источника и адресата, у них есть разные операнды источника и адресата, что делает их поверхностно похожими на большинство 2- ввод инструкций. Возможно, схема переименования / планировщика просто не отличает особый случай этих унарных с двумя регистрами-операндами по сравнению с подавляющим большинством простых разделенных исходных / целевых инструкций с двумя входами, которые не имеют этой зависимости.

Фактически, для случая popcnt Intel выпустила различные ошибки, охватывающие проблему ложной зависимости, такую ​​как HSD146 для Haswell Desktop и SKL029 для Skylake , которая гласит:

Инструкция POPCNT может потребовать больше времени, чем ожидалось

Проблема Выполнение команды POPCNT с 32 или 64-битным операндом может быть отложено до тех пор, пока не будут выполнены предыдущие независимые инструкции.

Программное обеспечение Implication с использованием инструкции POPCNT может иметь более низкую производительность, чем ожидалось.

Обход проблемы Не определено

Я всегда считал этот необычный случай необычным, так как он не идентифицирует какой-либо функциональный дефект или несоответствие спецификации, которое имеет место, по существу, для всех других ошибок. Intel действительно не документирует конкретную модель производительности для механизма выполнения OoO, и на протяжении многих лет появилось и исчезло множество других «gotchas» производительности, многие из которых имеют гораздо больший эффект, что это очень незначительная проблема, t задокументировать в ошибках. Тем не менее, это, возможно, дает некоторые доказательства того, что это можно считать ошибкой. Как ни странно, erratum никогда не расширялся, чтобы включить tzcnt или lzcnt которые имели такую ​​же проблему, когда они были введены.


1 Ну tzcnt и lzcnt появились только в Haswell, но проблема существует и для popcnt которая была представлена ​​в Nehalem, но проблема с ложной зависимостью, возможно, существует только для Sandy Bridge или позже.

2 На практике , хотя это не документировано в документах ISA, поскольку результат для ввода всех нhive не определен в руководствах Intel. Тем не менее, большинство или все чипы Intel реализовали поведение, так как оставляя регистр адресата неизменным в этом случае.

Вдоль линий того, что предложил @BrettHale, возможно (если нечетно), что вы попадаете в стойку с частичными флагами с коротким флагом. Состояние флага следует теоретически просто переименовать, потому что следующее добавление обновляет все флаги, но если это не по какой-то причине, то оно вводит зависимую от цикла зависимость, а вставка xor нарушит эту зависимость.

Трудно узнать наверняка, если это то, что происходит, но он выглядит случайным взглядом, чтобы быть наиболее вероятным объяснением; вы можете проверить гипотезу, заменив xor на test (который также нарушает зависимость флагов, но не влияет на зависимости регистра).

  • Установите и запустите 32-разрядную версию на 64-битной машине
  • Заказ локального распределения переменных в стеке
  • Почему x86 маленький endian?
  • Режимы адресации на языке сборки (IA-32 NASM)
  • Использование базового указателя в C ++ inline asm
  • Проблемы с ADC / SBB и INC / DEC в узких петлях на некоторых процессорах
  • Изменение целевых настроек процессора в Visual Studio 2010 Express
  • Почему назначение целых чисел на естественно выровненной переменной атома на x86?
  • Ошибка сегментации сборки после выполнения системного вызова, в конце моего кода
  • 8086 на DOSBox: ошибка с инструкцией idiv?
  • Как вы используете gcc для генерации кода сборки в синтаксисе Intel?
  • Interesting Posts

    Ошибка ASP 0177: 8007007e Ошибка сервера.CreateObject для COM-библиотеки DLL

    Как преобразовать длину строки в пиксельный блок?

    libjpeg-turbo для Android

    Что означает «Включить Windows для определения приоритетов внешних манифестаций»?

    Как изменить цвет фона ActionBar ActionBarActivity с помощью XML?

    Как создать загрузочную ОС Windows с ОС Mac OS X

    Что такое YCbCr444?

    Почему приведение int к недопустимому значению enums НЕ выбрасывает исключение?

    Получить значение для элемента списка по индексу

    Есть ли способ получить список общедоступных сокращений клавиатуры в настоящее время?

    Разделение PDF в PDF-файлы различных размеров

    Почему временные метки меняются при копировании или перемещении файлов в Windows?

    Почему «использование пространства имен X» не допускается внутри уровня classа / структуры?

    Как заполнить таблицу MySQL множеством случайных чисел?

    Отправка электронной почты в .NET через Gmail

    Давайте будем гением компьютера.