В чем разница между __popcnt() и _mm_popcnt_u32()?

MS Visual C++ поддерживает 2 варианта инструкции popcnt на процессорах с SSE4.2:

  1. __popcnt()
  2. _mm_popcnt_u32()

Единственное отличие, которое я обнаружил, заключалось в том, что документы для __popcnt() помечены как «Специфические для Microsoft», а _mm_popcnt_u32() кажется внутренним именем команды (не специфичным для MS).

Это единственная разница, где MS __popcnt() просто вызывает HW _mm_popcnt_u32()?


person Adi Shavit    schedule 20.06.2012    source источник


Ответы (1)


Это два разных встроенных имени для одной и той же машинной инструкции, благодаря Intel и AMD. Эта инструкция одинакова на всех процессорах, которые ее поддерживают, и разные встроенные функции также не имеют различий в C или C++.


Встроенные функции __popcnt*() предназначены для инструкций AMD Advanced Bit Manipulation (ABM). См. http://blogs.amd.com/developer/2007/09/26/barcelona-processor-feature-advanced-bit-manipulation-abm/

Встроенные функции _mm_popcnt_u*() предназначены для реализации Intel, которые сами по себе не являются частью SSE4.2, но были реализованы примерно в то же время. См. http://en.wikipedia.org/wiki/SSE4#POPCNT_and_LZCNT.

Согласно https://www.chessprogramming.org/Population_Count, обе реализации бинарно совместимы, несмотря их различных внутренних имен.

В руководстве по архитектуре говорится, что:

Прежде чем приложение попытается использовать инструкцию POPCNT, оно должно убедиться, что процессор поддерживает SSE4.2 (если CPUID.01H:ECX.SSE4_2[бит 20] = 1) и POPCNT (если CPUID.01H:ECX.POPCNT[бит 23 ] = 1).

В Руководстве программиста по архитектуре AMD64, том 3: Общее назначение и системные инструкции говорится:

На поддержку инструкции POPCNT указывает бит 23 ECX (POPCNT), возвращенный функцией CPUID 0000_0001h. Программное обеспечение ДОЛЖНО проверять бит CPUID один раз при инициализации программы или библиотеки перед использованием инструкции POPCNT, иначе может возникнуть непоследовательное поведение.

Я не вижу причин, по которым popcnt требовал бы наличия SSE4.2, поэтому я думаю, что проверки 23-го бита ECX достаточно, чтобы определить присутствие popcnt.


AMD Barcelona, ​​первый процессор AMD с popcnt, не полностью реализовал SSE4, поэтому возможно, что в руководстве по архитектуре Intel предлагается метод определения присутствия, который будет работать на процессорах Intel и не будет работать даже на квалифицированных процессорах AMD.

Текущая документация Intel для popcnt в их справочном руководстве по набору инструкций, том 2 говорит только #UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0, поэтому антиконкурентное предложение, которое привело бы к тому, что программное обеспечение не использует преимущества popcnt на некоторых процессорах AMD без SSE4.2, больше не используется.

person mattst88    schedule 21.06.2012
comment
Так есть ли разница в том, когда использовать каждый из них в программном обеспечении? Следует ли проверять другой бит cpuid? Если я хочу написать независимое от Intel/AMD cwhat, которое по-прежнему использует команду, что мне делать? - person Adi Shavit; 21.06.2012
comment
Не похоже, что они разные или несовместимые. Смотрите мой отредактированный ответ выше. - person mattst88; 21.06.2012
comment
Запись insn ref Intel для popcnt в настоящее время просто говорит #UD If CPUID.01H:ECX.POPCNT [Bit 23] = 0, поэтому бесполезный / антиконкурентный предложения проверить SSE4.2 там нет. - person Peter Cordes; 11.08.2016