gcc 编译器开关 (-mavx -mavx2 -mavx512f) 到底有什么作用?

2024-04-29

我在 C/C++ 代码中明确使用了英特尔 SIMD 内在扩展。为了编译代码,我需要在命令行上指定 -mavx、-mavx512 或类似的内容。我对这一切都很满意。

然而,从阅读 gcc 手册页来看,并不清楚这些命令行标志是否也告诉 gcc 编译器尝试使用英特尔 SIMD 指令自动矢量化 C/C++ 代码。有人知道情况是否如此吗? -mavx 标志只是允许您手动将 SIMD 内在函数插入代码中,还是还告诉编译器在编译 C/C++ 代码时使用 SIMD 指令?


-mavx/-mavx2/-mavx512f (and -march=暗示它们具有相关调整设置的选项)让 GCC 在编译代码时使用 AVX / AVX2 / AVX-512 指令来处理它认为是个好主意的任何内容,包括但不限于循环的自动矢量化,如果您也启用了该功能。

SSE 指令的其他用例(如果您告诉 GCC 启用了 AVX,GCC 将使用 AVX 编码)包括复制和零初始化结构体和数组,以及内联小型常量大小的其他情况memset and memcpy。还有标量 FP 数学,即使在-O0在 64 位代码中,其中-mfpmath=sse是默认值。

代码构建于-mavx通常无法在没有 AVX 的 CPU 上运行,即使未启用自动矢量化并且您没有使用任何 AVX 内在函数;它使 GCC 对每个 SIMD 指令使用 VEX 编码而不是传统的 SSE。另一方面,除非实际自动矢量化循环,否则通常不会使用 AVX2。它与复制数据或标量 FP 数学无关。如果满足以下条件,GCC 将使用标量 FMA 指令:-mfma不过已启用。

