Включая правильный внутренний заголовок - PullRequest
2 голосов
/ 09 мая 2019

Я продолжаю читать мнения о том, какой заголовочный файл лучше включить для доступа к встроенным функциям Intel: x86intrin.h или immintrin.h.

Оба, похоже, достигают одинакового результата, но я уверен, что должны быть некоторые тонкие различия в отношении переносимости кода. Может быть, одно более распространенное или более полное, чем другое?

Я не смог найти объяснения ни по одному из них. Если кто-то знает, почему существуют 2 файла и какие у них различия, это будет приветствованный ответ SO.

Говоря о переносимости, для более старых компиляторов (таких как gcc другого встроенного заголовка (вероятно, emmintrin.h для поддержки SSE).

1 Ответ

3 голосов
/ 09 мая 2019

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


immintrin.h является переносимым для всех компиляторов и включает в себя все Intel SIMD встроенные и некоторые скалярные расширения, такие как BMI2 _pdep_u32. (Для AMD SSE4a и XOP (только семейство Bulldozer, исключено для Zen) вам также необходимо включить другой заголовок.)

Единственная причина, по которой я могу подумать о включении <emmintrin.h>, в частности, заключается в том, что вы используете MSVC и хотите оставить внутренние свойства неопределенными для расширений ISA, от которых вы не хотите зависеть.

Модель GCC, требующая от вас включения расширений, прежде чем вы сможете использовать встроенные функции для них, означает, что компилятор делает эту проверку за вас, поэтому вы можете просто #include <immintrin.h>, но все равно получите ошибку, если попытаетесь использовать _mm_shuffle_epi8 (pshufb) без -mssse3.

Не используйте компиляторы старше gcc4.4. Они устарели и, как правило, генерируют более медленный код, особенно для современных процессоров, которых не было, когда определялись их параметры настройки.


gcc / clang x86intrin.h против MSVC intrin.h полезны только в том случае, если вам нужны некоторые дополнительные не-SIMD встроенные функции, такие как _BitScanReverse() MSVC, которые не всегда переносимы между компиляторами. Такие вещи, как целочисленные функции поворота / битового сканирования, которые являются базовыми (в отличие от BMI1 lzcnt / tzcnt или BMI2 rorx), но трудно или невозможно выразить в C так, чтобы компиляторы распознали и превратили цикл обратно в одна инструкция.

Intel документирует некоторые из них как доступные в immintrin.h в их руководстве по встроенным функциям , но gcc / clang и MSVC фактически имеют их в своих x86intrin.h или intrin.h заголовках соответственно.

См. Получить количество циклов ЦП? для примера , используя #ifdef _MSC_VER, чтобы выбрать правильный заголовок , чтобы определить uint64_t __rdtsc(void) и __rdtscp().

...