首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GCC中的FMA3 :如何启用

GCC中的FMA3 :如何启用
EN

Stack Overflow用户
提问于 2014-01-08 16:37:00
回答 2查看 16.7K关注 0票数 23

我有一台i5-4250U,里面有AVX2和FMA3。我正在我写的Linux上测试GCC 4.8.1中的一些密集矩阵乘法代码。下面是我编译的三种不同方式的列表。

代码语言:javascript
复制
SSE2:     gcc matrix.cpp -o matrix_gcc -O3 -msse2 -fopenmp
AVX:      gcc matrix.cpp -o matrix_gcc -O3 -mavx  -fopenmp
AVX2+FMA: gcc matrix.cpp -o matrix_gcc -O3 -march=native -fopenmp -ffast-math

SSE2和AVX版本在性能上显然是不同的。然而,AVX2+FMA并不比AVX版本好。我不明白这个。我得到超过80%的峰值失败的CPU假设没有FMA,但我认为我应该能够做得更好的FMA。矩阵乘法应直接受益于FMA。我基本上是在AVX中同时做八个点的产品。当我检查march=native时,它给出:

代码语言:javascript
复制
cc -march=native -E -v - </dev/null 2>&1 | grep cc1 | grep fma 
...-march=core-avx2 -mavx -mavx2 -mfma -mno-fma4 -msse4.2 -msse4.1 ...

所以我可以看到它是启用的(只是为了确定我添加了-mfma,但这并没有什么区别)。ffast-math应该允许轻松的浮点模型如何在SSE/AVX中使用融合乘法加(FMA)指令

编辑:

根据神秘的评论,我继续使用_mm256_fmadd_ps,现在AVX2+FMA版本更快了。我不知道为什么编译器不会为我做这件事。,我现在得到了大约80个GFLOPS (110%的峰值触发器没有FMA),用于1000×1000矩阵。如果有人不相信我的峰值失败计算,这里是我所做的。

代码语言:javascript
复制
peak flops (no FMA) = frequency * simd_width * ILP * cores
                    = 2.3GHZ    * 8          * 2   * 2     =  73.2 GFLOPS
peak flops (with FMA) = 2 * peak flops (no FMA)            = 146.2 GFLOPS

我在涡轮模式下使用这两种核的CPU是2.3 GHz。我得到2的ILP,因为常春藤桥可以做一个AVX乘法和一个AVX加法同时(我已经展开了循环多次,以确保这一点)。

我只得到了大约55%的高峰失败(与FMA)。我不知道为什么,但至少我现在看到了一些东西。

一个副作用是,我现在得到一个小的误差,当我比较一个简单的矩阵乘法算法,我知道我相信。我认为这是因为FMA只有一种舍入模式,而不是通常是两种(讽刺的是,FMA打破了IEEE浮点规则,尽管它可能更好)。

编辑:

有人需要重做如何实现理论上每个周期4次失败的最大值?,但每次做8双浮点触发器与哈斯韦尔。

编辑

实际上,神秘主义已经更新了他的项目,以支持FMA3 (见上面链接中的答案)。我在Windows8中使用MSVC2012运行了他的代码(因为Linux版本没有使用FMA支持进行编译)。以下是结果。

代码语言:javascript
复制
Testing AVX Mul + Add:
Seconds = 22.7417
FP Ops  = 768000000000
FLOPs   = 3.37705e+010
sum = 17.8122

Testing FMA3 FMA:
Seconds = 22.1389
FP Ops  = 1536000000000
FLOPs   = 6.938e+010
sum = 333.309

这是69.38倍浮点数的FMA3的GFLOPS。对于单个浮点,我需要加倍,这是138.76 SP GFLOPS。我计算我的峰值是146.2 SP GFLOPS。,也就是峰值的95%!,换句话说,我应该能够对我的GEMM代码进行相当大的改进(尽管它已经比特征代码快了很多)。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-02-08 19:37:49

这里只回答了问题的一小部分。如果您编写_mm256_add_ps(_mm256_mul_ps(areg0,breg0), tmp0),gcc-4.9处理它几乎像内联asm,并且没有对它进行过多的优化。如果您用areg0*breg0+tmp0 ( gcc和clang都支持的语法)替换它,gcc就开始优化,如果可用的话可以使用FMA。我是gcc-5的改进了,例如,_mm256_add_ps现在是作为一个内联函数实现的,它只使用+,所以具有内部结构的代码也可以进行优化。

票数 9
EN

Stack Overflow用户

发布于 2015-12-25 10:12:38

下面的编译器选项足以将_mm256_add_ps(_mm256_mul_ps(a, b), c)压缩到单个fma指令(例如vfmadd213ps):

代码语言:javascript
复制
GCC 5.3:   -O2 -mavx2 -mfma
Clang 3.7: -O1 -mavx2 -mfma -ffp-contract=fast
ICC 13:    -O1 -march=core-avx2

我尝试了/O2 /arch:AVX2 /fp:fast与MSVC,但它仍然没有收缩(惊喜)。MSVC将承包标量操作。

GCC开始这么做,至少从GCC 5.1开始。

虽然对于某些编译器来说,-O1足以进行这种优化,但是总是至少使用来实现总体性能,最好是使用-O3 -march=native -flto和配置文件引导的优化。

如果您的代码没有问题,-ffast-math

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21001388

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档