例子在戈德螺栓上 https://godbolt.org/#z:OYLghAFBqd5TKALEBjA9gEwKYFFMCWALugE4A0BIEAZgQDbYB2AhgLbYgDkAjF%2BTXRMiAZVQtGIHgBYBQogFUAztgAKAD24AGfgCsp5eiyagA%2BudTkVjVEQJDqzTAGF09AK5smIAEzknADIETNgAcp4ARtikvgBs5AAO6ErE9kyuHl6%2BicmpQkEh4WxRMT7x1ti2aSJELKREGZ7ePFbYNnZCNXVEBWGR0b4AzFa19Y1ZLUqjPcF9xQM%2BgwCUVujupKicXMFEANSC6BA7uwBUdaRLAKQA7ABCl1oAgrsvu8dKnruXgwAiu1rfe5PV77Mi7I7CN7fH5aL6DW5QwbOHhaHzSOEIgiXHz3HFXO4PZ4g14fNhfHHQ3bnS4AVluWJpP0BhJBNyZwNepGwRHWTF2pOZTzZhMJAHpRbtsAA3Zi7ADuxCQLwAtGxgMxohJlVzgEplUJ6ABPMUSgDizmcu0w6GwSl2IgA6o8AEpU9wkZUy2xkAgALxYHT5wV2sWkyoixDewmw6tIux1SkJ7iYKWAIUwu1QSDquwihqI2FM6jIEGTqfTmezcbOpAuIoJQsWBBoOBou3MptCCmc5hZr3OcL%2B5gi7gYdiYphYSlJhYkBDT2EwEHO5F2gx8V3hIsWTmbfZe4szRhMbo9XpIpD9tvj2AkRtzLEw94VRCVLHlBBwca5PNITGVRCGgk2CrgqOBMMEwBRikOC7K%2B2C7PQ6DoAkkoykGbakm8dqsLW6BymAYD7rsZbzhWWY5lhlIAluHIvIIcYQnsWK/LCgKIsiqLouxWIUniNxAkSxL8p8tK4JS1J0gyTK0UJXzXOyck/ryIlsIKjzCkKTzWu4ESMPsCQQDpekISwq7GfpET4oJILKX%2BubKiw6maRpTxSugn6SuoRAQO5nknJugl%2BRm4j0IwpC%2BR5mDWcRxySbcPCxLSfyUgJAIKepILYN5y61oF9Y/FwKz0NwNL8N4XA6OQ6DcJaShrBsCHYoMfDkEQ2hFSsADWIA0j4AB00jrtI1yLC1AAcWgAJzXFNhjcNI/BsL1WjkBVVU1Vw/BKCAq3tZVRXkHAsAoBgbAJAw0SUNQZ0XeFaCoMewA8IMWgtHQ9AFqQO0QBEHXkBGuGGtwrVnRwwgAPJMEa/04GwxjAJIB3kIQXJVDKO3I9llTulsrU7G0/30AQESkHUhquDg/1EJey28IdNBGLqABqBDYHKEPARVrWCMIYgSJwMhyMIyhqJoyP6H4T0gOYpiWMTEQ7ZAKwoYGmPKhDgy7MqNBMOgyrJqQbj0MqSEoUo21tJUgaOEwLhuE0BiBLMRQlAYSQpIG4zNDkntpL0rsDJMVtVJ00zewYFSh0wXT1AH/QxJM4cOxMIzdPH8yJys9XrJsBg09geOHSVXBlWt/2beo42xMqoZHgjuwvf1Wj9Tw4LOKu%2BDEGCzUtLsrjnZdcbNRu/D7ToSwrEgt5ftQxULUtK3l8jm3bbtbUdZP5A9YM1yDTSsTV4fWjSLEU0%2BHNJeDOVFfcGPm9HYgECnegg/hddEC3UPaDPTwfgfV9H6f1kaA3JiDfgYNmBEChjDZGcMEZIyqqja2BAMb/WxqgXG4DKDRhLlVBWZNSAUywFsKqNMCB0z4CsRmLAWZsw5lzbBvNRChUFrIZhosND/X0C0aWst5YkyVhAFWCQ1bcA1j4bW8MpTqG1rrfWBdsCemtj6X02BLbtDSLbe2mQfbO0KAnXwfgPZ5HSCnH2JjAwZzdj4PwUdAyxwaOYyOIcHHTGsUHOaUxugRyTunF2hieBTWzg1POLRFHgPnqXG%2BK9uBVxrnXYAqBUCNx4P1SREAO67C7heckLVVwDzutEPJPAlj3wOlvaej4BjCO3iAV6/Vrg8HGlNVEh8XojVPvNLgi1yDLRRKtda/BV5WHXuPQ6x1kBoFfkUigVBP4zO/qgX%2B/8xzRCAf9UBRDsGQMhtDYGcDsDwxMIg/gyD0a2nQeoHGBZsEEzwfwAh5NKakLHrTSJAgmZKFZuzTmzAmHyH5pIIWHCVBcIlvUwwCMZYWEMII%2BAIixFcA1lrDRKCHAQCcL4/wdsPGJ19qY7Flj/YBMzi4zRYcfHOODhSmO7jSVuz8WMalac44MqDiE3Ogs2pciLlEsuQzqpxOrrXdESSUk8DSRkrJOSe6LD7oUoeeTljlInt1epaTxpokWFoGkL0po0imrEeIJdemCpGTtPam8ok%2BBiRtO%2BG8KkrBlN9LR0ggA%3D%3D

void ext(void *);
void caller(void){
    int arr[16] = {0};
    ext(arr);
}

double fp(double a, double b){
    return b-a;
}

使用 AVX 指令进行编译gcc -O2 -fno-tree-vectorize -march=haswell,因为当启用 AVX 时,GCC 完全避免到处使用传统的 SSE 编码。

caller:
        sub     rsp, 72
        vpxor   xmm0, xmm0, xmm0
        mov     rdi, rsp
        vmovdqa XMMWORD PTR [rsp], xmm0         # only 16-byte vectors, not using YMM + vzeroupper
        vmovdqa XMMWORD PTR [rsp+16], xmm0
        vmovdqa XMMWORD PTR [rsp+32], xmm0
        vmovdqa XMMWORD PTR [rsp+48], xmm0
        call    ext
        add     rsp, 72
        ret

fp:
        vsubsd  xmm0, xmm1, xmm0
        ret

-m选项不enable自动矢量化;-ftree-vectorize这样做。播出时间为-O3和更高。 (或者以有限的形式-O2对于 GCC12 及更高版本,仅在“非常便宜”时进行矢量化,例如当它知道迭代计数是 4 的倍数或其他任何值时,这样它就可以在没有清理循环的情况下进行矢量化。 clang 完全启用自动矢量化-O2.)

如果你这样做want启用扩展的自动矢量化,使用-O3以及,并且最好是-march=native or -march=znver2或其他东西而不仅仅是-mavx2. -march还设置调整选项,并将启用您可能忘记的其他 ISA 扩展,例如-mfma and -mbmi2.

