GCC在类似的体系结构上使用“ -march = native”发出完全不同的代码

雅各古特

我正在用C语言编写OpenCL基准测试。目前,它使用C代码测量CL设备和系统处理器的融合乘累加性能。然后交叉检查结果的准确性。

我编写了本机代码以利用GCC的自动矢量化程序,并且可以正常工作。但是,我注意到GCC带有“ -march = native”标志的某些奇怪行为。

这是我的循环:

#define BUFFER_SIZE_SQRT 4096
#define SQUARE(n) (n * n)

#define ROUNDS_PER_ITERATION 48

static float* cpu_result_matrix(const float* a, const float* b, const float* c)
{
    float* res = aligned_alloc(16, SQUARE(BUFFER_SIZE_SQRT) * sizeof(float));

    const unsigned buff_size = SQUARE(BUFFER_SIZE_SQRT);
    const unsigned round_cnt = ROUNDS_PER_ITERATION;

    float lres;
    for(unsigned i = 0; i < buff_size; i++)
    {
        lres = 0;
        for(unsigned j = 0; j < round_cnt; j++)
        {
            lres += a[i] * ((b[i] * c[i]) + b[i]);
            lres += b[i] * ((c[i] * a[i]) + c[i]);
            lres += c[i] * ((a[i] * b[i]) + a[i]);
        }

        res[i] = lres;
    }

    return res;
}

当我在Broadwell系统上使用“ -march = native -Ofast”进行编译时,会得到漂亮的矢量化AVX代码。

.L19:
        vmovups ymm0, YMMWORD PTR [rcx+rdx]
        mov     eax, 48
        vmovups ymm2, YMMWORD PTR [rdi+rdx]
        vaddps  ymm1, ymm0, ymm5
        vmovups ymm3, YMMWORD PTR [rsi+rdx]
        vaddps  ymm4, ymm2, ymm5
        vmulps  ymm1, ymm1, ymm2
        vfmadd132ps     ymm4, ymm1, ymm0
        vaddps  ymm1, ymm3, ymm5
        vmulps  ymm0, ymm2, ymm0
        vmulps  ymm0, ymm0, ymm1
        vfmadd132ps     ymm4, ymm0, ymm3
        vmovaps ymm1, ymm4
        vxorps  xmm0, xmm0, xmm0
        .p2align 4,,10
        .p2align 3

即使体系结构支持,在桩驱动程序系统上使用相同的标志进行编译也会发出SSE2指令,但不会发出AVX指令。(我在这里澄清我的标题的方式是说Broadwell和打桩机没有什么相似之处,但是它们都支持相似的矢量指令集扩展,因此发出的代码应该相似。)

.L19:
        mov     eax, 48
        movups  xmm0, XMMWORD PTR [rcx+rdx]
        movups  xmm2, XMMWORD PTR [r13+0+rdx]
        movaps  xmm4, xmm0
        movaps  xmm1, xmm2
        movups  xmm3, XMMWORD PTR [rsi+rdx]
        addps   xmm4, xmm5
        addps   xmm1, xmm5
        mulps   xmm4, xmm2
        mulps   xmm1, xmm0
        mulps   xmm0, xmm2
        addps   xmm1, xmm4
        movaps  xmm4, xmm1
        mulps   xmm4, xmm3
        addps   xmm3, xmm5
        mulps   xmm0, xmm3
        addps   xmm4, xmm0
        pxor    xmm0, xmm0
        movaps  xmm1, xmm4
        .p2align 4,,10
        .p2align 3

我什至可以使用-march = broadwell编译整个项目,然后在打桩机系统上运行它,并且可以正常工作,并获得约100%的性能提升。

我正在使用GCC 5.1.0进行编译,“-ftree-vectorizer-verbose”似乎不再起作用,因此编译器的行为非常不透明。我尚未找到有关已弃用该标志的任何信息,所以我不确定为什么它不再起作用了,我真的很想弄清楚GCC在做什么。

整个项目在这里:https : //github.com/jakogut/clperf/tree/v0.1

神秘主义者

由于整个AMD Bulldozer系列产品无法有效处理256位AVX指令,因此已禁用了AVX。在内部,执行单元只有128位宽。因此,将256位操作拆分为128位,因此没有任何好处。

为了增加侮辱性伤害,在Pipedriver上,256位存储中存在一个错误,该错误将吞吐量降低到每17个周期约1个


您的测试用例似乎是异常的。在该关键循环中您没有256位存储-这样可以避免该错误。从理论上讲,这使SSE与打桩机的AVX保持一致。

决胜局来自打桩机支持的FMA3指令。这可能就是为什么AVX循环在桩驱动器上确实变得更快的原因。

您可以尝试的一件事就是-mfma4 -mtune=bdver2看看会发生什么。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

-march = native使用Clang激活哪些标志?

为什么很少使用-march = native?

GCC:Mtune,March,MCpu

在不同的ARM体系结构上编程

完全相同的代码在不同设备上获得完全不同的Tensorboard结果

对于大型缓冲区,为什么在Ryzen上使用gcc -march = native在32位模式下memcpy会变慢?

如何使用clang和distcc在不同体系结构的从属上编译(例如Mac / Linux)

是否应使用条件编译来应对不同体系结构上CGFloat的差异?

getCString和withCString在不同体系结构上的行为

为什么gcc和clang会为成员函数模板参数生成完全不同的代码?

将React Native FlatList与两个完全不同的数据数组一起使用

-march = native归结为什么?

为什么此代码段错误在64位体系结构上却在32位体系结构上能正常工作?

避免使用类似的结构重复代码C

在编译行中添加“ -march = native” intel编译器标志会导致KNL上出现浮点异常

在具有不同体系结构的群集上应指定哪个AVX和行军?

在X86机器上生成MIPS体系结构汇编代码

如何使用.replace()和.substring()修复完全不同的输出?

如何使用Random使Java中生成的数字完全不同?

干净的体系结构:对不同的数据源使用不同的模型类?

使用make为不同体系结构构建动态目标?

使用Agner的Vector类库编译多体系结构代码

GCC只能为一种特定的体系结构和操作系统编译代码吗?

gcc -march选项的默认设置是什么?

rustc /货物是否具有-march = native等效项?

为什么march = native破坏了我的程序?

如何查看-march = native将激活哪些标志?

Rust是否具有-Ofast -march = native的等效项?

Golang:代码重复和类似的结构