ไฟล์ส่วนหัวสำหรับ x86 SIMD intrinsics


131

ไฟล์ส่วนหัวใดที่ให้อินทรินนิกส์สำหรับส่วนขยายชุดคำสั่ง x86 SIMD (MMX, SSE, AVX, ... ) ดูเหมือนว่าจะไม่พบรายการดังกล่าวทางออนไลน์ ช่วยแก้ให้ด้วยนะถ้าฉันผิด.

คำตอบ:


174

วันนี้คุณควรรวม<immintrin.h>ไว้ มันรวมทุกอย่าง

GCC และเสียงดังกราวจะหยุดคุณจากการใช้ intrinsics สำหรับคำแนะนำคุณยังไม่ได้เปิดใช้งานที่รวบรวมเวลา (เช่นกับ-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

รวมถึงสิ่งเหล่านี้ในการดึงก่อนหน้านี้ทั้งหมด (ยกเว้น SSE4A เฉพาะของ AMD: immintrin.hไม่ดึงสิ่งนั้นเข้ามา)

คอมไพเลอร์บางตัวมี<zmmintrin.h>สำหรับ AVX512


62
หรือคุณสามารถ#include <x86intrin.h>ดึงทุกสิ่งที่คุณต้องการได้
Paul R

2
zmmintrin.h มี AVX-512 intrinsics
onitake

3
ทำไม p, t, s และ n สำหรับ SSE3 / SSSE3 / SSE4.1 และ 4.2 ตัวละครเหล่านั้นแสดงถึงอะไร?
phuclv

5
@ LưuVĩnhPhúc SSE3 = Prescott คำสั่งใหม่ SSSE3 = Tejas คำแนะนำใหม่ ฉันคิดว่า SSE4.2 และ AES หมายถึงตระกูลโปรเซสเซอร์ที่พวกเขาเปิดตัว (Nehalem และ Westmere)
Drew McGowen

14
อย่ารวม<zmmintrin.h>โดยตรง gcc ไม่ได้ให้ไว้ เพียงแค่ใช้<immintrin.h>หรือยิ่ง - สมบูรณ์<x86intrin.h>มากขึ้น คำตอบนี้เป็นคำตอบที่ล้าสมัยโดยทั่วไปเว้นแต่คุณจะจงใจหลีกเลี่ยงการรวมอินทรินนิกสำหรับ SSE เวอร์ชันใหม่เนื่องจากคอมไพเลอร์ของคุณไม่บ่นเมื่อคุณใช้คำสั่ง SSE4.1 ในขณะที่รวบรวม SSE2 (GCC / เสียงดังกราวไม่บ่นดังนั้นคุณก็ควรใช้ immintrin.h สำหรับพวกเขา IDK เกี่ยวกับคนอื่น..)
ปีเตอร์ Cordes

76

ใน GCC / clang ถ้าคุณใช้เพียง

#include <x86intrin.h>

มันจะรวมส่วนหัวของ SSE / AVX ทั้งหมดซึ่งมีการใช้งานตามที่สวิทช์คอมไพเลอร์เหมือนหรือเพียงแค่-march=haswell -march=nativeนอกจากนี้คำแนะนำเฉพาะบางอย่างของ x86 เช่นbswapหรือrorพร้อมใช้งานในรูปแบบที่แท้จริง


เทียบเท่า MSVC ของส่วนหัวนี้ <intrin.h>


หากคุณต้องการเพียง SIMD แบบพกพาให้ใช้ #include <immintrin.h>

MSVC, ICC และ gcc / clang (และคอมไพเลอร์อื่น ๆ เช่น Sun I think) ทั้งหมดรองรับส่วนหัวนี้สำหรับ SIMD intrinsics ที่จัดทำเอกสารโดยเครื่องมือค้นหา / เครื่องมือค้นหาภายในของ Intel: https://software.intel.com/sites/landingpage/IntrinsicsGuide /


ฉันไม่แน่ใจว่าเวอร์ชันที่ใหม่กว่าอาจจะ ... อย่างไรก็ตามตราบใดที่ gcc, icc และ clang มีมันก็ใช้ได้ฉันคิดว่า :-)
Gunther Piez