隐含的调整选项-march=haswell(要不就-mtune=haswell)对于较旧的 GCC 特别有用,当tune=generic更关心没有 AVX2 的旧 CPU,或者在某些情况下将未对齐的 256 位加载作为两个独立的部分是一种胜利:为什么 gcc 不将 _mm256_loadu_pd 解析为单个 vmovupd? https://stackoverflow.com/questions/52626726/why-doesnt-gcc-resolve-mm256-loadu-pd-as-single-vmovupd

不幸的是没有类似的东西-mtune=generic-avx2 or -mtune=enabled-extension仍然关心 AMD 和 Intel CPU,但不关心那些对于您启用的所有扩展而言太旧的 CPU。


When manually使用内在函数进行矢量化时,您只能将内在函数用于已启用的指令集。 (或者是默认打开的,例如 SSE2,它是 x86-64 的基线,即使使用-m32在现代 GCC 配置中。)

例如如果你使用_mm256_add_epi32,除非您使用,否则您的代码将无法编译-mavx2。 (或者更好的是,类似-march=haswell or -march=native支持 AVX2、FMA、BMI2 和现代 x86 所具有的其他功能,and设置适当的调整选项。)

这种情况下的 GCC 错误消息是error: inlining failed in call to 'always_inline' '_mm256_loadu_si256': target specific option mismatch.

在 GCC 术语中,“目标”是您正在编译的机器。 IE。-mavx2告诉 GCC 目标支持 AVX2。因此,GCC 将生成一个可以在任何地方使用 AVX2 指令的可执行文件,例如用于复制结构体或对本地数组进行零初始化,或以其他方式扩展小型常量大小的 memcpy 或 memset。

它还将定义 CPP 宏__AVX2__, so #ifdef __AVX2__可以测试编译时是否可以假设AVX2。

如果那是not你想要的整个程序,你需要确保不使用-mavx2编译任何在没有运行时检查 CPU 功能的情况下调用的代码。例如将 AVX2 版本的函数放在单独的文件中进行编译-mavx2,或使用__attribute__((target("avx2")))。让你的程序在检查后设置函数指针__builtin_cpu_supports("avx2") https://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html,或者使用 GCC 的ifunc进行多版本控制的调度机制。

  • https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-target-function-attribute-5 https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#index-target-function-attribute-5
  • https://gcc.gnu.org/onlinedocs/gcc/Function-Multiversioning.html https://gcc.gnu.org/onlinedocs/gcc/Function-Multiversioning.html

-m选项做not自行启用自动矢量化

(自动矢量化并不是 GCC 使用 SIMD 指令集的唯一方式。)

-ftree-vectorize(作为一部分启用-O3,或者甚至在-O2在 GCC12 及更高版本中)对于 GCC 自动矢量化是必要的。和/或-fopenmp如果代码有一些#pragma omp simd。 (你肯定总是想要至少-O2 or -Os如果您关心性能;-O3 should最快,但可能并不总是如此。有时,GCC 会出现错过优化的错误,其中 -O3 会使情况变得更糟,或者在大型程序中,可能会发生较大的代码大小会导致更多的 I-cache 和 I-TLB 未命中。)

一般来说,当自动向量化和优化时,GCC(可能)会使用您告诉它可用的任何指令集(带有-m选项)。例如,-O3 -march=haswell将使用 AVX2 + FMA 自动矢量化。-O3没有-m选项将仅使用 SSE2 自动矢量化。

