В чем разница между vextracti128 и vextractf128?

vextracti128 и vextractf128 имеют одинаковые функции, параметры и возвращаемые значения. Вдобавок один - это набор инструкций AVX, а другой - AVX2. В чем разница?


person user2813757    schedule 25.09.2013    source источник
comment
Vs2012 c ++ имеет ошибку: при компиляции инструкции vextracti128 иногда происходит неправильная инверсия двух регистров. Скомпилировать инструкцию vextractf128 правильно. Vs2013 c ++ кажется правильным.   -  person user2813757    schedule 21.11.2013


Ответы (2)


vextracti128 и vextractf128 имеют не только одинаковые функции, параметры и возвращаемые значения. У них одинаковая длина инструкций. И у них одинаковая пропускная способность (согласно руководствам по оптимизации Agner Fog).

Что не совсем понятно, так это их значения задержки (производительность в жестких циклах с цепочками зависимостей). Задержка самих инструкций составляет 3 цикла. Но после прочтения раздела 2.1.3 («Механизм выполнения») Руководства по оптимизации Intel мы можем подозревать, что vextracti128 должен получить дополнительную 1 тактовую задержку при работе с данными с плавающей запятой, а vextractf128 должен получить дополнительную 1 тактовую задержку при работе с целочисленными данными. Измерения показывают, что это не так, и задержка всегда остается ровно 3 цикла (по крайней мере, для процессоров Haswell). И, насколько мне известно, это нигде не задокументировано в Руководстве по оптимизации.

Тем не менее, набор инструкций - это только интерфейс для процессора. Haswell - единственная реализация этого интерфейса, содержащая обе эти инструкции (на данный момент). Мы могли бы проигнорировать тот факт, что реализации этих инструкций (скорее всего) идентичны. И используйте эти инструкции по назначению - vextracti128 для целочисленных данных и vextractf128 для данных FP. (Если нам нужно только переупорядочить данные без выполнения каких-либо операций int / FP, очевидный выбор - vextractf128, поскольку он поддерживается несколькими более старыми процессорами). Также опыт показывает, что Intel иногда снижает производительность некоторых инструкций в процессорах следующих поколений, поэтому было бы разумно соблюдать схожесть этих инструкций, чтобы избежать возможного снижения скорости в будущем.

Поскольку руководство по оптимизации Intel не очень подробно описывает взаимосвязь между доменами int / FP для инструкций SIMD, я провел еще несколько измерений (на Haswell) и получил некоторые интересные результаты:


Инструкции по перемешиванию

Нет никакой дополнительной задержки для любых переходов между инструкциями SSE integer и shuffle. И нет никакой дополнительной задержки для любых переходов между SSE FP и инструкциями перемешивания. (Хотя я не проверял каждую инструкцию). Например, вы можете вставить такую ​​«явно целочисленную» инструкцию как pshufb между двумя инструкциями FP без дополнительной задержки. Вставка shufpd в середину целочисленного кода также не дает дополнительной задержки.

Поскольку vextracti128 и vextractf128 выполняются модулем тасования, у них также есть это свойство «без задержки».

Это может быть полезно для оптимизации смешанного кода int + FP. Если вам нужно переинтерпретировать данные FP как целые числа и в то же время перемешать регистр, просто убедитесь, что все инструкции FP стоят перед перемешиванием, а все целочисленные инструкции находятся после него.


Логические инструкции FP

andps и другие логические инструкции FP также имеют свойство игнорировать домены FP / int.

Если вы добавите целочисленную логическую инструкцию (например, pand) в код FP, вы получите дополнительную задержку в 2 цикла (один для перехода в домен int, а другой для возврата в FP). Таким образом, очевидным выбором для кода SIMD FP является andps. Тот же andps можно использовать в середине целочисленного кода без каких-либо задержек. Еще лучше использовать такие инструкции прямо между инструкциями int и FP. Интересно, что логические инструкции FP используют тот же порт номер 5, что и все инструкции перемешивания.


Зарегистрируйтесь, чтобы получить доступ

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

Этому фрагменту кода требуется всего 3 такта на итерацию (как того требует vaddps):

    vxorps ymm7, ymm7, ymm7
_benchloop:
    vaddps ymm0, ymm0, ymm7
    jmp _benchloop

Но для этого нужно 2 такта на итерацию (на 1 больше, чем нужно для vpaddd):

    vpxor ymm7, ymm7, ymm7
_benchloop:
    vpaddd ymm0, ymm0, ymm7
    jmp _benchloop

Единственная разница здесь - вычисления в целочисленной области, а не в FP-области. Чтобы получить 1 такт / итерацию, нам нужно добавить инструкцию:

    vpxor ymm7, ymm7, ymm7
_benchloop:
    vpand ymm6, ymm7, ymm7
    vpaddd ymm0, ymm0, ymm6
    jmp _benchloop

