gcc:使用“-mavx -mprefer-avx 128”优化单个函数

at0kjp5o  于 2023-03-18  发布在  其他
关注(0)|答案(2)|浏览(163)

我想用-mavx -mprefer-avx128优化一个函数,基本上代码都不用AVX,除了一个函数:这一个应该使用AVX128。
我试过这些方法:

__attribute__((target("avx")))
void f() { ... }

=〉似乎使用avx2

__attribute__((target("prefer-avx128")))
void f() { ... }

=〉不编译

__attribute__((target("avx")))
__attribute__((optimize("prefer-avx128")))
void f() { ... }

=〉不编译
也许有人知道怎么做?

uttx8gqw

uttx8gqw1#

-mprefer-avx128及其现代替代品-mprefer-vector-width=128-m选项,而不是-f,因此它们只能与target("string")而不是optimize("string")属性一起使用。
但实际上只有一些-m选项作为属性工作;GCC手册的x86目标属性列表主要是伊萨扩展,arch=tune=,但也包括prefer-vector-width=OPT。没有一个基于旧选项-mprefer-avx128;可能是在-mprefer-avx128过时后添加了对属性的支持,而支持-mprefer-vector-width选项。

__attribute__((target("avx,prefer-vector-width=128")))

这将启用AVX(仅AVX 1,不支持AVX 2),并针对128位自动矢量化进行调整。由于整数代码更容易自动矢量化,因此我实际上使用AVX 2进行了测试:

__attribute__((target("avx2,prefer-vector-width=128")))
unsigned foo(unsigned *arr){
    unsigned sum=0;
    for(int i=0 ; i<10240; i++) {
        sum += arr[i];
    }
    return sum;
}

__attribute__((target("avx2")))
unsigned bar(unsigned *arr){
    unsigned sum=0;
    for(int i=0 ; i<10240; i++) {
        sum += arr[i];
    }
    return sum;
}

使用gcc -O3 -mtune=haswell(Godbolt)编译,第一个版本使用vpaddd xmm,第二个版本使用vpaddd ymm(tune=haswell将法线矢量宽度首选项设置为256)。

术语:AVX 1支持vaddps等FP运算的256位矢量宽度。

AVX 2是256位整数运算,如vpaddb ymm,而跨车道 Shuffle 的粒度小于128位,如vpermps/vpermq
如果您尚未在命令行上或使用早期的#pragma GCC target启用AVX 2指令,__attribute__((target("avx")))肯定不会使用这些指令

7cjasjjr

7cjasjjr2#

您要查找的选项是__attribute__((target("prefer-vector-width=128")))--有关其他选项,请参见https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html#x86-Function-Attributes。

__attribute__((target("prefer-vector-width=128")))
__attribute__((target("avx")))
void f1(float* restrict x, float const* y) { 
    for(int i=0; i<16; ++i)
    {
        x[i] += y[i];
    }
}

Godbolt-演示:https://godbolt.org/z/f3xWY3vs6

相关问题