例如比较在戈德螺栓上 https://godbolt.org/#z:OYLghAFBqd5TKALEBjA9gEwKYFFMCWALugE4A0BIEAZgQDbYB2AhgLbYgDkAjF%2BTXRMiAZVQtGIHgBYBQogFUAztgAKAD24AGfgCsp5eiyagA%2BudTkVjVEQJDqzTAGF09AK5smBpwBkCTNgAcp4ARtikIABMUeQADuhKxPZMrh5eBglJdkL%2BgSFs4ZExVtg2OUwiRCykRGme3jyl5SlVNUR5wWER0bFK1bX1GU397Z0FRb0AlFbo7qSonFwBRADUgugQK6sAVDWkUwCkAOwAQodaAIKrN6vbSp6rhwDMACKrWi/nV7frZKtbYR3F6vLRPZ6nYHPZw8LRRaTgyEEQ5Rc6oo5nC7XX63B5sJ6okGrfaHACsp2RpNeXyxvxO1J%2Bt1I2CI8yYqzxNKu9KxWIA9HzVtgAG7MVYAd2ISBuAFo2MBmBEJDLmcAlDKhPQAJ78wUAcWczlWmHQ2CUqxEAHVLgAlYnuEgy0W2MgEABeLAqd3ZADZpDLQsRvURsArSKtVUose4mElgIFMKtUEgaqtQlqQ6Z1GQIDG4wmkynw3tSAdeZjuVFngQaDgaKtzHqggpnOZabd9uD3uZQu4GHYmKYWEo8dgh/QCPHsJgIPtyKtnlEjhDeVWnDX2zc85OC8nU3iux8udiboJw4C1si3mCvlCYXCEbfkYT0SdviecQeybgiSTyZTqRXRkbh5YCIxZNkOU8Y9QMuLgZnobhSX4bwuB0ch0G4I0lDmBZsAJZ4%2BHIIhtHgmYAGsQFJKIADppEXaRjirQiAA4tAATmOdjDG4aR%2BDYKitHIVD0Mwrh%2BCUEAhJItD4PIOBYBQDA2DiBgIkoahlNUxhIlQVAjBMUktCaOh6BDUhJIgUJSPIQNWFILVuCI5SOGEAB5JhtRsnA2GMYBJFk8hCGZWwCFFSTAuwdRsFQB0liIlYyhsidQlIGotVcHAbKIUgCAE3g5JoIw1QANQIbBxTcuJmCc/hBGEMQJE4GQ5GEZQ1E0QL9FiAyzAsQwCFCSTIBmdA4gqCKZTc55VhlGgmHQGUY1INx6Bleh0DGpQJLKGKKkcJgXDcBofEO8ZukiJosmSIQhkaeJEhuphzsKHoRl20KhDaQZjuGZo9taAYOgCLpXsuqwgbugxRlqF7Jh4GYcPmRYDBy7B4rkxCuGQ4SbLE9QWJ9GU/STXrVlJGitBongAWced8GIf4UUI%2BdXBUtTw2Zpd%2BBknQphmJBsBYHBIggBDeP4wTccCsSJKk4jSP58hKOeY46NJH1Cc1rRpB9diom4rHnhQvHuB5xX5MQCAlPQdmdI0iAtI5tBgB4HhYlM8zLOswK7PS2ryBc5giA8rzAp8vyAvQ4KAfCmyopiuKA8SrH0JStKHMypZ0JyvLapmIqWFK8rKuq1CiPq0RxEkFrK/ajQbP0JpepAcxTEsFLhrFjDxpSSbptm3yFiQEFAhTRg2B2loHAgJwoaaPwQYmN6HuyFJ59Xp64ZX6wAa%2ByHfvu3fPsqIHt/BmG6kP6Gz6Xi6pER3CUaaNGMfF7GTZl7gCaJkngD01YbsaJRFpvTQgJBOZViaKsNm2kIgEQRubWSStBbCx6N3FWVNjg8BYuxOEmseDPEYrrHiXA%2BLkAErCISIl%2BCyysPLXmckFLIDQLbOBFAqCOzYc7VArt3YCH7BEb2Nk/YOQDkHdynlHLh2wL5EwUd%2BAx1CnHSK0VYohmTsIJKgV07pSztlXK%2BU%2BAF2KkoMqFUqo1QKq1KuTUpCyDrioBuXUQDPEMH5Vu/VO7wFGr3IQ/cZpyhqMmEEbomCilIFEKee9vCz0OhvRe%2BR75XUehUDe10Kjn2hh9Co30r7pCPjkwGYw75gxvu0Del8skI1mMjZqxFmRv1ITjGhGFv6E2Jgif%2BqBAE8GAaA1YDMIEINZtwnSBFnhTCQXzCiri%2BksXhFWLQpJCHsVJOxH0PpSHkNaXQyS0lFbvyidLUSZsFbIJmBEpIDhpBAA%3D%3D%3D GCC -O3 -march=nehalem(SSE4.2) 对比-march=znver2(AVX2) 用于对整数数组求和。 (编译时常量大小以保持汇编简单)。

