Quais arquivos de cabeçalho fornecem as intrínsecas para as diferentes extensões do conjunto de instruções x86 SIMD (MMX, SSE, AVX, ...)? Parece impossível encontrar essa lista online. Corrija-me se eu estiver errado.
Quais arquivos de cabeçalho fornecem as intrínsecas para as diferentes extensões do conjunto de instruções x86 SIMD (MMX, SSE, AVX, ...)? Parece impossível encontrar essa lista online. Corrija-me se eu estiver errado.
Respostas:
Hoje em dia você normalmente deve apenas incluir <immintrin.h>. Inclui tudo.
O GCC e o clang impedirão você de usar intrínsecos para instruções que você não ativou no momento da compilação (por exemplo, com -march=nativeou -mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1ou o que for.)
O MSVC e o ICC permitem usar intrínsecos sem ativar nada no tempo de compilação, mas você ainda deve habilitar o AVX antes de usar os intrínsecos do AVX.
Historicamente (antes de obter immintrin.htudo), era necessário incluir manualmente um cabeçalho para o mais alto nível de intrínsecas que você desejava.
Isso ainda pode ser útil com o MSVC e o ICC para impedir o uso de conjuntos de instruções que você não deseja exigir.
<mmintrin.h> MMX
<xmmintrin.h> SSE
<emmintrin.h> SSE2
<pmmintrin.h> SSE3
<tmmintrin.h> SSSE3
<smmintrin.h> SSE4.1
<nmmintrin.h> SSE4.2
<ammintrin.h> SSE4A
<wmmintrin.h> AES
<immintrin.h> AVX, AVX2, FMA
Incluindo um desses puxões em todos os anteriores (exceto o SSE4A somente AMD: immintrin.hnão puxa isso)
Alguns compiladores também têm <zmmintrin.h>para o AVX512.
<zmmintrin.h>diretamente; O GCC nem o fornece. Basta usar<immintrin.h> ou o ainda mais completo <x86intrin.h>. Essa resposta é basicamente obsoleta, a menos que você intencionalmente evite incluir intrínsecos para versões mais recentes do SSE, porque seu compilador não reclama quando você usa uma instrução SSE4.1 durante a compilação do SSE2. (gcc / clang que reclamar, então você deve apenas usar immintrin.h para eles IDK sobre os outros..)
No GCC / clang, se você usar apenas
#include <x86intrin.h>
incluirá todos os cabeçalhos SSE / AVX que são ativados de acordo com as opções do compilador, como -march=haswellapenas -march=native. Além disso, algumas instruções específicas do x86, como bswapou rorse tornam disponíveis como intrínsecas.
O equivalente MSVC deste cabeçalho <intrin.h>
Se você quiser apenas o SIMD portátil, use #include <immintrin.h>
MSVC, ICC e gcc / clang (e outros compiladores como a Sun, eu acho) suportam esse cabeçalho para as intrínsecas SIMD documentadas pela única ferramenta de busca / pesquisa intrínseca da Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide /
<x86intrin.h>, mas <intrin.h>alcança um efeito semelhante. Você ainda precisa de compilação condicional, é claro. :-(
#include <immintrin.h>. Use isso para intrínsecas do SIMD. Você só precisa do tamanho ainda maior (e um pouco mais lento para o compilador) x86intrin.hou intrin.hse precisar de itens como intrínsecos de rotação / varredura de bits inteiros (embora a Intel documente alguns deles como disponíveis no immintrin.h guia de intrínsecos ).
x86intrin.h/ intrin.hmas não em immintrin.h.
O nome do cabeçalho depende do seu compilador e arquitetura de destino.
intrin.hx86intrin.harm_neon.hmmintrin.haltivec.hspe.hVocê pode lidar com todos esses casos com diretivas de pré-processamento condicional:
#if defined(_MSC_VER)
/* Microsoft C/C++-compatible compiler */
#include <intrin.h>
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
/* GCC-compatible compiler, targeting x86/x86-64 */
#include <x86intrin.h>
#elif defined(__GNUC__) && defined(__ARM_NEON__)
/* GCC-compatible compiler, targeting ARM with NEON */
#include <arm_neon.h>
#elif defined(__GNUC__) && defined(__IWMMXT__)
/* GCC-compatible compiler, targeting ARM with WMMX */
#include <mmintrin.h>
#elif (defined(__GNUC__) || defined(__xlC__)) && (defined(__VEC__) || defined(__ALTIVEC__))
/* XLC or GCC-compatible compiler, targeting PowerPC with VMX/VSX */
#include <altivec.h>
#elif defined(__GNUC__) && defined(__SPE__)
/* GCC-compatible compiler, targeting PowerPC with SPE */
#include <spe.h>
#endif
A partir desta página
+----------------+------------------------------------------------------------------------------------------+
| Header | Purpose |
+----------------+------------------------------------------------------------------------------------------+
| x86intrin.h | Everything, including non-vector x86 instructions like _rdtsc(). |
| mmintrin.h | MMX (Pentium MMX!) |
| mm3dnow.h | 3dnow! (K6-2) (deprecated) |
| xmmintrin.h | SSE + MMX (Pentium 3, Athlon XP) |
| emmintrin.h | SSE2 + SSE + MMX (Pentium 4, Athlon 64) |
| pmmintrin.h | SSE3 + SSE2 + SSE + MMX (Pentium 4 Prescott, Athlon 64 San Diego) |
| tmmintrin.h | SSSE3 + SSE3 + SSE2 + SSE + MMX (Core 2, Bulldozer) |
| popcntintrin.h | POPCNT (Nehalem (Core i7), Phenom) |
| ammintrin.h | SSE4A + SSE3 + SSE2 + SSE + MMX (AMD-only, starting with Phenom) |
| smmintrin.h | SSE4_1 + SSSE3 + SSE3 + SSE2 + SSE + MMX (Penryn, Bulldozer) |
| nmmintrin.h | SSE4_2 + SSE4_1 + SSSE3 + SSE3 + SSE2 + SSE + MMX (Nehalem (aka Core i7), Bulldozer) |
| wmmintrin.h | AES (Core i7 Westmere, Bulldozer) |
| immintrin.h | AVX, AVX2, AVX512, all SSE+MMX (except SSE4A and XOP), popcnt, BMI/BMI2, FMA |
+----------------+------------------------------------------------------------------------------------------+
Portanto, em geral, você pode incluir apenas immintrin.hpara obter todas as extensões Intel, ou x86intrin.hse quiser tudo, incluindo _bit_scan_forwarde _rdtsc, além de todas as intrínsecas de vetores, incluindo apenas AMD. Se você for contra, incluindo mais do que realmente precisa, poderá escolher a inclusão correta olhando para a mesa.
x86intrin.hé a maneira recomendada de obter intrínsecas para o AMD XOP (somente Bulldozer, nem mesmo os futuros processadores AMD) , em vez de ter seu próprio cabeçalho.
Alguns compiladores ainda gerarão mensagens de erro se você usar elementos intrínsecos para conjuntos de instruções que você não ativou (por exemplo, _mm_fmadd_pssem ativar o fma, mesmo se você incluir immintrin.he ativar o AVX2).
smmintrin(SSE4.1) é Penryn (45 nm Core2), não Nehalem ("i7"). Podemos parar de usar "i7" como um nome de arquitetura? Não faz sentido agora que a Intel continuou usando-o para a família SnB .
immintrin.hparece não incluir _popcnt32e _popcnt64(não deve ser confundido com os que estão dentro popcntintrin.h!) intrínsecas no GCC 9.1.0. Então parece que x86intrin.hainda serve a um propósito.
Como muitas das respostas e comentários declararam, <x86intrin.h>é o cabeçalho abrangente para intrínsecas do SIMD x86 [-64]. Ele também fornece instruções de suporte intrínsecas para outras extensões ISA. gcc,, clange icctodos decidiram isso. Eu precisava pesquisar algumas versões que suportam o cabeçalho e pensei que poderia ser útil listar algumas descobertas ...
gcc : o suporte para o x86intrin.hprimeiro aparece em gcc-4.5.0. A gcc-4série de lançamentos não está mais sendo mantida, enquanto gcc-6.xa atual é a série estável. gcc-5também introduziu a __has_includeextensão presente em todas as clang-3.xversões. gcc-7está em pré-lançamento (teste de regressão, etc.) e segue o esquema de versão atual, será lançado como gcc-7.1.0.
clang : x86intrin.hparece ter sido suportado para todos os clang-3.xlançamentos. A última versão estável é clang (LLVM) 3.9.1. O ramo de desenvolvimento é clang (LLVM) 5.0.0. Não está claro o que aconteceu com a 4.xsérie.
Clang da Apple : irritantemente, o versionamento da Apple não corresponde ao dos LLVMprojetos. Dito isto, a versão atual:, clang-800.0.42.1é baseada em LLVM 3.9.0. A primeira LLVM 3.0versão baseada parece estar de Apple clang 2.1volta Xcode 4.1. LLVM 3.1aparece pela primeira vez com Apple clang 3.1(uma coincidência numérica) em Xcode 4.3.3.
A Apple também define __apple_build_version__, por exemplo 8000042,. Esse parece ser o esquema de versão mais estável e estritamente ascendente disponível. Se você não deseja oferecer suporte a compiladores herdados, torne um desses valores um requisito mínimo.
Qualquer versão recente clang, incluindo as versões da Apple, não deve ter nenhum problema x86intrin.h. Obviamente, junto com gcc-5, você sempre pode usar o seguinte:
#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif
Um truque em que você realmente não pode confiar é usar as __GNUC__versões clang. O controle de versão é, por razões históricas, bloqueado 4.2.1. Uma versão que precede o x86intrin.hcabeçalho. Ocasionalmente, é útil para, digamos, extensões GNU C simples que permaneceram compatíveis com versões anteriores.
icc : pelo que sei, o x86intrin.hcabeçalho é suportado desde pelo menos Intel C ++ 16.0. O teste versão pode por executada com: #if (__INTEL_COMPILER >= 1600). Esta versão (e possivelmente versões anteriores) também fornece suporte para a __has_includeextensão.
MSVC : Parece que MSVC++ 12.0 (Visual Studio 2013)é a primeira versão a fornecer o intrin.hcabeçalho - não x86intrin.h ... isso sugere: #if (_MSC_VER >= 1800)como um teste de versão. Obviamente, se você estiver tentando escrever um código portátil em todos esses diferentes compiladores, o nome do cabeçalho nessa plataforma será o menor dos seus problemas.
#include <x86intrin.h>que extrai tudo o que você precisa.