[x86] x86 SIMD 내장 함수의 헤더 파일

어떤 x86 SIMD 명령어 세트 확장 (MMX, SSE, AVX, …)에 내장 함수를 제공하는 헤더 파일은 무엇입니까? 온라인에서 그러한 목록을 찾는 것은 불가능합니다. 틀 렸으면 말해줘.



답변

요즘에는 일반적으로 포함해야합니다 <immintrin.h>. 모든 것을 포함합니다.

GCC와 그 소리는 지침이 컴파일시에 설정하지 않은 내장 함수를 사용을 중지합니다 (예 :와 -march=native-mavx2 -mbmi2 -mpopcnt -mfma -mcx16 -mtune=znver1또는 무엇이든.)

MSVC와 ICC를 사용하면 컴파일 타임에 아무 것도 활성화하지 않고 내장 함수를 사용할 수 있지만 AVX 내장 함수를 사용하기 전에 AVX를 활성화 해야합니다 .


역사적으로 ( immintrin.h모든 것을 가져 오기 전에 ) 원하는 최고 수준의 내장 함수에 대한 헤더를 수동으로 포함해야했습니다.

이것은 MSVC 및 ICC에서 여전히 원하지 않는 명령어 세트를 사용하지 못하게하는 데 유용 할 수 있습니다.

<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