如果你使用-O3 -mgeneral-regs-only(后一个选项通常只在内核代码中使用),GCC 仍然会自动矢量化,但仅在它认为这样做有利可图的情况下SWAR https://en.wikipedia.org/wiki/SWAR(例如,使用 64 位整数寄存器对数组进行异或很简单,甚至可以使用 SWAR 位黑客来阻止/纠正字节之间的进位来计算字节总和)

e.g. gcc -O1 -mavx仍然只使用标量代码。

通常,如果您想要完全优化而不是自动矢量化,您可以使用类似的东西-O3 -march=znver1 -fno-tree-vectorize


其他编译器

以上所有内容对于 clang 来说也都是正确的,只是它不理解-mgeneral-regs-only。 (我想你需要-mno-mmx -mno-sse也许还有其他选择。)

(使用 SSE / AVX Intrinisics 时架构的影响 https://stackoverflow.com/questions/55747789/the-effect-of-architecture-when-using-sse-avx-intrinisics重复其中一些信息)

对于 MSVC / ICC,您can使用 ISA 扩展的内在函数,您没有告诉编译器它可以单独使用。例如,MSVC-O2没有-arch:AVX让它使用 SSE2 自动矢量化(因为这是 x86-64 的基线),并使用movaps用于复制大约 16 字节结构或其他内容。

但使用 MSVC 的目标选项风格,您仍然可以使用 SSE4 内在函数,例如_mm_cvtepi8_epi32 (pmovsxwd),甚至是 AVX 内在函数,而不告诉编译器它本身允许使用这些指令。

较旧的 MSVC 曾经制作过非常糟糕的汇编 https://stackoverflow.com/questions/7839925/using-avx-cpu-instructions-poor-performance-without-archavx/28356924#28356924当您使用 AVX / AVX2 内在函数而不-arch:AVX,例如导致在同一函数中混合 VEX 和传统 SSE 编码(例如,对 128 位内在函数使用非 VEX 编码,例如_mm_add_ps),并且在 256 位向量之后无法使用 vzeroupper,这两者都会对性能造成灾难性的影响。

但我认为现代 MSVC 已经基本解决了这个问题。尽管它仍然没有对内在函数进行太多优化,甚至没有通过它们进行恒定传播。

不优化内在函数可能与 MSVC 让您编写类似代码的能力有关if(avx_supported) { __m256 v = _mm256_load_ps(p); ...等等。如果它试图优化,它必须跟踪沿着执行路径已经看到的可以到达任何给定内在的最小扩展级别,这样它就知道哪些替代方案是有效的。 ICC也是这样。

出于同样的原因,GCC 无法将具有不同目标选项的函数相互内联。所以你不能使用__attribute__((target("")))避免运行时调度的成本;您仍然希望避免循环内的函数调用开销,即确保 AVX2 函数内有循环,否则可能不值得使用 AVX2 版本,只需使用 SSE2 版本即可。

我不知道Intel新的OneAPI编译器ICX。我认为它是基于 LLVM 的,所以它可能更像 clang。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gcc 编译器开关 (-mavx -mavx2 -mavx512f) 到底有什么作用? 的相关文章

  • Clang 使用 -nostdlib 生成崩溃代码

    我正在尝试为可执行文件设置自己的运行时环境 但无法使用 clang v3 4 1ubuntu1 目标 x86 64 pc linux gnu 来生成没有段错误的可执行文件 我已将问题简化为以下内容 如果我有一个文件 crt1 c 除了满足
  • 使用动态链接器包装 glibc 函数

    我正在尝试包装 GLIBCfstat通过将我的库注入可执行文件来实现函数 可以是任何其他 这只是概念证明 我通过将我的库放置在可执行文件的位置来做到这一点RPATH用名字指着libc so 6 我的库的源代码如下 define GNU SO
  • 如何使用 #pragma 在 G++ 中启用优化

    我想在没有命令行参数的情况下启用 g 优化 我知道 GCC 可以通过写来做到这一点 pragma GCC optimize 2 在我的代码中 但它似乎在 G 中不起作用 此页面可能有帮助 http gcc gnu org onlinedoc
  • 为什么 GCC 不将 a*a*a*a*a*a 优化为 (a*a*a)*(a*a*a)?

    我正在对科学应用程序进行一些数值优化 我注意到的一件事是 GCC 会优化调用pow a 2 通过将其编译成a a 但是调用pow a 6 没有优化 实际会调用库函数pow 这大大降低了性能 相比之下 英特尔 C 编译器 http en wi
  • 使用 AVX 内在函数代替 SSE 并不能提高速度 - 为什么?

    我已经使用 Intel 的 SSE 内在函数相当长一段时间了 并取得了良好的性能提升 因此 我希望 AVX 内在函数能够进一步加速我的程序 不幸的是 直到现在情况并非如此 可能我犯了一个愚蠢的错误 所以如果有人能帮助我 我将非常感激 我使用
  • 用更有意义的文本替换 GCC 输出中的 a-hats [重复]

    这个问题在这里已经有答案了 可能的重复 为什么 gcc 的所有错误消息中都有 https stackoverflow com questions 547071 why does gcc have a in all its error mes
  • 在 Ubuntu 上用 C 项目编译和链接 GTK 3

    我相信这不是重复的问题 在发布此问题之前我已经看过所有问题 答案 我想我这里的情况有所不同 我使用Ubuntu 12 04并下载GTK 2 和 3 我从 GNOME 网站复制了一个简单的 GTK 源代码 但是当我在终端中使用这个命令时 gc
  • C++ while 循环优化无法正常工作

    我有这个代码段 include
  • 为什么 -march=native 很少使用?

    对于大多数 C C 编译器 有一个可传递给编译器的标志 march native 它告诉编译器调整为主机 CPU 的微架构和 ISA 扩展生成的代码 即使它的名称不同 基于 LLVM 的编译器通常也有一个等效的选项 例如rustc or s
  • 使用 OpenMP 编译会导致内存泄漏

    根据 valgrind 的说法 使用 OpenMP 编译简单的 hello world 程序时可能会导致内存泄漏 这是没有意义的 因为 hello world 程序并没有有意使用任何 OpenMP 功能 假设下面的程序名为hi c并根据 g
  • 在 Linux 上将 libquadmath 与 C++ 链接

    我有一个示例代码 include
  • 什么定义了类型的大小?

    ISO C 标准规定 sizeof char lt sizeof short lt sizeof int lt sizeof long 我在 BIT Linux mint 19 1 上使用 GCC 8 大小为long int is 8 我正
  • 错误:“uint16_t”未声明? [复制]

    这个问题在这里已经有答案了 我有代码 include
  • C 中的 N 依赖注入 - 比链接器定义的数组更好的方法?

    Given a 库模块 在下文中称为Runner 它作为可重复使用的组件 无需重新编译 即静态链接库 中应用程序分区架构的 而不是主分区 请注意 它仅包含main 出于演示目的 Given a set 顺序无关 调用的其他模块 对象Call
  • AVX-512 指令编码 - {er} 含义

    在 Intel x86 指令集参考中 有许多 AVX 512 指令在指令中具有可选的 er 例如 VADDPD 的一种形式定义为 EVEX NDS 512 66 0F W1 58 r VADDPD zmm1 k1 z zmm2 zmm3 m
  • 按字节数对向量进行混洗

    有什么办法可以左移 v 0 gt v 1 a m128i by n字节 其中n仅在运行时才知道 我目前仅限于 AVX1 但如果 AVX2 512 使这变得更容易 我非常感兴趣 I found mm bslli si128 m128i imm
  • 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符:“vfmadd132pd”、“231”和“213”?

    有人可以向我解释一下为什么融合乘法累加指令有 3 种变体 vfmadd132pd vfmadd231pd and vfmadd213pd 而只有一个 C 内在函数 mm256 fmadd pd 为了简单起见 在 AT T 语法中 有什么区别
  • arm-linux-gnueabi 编译器选项

    我在用 ARM Linux gnueabi gcc在 Linux 中为 ARM 处理器编译 C 程序 但是 我不确定它编译的默认 ARM 模式是什么 例如 对于 C 代码 test c unsigned int main return 0x
  • ELF动态符号表

    我有一个关于 ELF 动态符号表的问题 对于 FUNC 类型的符号 我注意到某些二进制文件中的值为 0 但在其他二进制文件中 它具有一些非零值 这两个二进制文件都是由 gcc 生成的 我想知道为什么会出现这种差异 有没有编译器选项来控制这个
  • 包括带有大量全局变量的 C 头文件

    我有一个包含 100 多个全局变量的包含文件 它正在库中使用 但我链接库的一些程序也需要访问全局变量 它的构建方式 In one library c file define Extern In the programs that use t

随机推荐