5
MSVC ไม่มี<x86intrin.h>แต่<intrin.h>ให้ผลลัพธ์ที่คล้ายกัน คุณยังคงต้องมีการรวบรวมตามเงื่อนไขแน่นอน :-(
โคดี้เกรย์

ทุกคอมไพเลอร์ x86 #include <immintrin.h>ที่สำคัญมี ใช้สำหรับ SIMD intrinsics คุณต้องการเพียงแค่คอมไพเลอร์ที่ใหญ่กว่าเท่านั้น (และช้ากว่าเล็กน้อยสำหรับคอมไพเลอร์) x86intrin.hหรือintrin.hหากคุณต้องการสิ่งต่างๆเช่นอินทรินซิคการหมุนจำนวนเต็ม / บิตสแกน (แม้ว่า Intel จะจัดทำเอกสารบางส่วนว่ามีอยู่immintrin.h ในคู่มือภายใน )
Peter Cordes

IIRC มีเนื้อแท้ที่ไม่ใช่ SIMD ซึ่ง Intel เอกสารว่าอยู่ใน immintrin.h แต่ gcc เสียงดังและ / หรือ MSVC มีเฉพาะในx86intrin.h/ intrin.hแต่ไม่มีในimmintrin.h.
Peter Cordes

56

ชื่อส่วนหัวขึ้นอยู่กับคอมไพเลอร์และสถาปัตยกรรมเป้าหมายของคุณ

  • สำหรับ Microsoft C ++ (กำหนดเป้าหมายเป็น x86, x86-64 หรือ ARM) และคอมไพเลอร์ Intel C / C ++ สำหรับ Windows intrin.h
  • สำหรับ gcc / clang / icc ที่กำหนดเป้าหมาย x86 / x86-64 ให้ใช้ x86intrin.h
  • สำหรับ gcc / clang / armcc กำหนดเป้าหมาย ARM ด้วยการใช้ NEON arm_neon.h
  • สำหรับ gcc / clang / armcc กำหนดเป้าหมาย ARM ที่ใช้ WMMX mmintrin.h
  • สำหรับ gcc / clang / xlcc กำหนดเป้าหมาย PowerPC ด้วย VMX (aka Altivec) และ / หรือ VSX ใช้ altivec.h
  • สำหรับ gcc / clang กำหนดเป้าหมาย PowerPC ด้วยการใช้ SPE 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

นี่คือข้อมูลเพิ่มเติมที่จะเพิ่มในรายการของคุณ: ใน UltraSPARC + VIS ด้วย gcc ให้ใช้ visintrin.h; หากคุณมี VSDK ของ Sun vis.h จะนำเสนอชุดอินทรินส์ที่แตกต่างกัน documention สามารถพบได้ที่นี่: GCC VIS builtins , ซัน VIS คู่มือการใช้งาน
onitake

44

จากหน้านี้

+----------------+------------------------------------------------------------------------------------------+
|     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เพื่อรับส่วนขยายของ Intel ทั้งหมดหรือx86intrin.hถ้าคุณต้องการทุกอย่างรวมทั้ง_bit_scan_forwardและ_rdtscเช่นเดียวกับเวกเตอร์ภายในทั้งหมดรวมถึงส่วนขยายของ AMD เท่านั้น หากคุณไม่เห็นด้วยเพิ่มเติมที่คุณต้องการจริงๆคุณสามารถเลือกรวมที่เหมาะสมได้โดยดูที่ตาราง

x86intrin.hเป็นวิธีที่แนะนำในการรับข้อมูลภายในสำหรับAMD XOP (Bulldozer เท่านั้นไม่ใช่แม้แต่ซีพียู AMD ในอนาคต)แทนที่จะมีส่วนหัวของตัวเอง

คอมไพเลอร์บางตัวจะยังคงสร้างข้อความแสดงข้อผิดพลาดหากคุณใช้อินทรินซิคสำหรับชุดคำสั่งที่คุณไม่ได้เปิดใช้งาน (เช่น_mm_fmadd_psไม่เปิดใช้งาน fma แม้ว่าคุณจะรวมimmintrin.hและเปิดใช้งาน AVX2 ก็ตาม)


1
smmintrin(SSE4.1) คือ Penryn (45nm Core2) ไม่ใช่ Nehalem ("i7") เราสามารถหยุดใช้ "i7" เป็นชื่อสถาปัตยกรรมได้หรือไม่? ตอนนี้ Intel ยังคงใช้มันสำหรับ SnB-familyอย่างไร้ความหมาย
Peter Cordes

immintrin.hดูเหมือนจะไม่รวม_popcnt32และ_popcnt64(เพื่อไม่ให้สับสนกับสิ่งที่อยู่ในpopcntintrin.h!) ใน GCC 9.1.0 ดังนั้นดูเหมือนว่าx86intrin.hยังคงตอบสนองวัตถุประสงค์
Thom Wiggers

12

เป็นจำนวนมากของคำตอบและแสดงความคิดเห็นได้กล่าว<x86intrin.h>คือส่วนหัวที่ครอบคลุมสำหรับ x86 [-64] SIMD intrinsics นอกจากนี้ยังมีคำแนะนำที่สนับสนุนภายในสำหรับส่วนขยาย ISA อื่น ๆ , และมีการตัดสินทั้งหมดเกี่ยวกับเรื่องนี้ ฉันจำเป็นต้องทำการขุดในเวอร์ชันที่รองรับส่วนหัวและคิดว่าอาจเป็นประโยชน์ในการแสดงรายการสิ่งที่ค้นพบ ...gccclangicc

  • gcc : รองรับx86intrin.hครั้งแรกปรากฏในgcc-4.5.0. gcc-4ชุดปล่อยจะไม่ถูกเก็บรักษาไว้ในขณะที่gcc-6.xเป็นปัจจุบันที่มีเสถียรภาพการเปิดตัวซีรีส์ gcc-5ยังแนะนำ__has_includeส่วนขยายที่มีอยู่ในทุกclang-3.xรุ่น gcc-7อยู่ในรุ่นก่อน (การทดสอบการถดถอย, ฯลฯ ) gcc-7.1.0และต่อไปนี้โครงการเวอร์ชันปัจจุบันจะได้รับการปล่อยตัวออกมาเป็น

  • เสียงดัง : x86intrin.hดูเหมือนว่าจะได้รับการสนับสนุนสำหรับทุกclang-3.xรุ่น clang (LLVM) 3.9.1รุ่นเสถียรล่าสุด สาขาพัฒนาการคือclang (LLVM) 5.0.0. ยังไม่ชัดเจนว่าเกิดอะไรขึ้นกับ4.xซีรีส์นี้

  • เสียงดังของ Apple : น่ารำคาญการกำหนดเวอร์ชันของ 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 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)เป็นการทดสอบเวอร์ชัน แน่นอนว่าหากคุณกำลังพยายามเขียนโค้ดที่พกพาได้ในคอมไพเลอร์ต่างๆเหล่านี้ชื่อส่วนหัวบนแพลตฟอร์มนี้จะเป็นปัญหาน้อยที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.