【问题标题】:Get GCC to use AVX in 32-bit code (-m32)?让 GCC 在 32 位代码 (-m32) 中使用 AVX?
【发布时间】:2014-06-04 15:37:26
【问题描述】:

我有一个 C 程序,它只能在我正在编译代码的 Ivy Bridge CPU 上运行,在 gcc 4.8 上,我尝试使用 -march=native 进行编译以利用 CPU 的所有特定指令。 我也想在 32 位模式下编译它以进行一些研究比较

我以这种方式为 x64 编译了程序(注意我在 Linux x64 上)

gcc -march=native -s -O2 mycode.c

反汇编代码,可以看到使用了AVX指令集

对于 32 位 x86,这种方式

gcc -m32 -march=native -s -O2 mycode.c

如果我尝试反汇编代码,我看不到任何 AVX 指令,并且指令集是 Pentium Pro,80x87。像 fld / fadd / fstp 用于 FP 数学。添加-mavx 没有帮助,结果相同。

我该如何解决这个问题?

【问题讨论】:

  • -mavx 并没有告诉编译器它必须使用 AVX 指令,只是它可以这样做,如果它想要......但也许它决定使用它们会不会产生更好的代码
  • @JonathanWakely 我知道,但似乎很奇怪,为 x64 编译的同一程序利用了 AVX,而在 x86 中更喜欢完全避免使用这些。 (此外,在没有新指令集的情况下,在 x86 中生成的代码要长得多。)
  • gcc 可能“认为”32 位操作系统(和 64 位操作系统 32 位仿真)不支持 256 位 YMM 状态。 -mavx 应该启用优化。
  • 人们不再关心 32 位是很常见的。 “如果你想要性能,升级到64位。然后我们可以谈谈。”甚至英特尔也展示了这一点,因为 AVX512 在 32 位上将坚持 8 个寄存器,但在 64 位上将获得 32 个寄存器。

标签: c linux gcc compiler-optimization avx


【解决方案1】:

来自GCC 4.8.3 manual

-m32 -m64 -mx32

为 32 位或 64 位环境生成代码。 -m32 选项将 int、long 和指针类型设置为 32 位,并生成可在任何 i386 系统上运行的代码。 -m64 选项将 int 设置为 32 位,将 long 和指针类型设置为 64 位,并为 x86-64 体系结构生成代码。对于 Darwin,只有 -m64 选项也会关闭 -fno-pic 和 -mdynamic-no-pic 选项。

-mx32 选项将 int、long 和指针类型设置为 32 位,并为 x86-64 架构生成代码。

使用 AVX 指令最接近 -m32 的是使用 -mx32 代替它,但它可能不是你想要的。

【讨论】:

  • 感谢您的回答,现在我尝试测试 -mx32
  • yes with -mx32 似乎也使用 AVX 指令,但是当我出于某种原因尝试反编译时生成的程序集完全是一场灾难,几乎无法阅读。如果我为 x64 编译或使用 -m32 在这两种情况下都是可读的
【解决方案2】:

-m32 的默认值为 -mfpmath=387

如果您使用 -O3 -m32 -march=native 编译,

GCC4.8 使用 AVX 自动矢量化,但要获得像 vmovss xmm0, DWORD PTR [edx+eax*4] 这样的标量 AVX 数学,使用 -mfpmath=sse 作为好吧

例如

void foo(float *arr){
    for(int i=0;i<4096;i++){
        arr[i] *= 2;
    }
}

on Godbolt with gcc4.8.5 -m32 -O2 -Wall -march=native(在 Skylake-X 上)编译为:

foo(float*):
    mov     edx, DWORD PTR [esp+4]
    xor     eax, eax
.L3:
    fld     DWORD PTR [edx+eax*4]
    fadd    st, st(0)
    fstp    DWORD PTR [edx+eax*4]
    add     eax, 1
    cmp     eax, 4096
    jne     .L3
    rep ret

-O3 它使用 x87 进行标量介绍/清理,但仍将 vaddps ymm 用于主循环。

或者使用 -mfpmath=sse -m32 -O2 -Wall -march=native 我们会得到您可能期望的结果:

foo(float*):
        mov     edx, DWORD PTR [esp+4]
        xor     eax, eax
.L3:
        vmovss  xmm0, DWORD PTR [edx+eax*4]
        vaddss  xmm0, xmm0, xmm0
        vmovss  DWORD PTR [edx+eax*4], xmm0
        add     eax, 1
        cmp     eax, 4096
        jne     .L3
        rep ret

我使用了-march=native,因为gcc4.8.5 对于-march=ivybridge 来说太旧了,我不想建议-march=corei7-avx 或他们过去使用的任何愚蠢的名称。并且绝对不想仅建议 -mavx 启用 AVX 而无需设置调整选项,将其保留在 -mtune=generic。并且无法启用 popcnt、BMI 或您的 CPU 可能具有的任何其他功能。


顺便说一句,-o2 将输出文件名设置为2。而-s 会生成一个剥离的二进制文件,这几乎不是您想要的反汇编。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-22
    • 2021-05-29
    • 2013-09-22
    • 2018-06-19
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2012-12-09
    相关资源
    最近更新 更多