이전의 모든 것들에 이러한 immintrin.h풀 중 하나를 포함 (AMD 전용 SSE4A를 제외하고 는 🙂

일부 컴파일러에는 <zmmintrin.h>AVX512 도 있습니다 .


답변

GCC / clang에서

#include <x86intrin.h>

여기에는 컴파일러 스위치에 따라 -march=haswell또는 처럼 활성화 된 모든 SSE / AVX 헤더가 포함됩니다 -march=native. 또한 일부 x86 특정 명령어 는 내장 함수 와 같 bswap거나 ror내장 함수로 제공됩니다.


이 헤더에 해당하는 MSVC <intrin.h>


휴대용 SIMD 만 원한다면 #include <immintrin.h>

MSVC, ICC 및 gcc / clang (및 Sun과 같은 다른 컴파일러)은 모두 Intel의 유일한 내장 검색기 / 검색 도구에 의해 문서화 된 SIMD 내장 함수에 대해이 헤더를 지원합니다. https://software.intel.com/sites/landingpage/IntrinsicsGuide /


답변

헤더 이름은 컴파일러와 대상 아키텍처에 따라 다릅니다.

  • Windows 용 Microsoft C ++ (타겟팅 x86, x86-64 또는 ARM) 및 Intel C / C ++ 컴파일러 intrin.h
  • x86 / x86-64를 타겟팅하는 gcc / clang / icc의 경우 x86intrin.h
  • NEON을 사용하여 ARM을 대상으로하는 gcc / clang / armcc의 경우 arm_neon.h
  • WMMX를 사용하여 ARM을 대상으로하는 gcc / clang / armcc의 경우 mmintrin.h
  • VMX (일명 Altivec) 및 / 또는 VSX를 사용하는 PowerPC를 대상으로하는 gcc / clang / xlcc의 경우 altivec.h
  • SPE를 사용하는 PowerPC를 대상으로하는 gcc / clang의 경우 spe.h

조건부 전처리 지시문을 사용하여 이러한 모든 경우를 처리 할 수 ​​있습니다.

#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


답변

페이지에서

+----------------+------------------------------------------------------------------------------------------+
|     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             |
+----------------+------------------------------------------------------------------------------------------+

그래서 일반적으로 당신 만 포함 할 수 있습니다 immintrin.h모든 인텔 확장을 얻기 위해, 또는 x86intrin.h당신은 모든 것을 포함하려는 경우 _bit_scan_forward_rdtsc,뿐만 아니라 모든 벡터 내장 함수를 AMD-유일한 사람을 포함한다. 실제로 필요한 것 이상을 포함하지 않으면 테이블을보고 올바른 포함을 선택할 수 있습니다.

x86intrin.h는 자체 헤더를 사용하지 않고 AMD XOP (Bulldozer 전용, 향후 AMD CPU는 아님)에 대한 내장 기능을 얻는 권장 방법 입니다.

활성화하지 않은 명령어 세트에 내장 함수를 사용하는 경우 일부 컴파일러는 여전히 오류 메시지를 생성합니다 (예 : AVX2 _mm_fmadd_ps를 포함 immintrin.h하고 활성화 하더라도 fma를 활성화하지 않음 ).


답변

답변 및 의견의 대부분이 언급했듯이 <x86intrin.h>이다 86 [-64] SIMD의 내장 함수에 대한 포괄적 인 헤더. 또한 다른 ISA 확장에 대한 지침을 지원하는 내장 함수도 제공합니다. , 그리고 이것 에 모두 정했습니다. 헤더를 지원하는 버전을 파헤쳐 야했고 결과를 나열하는 것이 도움이 될 것이라고 생각했습니다 …gccclangicc

  • gcc :에 대한 지원이에 x86intrin.h나타납니다 gcc-4.5.0. gcc-4릴리즈 시리즈는 더 이상 동안 유지되고 있지 gcc-6.x는 IS 현재 안정적인 릴리스 시리즈. gcc-5또한 __has_include모든 clang-3.x릴리스에 존재 하는 확장 을 도입했습니다 . gcc-7시험판 (회귀 테스트 등)에 있으며 현재 버전 관리 체계에 따라로 출시됩니다 gcc-7.1.0.

  • clang : x86intrin.h모든 clang-3.x릴리스 에서 지원되는 것으로 보입니다 . 최신 안정 릴리스는 clang (LLVM) 3.9.1입니다. 개발 지점은 clang (LLVM) 5.0.0입니다. 4.x시리즈에 무슨 일이 있었는지 명확하지 않습니다 .

  • Apple clang : 성가신 Apple 버전은 LLVM프로젝트 의 버전과 일치하지 않습니다 . 즉, 현재 릴리스 clang-800.0.42.1는을 (를) 기반으로 LLVM 3.9.0합니다. 첫 번째 LLVM 3.0기반 버전은로 Apple clang 2.1돌아온 것으로 보입니다 Xcode 4.1. LLVM 3.1에서 Apple clang 3.1(숫자 일치) 가 처음으로 나타납니다 Xcode 4.3.3.

    애플은 또한 정의 __apple_build_version__, 예 8000042. 이것은 가장 안정적이고 엄격하게 상승하는 버전 관리 체계에 관한 것 같습니다. 레거시 컴파일러를 지원하지 않으려면이 값 중 하나를 최소 요구 사항으로 설정하십시오.

clang따라서 Apple 버전을 포함한 최신 버전은 에 문제가 없어야 x86intrin.h합니다. 물론와 함께 gcc-5항상 다음을 사용할 수 있습니다.

#if defined (__has_include) && (__has_include(<x86intrin.h>))
#include <x86intrin.h>
#else
#error "upgrade your compiler. it's free..."
#endif

실제로 신뢰할 수없는 트릭은의 __GNUC__버전을 사용하는 것 입니다 clang. 역사적인 이유로 인해 버전 관리가 중단되었습니다 4.2.1. x86intrin.h헤더 앞에 오는 버전입니다 . 예를 들어 이전 버전과 호환되는 간단한 GNU C 확장에 유용합니다.

  • icc : 내가 알 수있는 한 x86intrin.h헤더는 적어도 Intel C ++ 16.0부터 지원됩니다. 버전 테스트는 다음과 같이 수행 할 수 있습니다 #if (__INTEL_COMPILER >= 1600). 이 버전 (및 이전 버전)도 __has_include확장을 지원합니다 .

  • MSVC : 헤더 MSVC++ 12.0 (Visual Studio 2013)를 제공하는 첫 번째 버전 인 것 같습니다 intrin.h.- 이것은 제안 하지 않습니다 x86intrin.h : #if (_MSC_VER >= 1800)버전 테스트로. 물론, 다른 모든 컴파일러에서 이식 가능한 코드를 작성하려는 경우이 플랫폼의 헤더 이름이 가장 문제가되지 않습니다.


답변