Это намекает на то, что (1) все значения, хранящиеся в регистрах SIMD, принадлежат домену FP, и (2) чтение из регистра SIMD увеличивает задержку целочисленной операции на единицу. (Разница между {ymm0, ymm6} и ymm7 здесь в том, что ymm7 хранится в некоторой временной памяти и работает как настоящий «регистр», тогда как ymm0 и ymm6 являются временными и представлены состоянием внутренних соединений ЦП, а не постоянным хранилищем, поэтому ymm0 и ymm6 не «читаются», а просто передаются между микрооперациями).

person Evgeny Kluev    schedule 06.09.2014
comment
В редизайне регистрового файла Sandybridge были удалены остановки порта чтения ROB. Этот совет сохранять ценности в сети пересылки уже устарел. Цикл может выполнять только 1 итерацию за 2 цикла, потому что взятые ветви имеют пропускную способность, равную одной итерации за 2 цикла. (Я тестировал SnB с Linux perf для подсчета insns / цикл. Agner Fog указывает пропускную способность получателя jmp near как 1-2c для Haswell, по сравнению с 2c для SnB, так что, возможно, вы сможете получить один цикл на итерацию на HSW.) Но я думаю. если любой из циклов равен 1c, оба не-FP-цикла равны. В противном случае хороший ответ. - person Peter Cordes; 17.07.2015
comment
Обновление моего предыдущего комментария: я почти уверен, что SnB может запускать крошечные циклы по одному за такт (как и большинство процессоров), несмотря на то, что таблица Агнера Фога говорит о показателях пропускной способности. Вероятно, пропускная способность один на 2 такта применима только к ветвям без цикла. - person Peter Cordes; 09.04.2017
comment
Обновление моего предыдущего комментария: я почти уверен, что SnB может запускать крошечные циклы по одному за такт (как и большинство процессоров), несмотря на то, что таблица Агнера Фога говорит о показателях пропускной способности скачков. Вероятно, пропускная способность один на 2 такта применима только к ветвям без цикла. См. Также этот вопрос и ответ о циклах с нечетным числом мопов, выдающих менее 4 мопов за такт из LSD (буфера цикла). Выполнение, конечно, может быть ограничено деталями тела цикла, как в этом случае. - person Peter Cordes; 09.04.2017
comment
Я пытался воспроизвести ваши результаты на Haswell. VPAND + VPADDD постоянно работает со скоростью 1 метр / такт. Версия just-VPADDD иногда делает, а иногда нет; если вам повезет, он работает так же быстро, как и версия с двумя инструкциями. Но в других случаях он работает с частотой 1 литр за ~ 1,5 цикла или 1 за ~ 2 цикла. Других закономерностей я не видел. (У меня нет легкого доступа к Haswell со счетчиками производительности, поэтому я изменил цикл, чтобы использовать dec ecx/jnz (который микроплавлен в один муп, точно так же, как jmp. Время от времени я пытался запустить 2 миллиарда итераций с повторными испытаниями с тех пор, как Я на шумной ВМ.) - person Peter Cordes; 09.04.2017
comment
Инициализация ymm7 чем-то другим, кроме xor-zeroing, тоже ничего не меняет. (Я пробовал vcmpeqw same,same получить все единицы, так как xor-zeroing является особенным). Это действительно озадачивает, так как вашему vpand все равно нужно читать ymm7 из файла физического реестра, а не из сети пересылки. Однако это не часть цепочки зависимостей, переносимой циклом, что является очевидной разницей. Изменение VPADDD на логическое значение не имеет значения. - person Peter Cordes; 09.04.2017
comment
Кстати, я не могу воспроизвести это на Skylake. Множественные прогоны perf stat в исходном цикле (с jmp) и в моей версии с 2 миллиардами итераций показывают, что он выполняется каждый раз ровно с 1 итерацией за такт с точностью до 0,01%. нет такой проблемы. - person Peter Cordes; 09.04.2017

Хороший вопрос - похоже, что инструкция AVX vextractf128 предназначена для любого типа вектора (int, float, double), а инструкция AVX2 vextracti128 предназначена только для вектора int. Я рекомендую использовать последний, когда у вас есть AVX2 и целочисленные векторы, если он обеспечивает лучшую производительность в некоторых случаях, в противном случае используйте первое.

person Paul R    schedule 25.09.2013
comment
Спасибо за ваш ответ. Я не нашел данных о задержке и пропускной способности vextracti128. Теперь я предполагаю, что они имеют одинаковую функциональность, поэтому я использовал vextractf128, потому что он совместим со старым процессором. vextracti128 доступен только на процессорах Haswell и новее. В последней версии Intel (июль 2013 г.) 64-ia-32-architecture-optimisation-manual.pdf нет данных о задержке и пропускной способности vextracti128. Как только обработка целочисленных данных vextracti128 даст дополнительное преимущество в производительности, я буду использовать ее, но не сейчас. Спасибо. - person user2813757; 01.10.2013