Arquivos de cabeçalho para intrinsics SIM86 x86

131

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.

fredoverflow
fonte

Respostas:

174

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.

fredoverflow
fonte
62
Ou você pode exatamente o #include <x86intrin.h>que extrai tudo o que você precisa.
Paul R
2
O zmmintrin.h possui os intrínsecos do AVX-512.
Onitake 29/10
3
Por que p, t, s e n para SSE3 / SSSE3 / SSE4.1 e 4.2? O que esses personagens representam?
precisa saber é
5
@ LưuVĩnhPhúc SSE3 = Prescott novas instruções, SSSE3 = Tejas novas instruções. Acho SSE4.2 e AES referem-se à família de processadores que foram introduzidos na (Nehalem e Westmere)
Tirou McGowen
14
Não inclua <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..)
Peter Cordes
76

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 /

Gunther Piez
fonte
Eu não tinha certeza, se as versões mais recentes pode ... De qualquer forma, desde que gcc, icc e clang tê-lo, ok para usar Eu acho :-)
Gunther Piez
5
MSVC não tem <x86intrin.h>, mas <intrin.h>alcança um efeito semelhante. Você ainda precisa de compilação condicional, é claro. :-(
Cody Gray
Todos os principais compiladores x86 possuem #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 ).
22818 Peter Cordes
IIRC, existem alguns intrínsecos não SIMD que documenta a Intel como estando em immintrin.h, mas que gcc, clang, e / ou MSVC só tem em x86intrin.h/ intrin.hmas não em immintrin.h.
22618 Peter Cordes
56

O nome do cabeçalho depende do seu compilador e arquitetura de destino.

  • Para Microsoft C ++ (visando x86, x86-64 ou ARM) e o Intel C / C ++ Compiler para Windows, use intrin.h
  • Para segmentação gcc / clang / icc x86 / x86-64, use x86intrin.h
  • Para gcc / clang / armcc segmentando ARM com NEON, use arm_neon.h
  • Para ARM de segmentação gcc / clang / armcc com WMMX, use mmintrin.h
  • Para segmentação do PowerPC com gcc / clang / xlcc com VMX (também conhecido como Altivec) e / ou VSX, use altivec.h
  • Para o PowerPC com SPE de segmentação por gcc / clang, use spe.h

Você 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
Marat Dukhan
fonte
Aqui estão mais algumas opções para adicionar à sua lista: No UltraSPARC + VIS com gcc, use visintrin.h; se você tiver o VSDK da Sun, o vis.h oferece um conjunto diferente de intrínsecas. A documentação pode ser encontrada aqui: GCC VIS builtins , guia do usuário do Sun VIS .
Onitake 29/10/14
44

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).

RubenLaguna
fonte
1
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 .
6266 Peter Cordes
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.
Thom Wiggers
12

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.

Brett Hale
fonte