问题标签 [fma]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
2284 浏览

c - 融合乘加和默认舍入模式

使用 GCC 5.3,以下代码与-O3 -fma

产生以下程序集

-O3我注意到 GCC已经在 GCC 4.8 中这样做了

-O3 -mfma带有产品的 Clang 3.7

但 Clang 3.7 with-Ofast -mfma产生与 GCC 相同的代码-O3 fast

我很惊讶 GCC 这样做,-O3因为从这个答案中它说

除非您允许宽松的浮点模型,否则不允许编译器融合分离的加法和乘法。

这是因为 FMA 只有一个舍入,而 ADD + MUL 有两个。因此编译器将通过融合违反严格的 IEEE 浮点行为。

但是,从这个链接它说

无论 FLT_EVAL_METHOD 的值如何,任何浮点表达式都可以收缩,也就是说,计算好像所有中间结果都具有无限范围和精度。

所以现在我很困惑和担心。

  1. GCC 使用 FMA 是否合理-O3
  2. 融合是否违反严格的 IEEE 浮点行为?
  3. 如果融合确实违反了 IEEE 浮点行为,并且由于GCC 返回__STDC_IEC_559__,这不是矛盾吗?

由于 FMA可以在软件中模拟,因此 FMA似乎应该有两个编译器开关:一个告诉编译器在计算中使用 FMA,另一个告诉编译器硬件具有 FMA。


显然这可以通过选项来控制-ffp-contract。使用 GCC 默认是-ffp-contract=fast,而使用 Clang 则不是。其他选项,例如-ffp-contract=on-ffp-contract=off不产生 FMA 指令。

例如带有-O3 -mfma -ffp-contract=fast产生的 Clang 3.7 vfmadd132ss


#pragma STDC FP_CONTRACT我检查了set toONOFFwith -ffp-contractset to onoff和的一些排列fast。在所有情况下,我也使用了-O3 -mfma.

使用 GCC,答案很简单。#pragma STDC FP_CONTRACTON 或 OFF 没有区别。只-ffp-contract重要。

fma它使用的GCC

  1. -ffp-contract=fast(默认)。

使用 Clang 它使用fma

  1. -ffp-contract=fast.
  2. 使用-ffp-contract=on(默认)和#pragma STDC FP_CONTRACT ON(默认为OFF)。

换句话说,使用 Clang 您可以fma使用#pragma STDC FP_CONTRACT ON(因为-ffp-contract=on是默认设置)或使用-ffp-contract=fast. -ffast-math(因此-Ofast)设置-ffp-contract=fast


我研究了 MSVC 和 ICC。

对于 MSVC,它使用 fma 指令和/O2 /arch:AVX2 /fp:fast. 使用 MSVC/fp:precise是默认设置。

对于 ICC,它使用 fma with -O3 -march=core-avx2-O1实际上就足够了)。这是因为默认情况下 ICC 使用-fp-model fast. 但是 ICC 使用 fma 甚至-fp-model precise. 要使用 ICC 禁用 fma,请使用-fp-model strict-no-fma

因此,默认情况下,GCC 和 ICC 在启用 fma 时使用 fma(使用-mfmaGCC/Clang 或-march=core-avx2使用 ICC),但 Clang 和 MSVC 不使用。

0 投票
2 回答
468 浏览

gcc - 我需要做什么才能让 GCC 4.9 认识到使用 AVX FMA 的机会?

我有std::vector<double> X,Y两个尺寸N(和N%16==0),我想计算sum(X[i]*Y[i])这是融合乘加(FMA)的经典用例,它在支持 AVX 的处理器上应该很快。我知道我所有的目标 CPU 都是 Intel、Haswell 或更新的。

如何让 GCC 发出该 AVX 代码?-mfma是解决方案的一部分,但我需要其他开关吗?

std::vector<double>::operator[]阻碍了这一点?我知道我可以转变

所以编译器可以发现&X[0]循环中没有改变。但这是否足够甚至必要?

当前编译器是 GCC 4.9.2、Debian 8,但如有必要可以升级到 GCC 5。

0 投票
2 回答
1438 浏览

c - 英特尔 FMA 指令提供零性能优势

考虑使用 Haswell 的 FMA 指令的以下指令序列:

可以使用非 FMA 指令表示相同的计算,如下所示:

人们会期望 FMA 版本比非 FMA 版本提供一些性能优势。

但不幸的是,在这种情况下,性能改进为零 (0)。

谁能帮我理解为什么?

我在基于核心 i7-4790 的机器上测量了这两种方法。

更新:

因此,我分析了生成的机器代码并确定 MSFT VS2013 C++ 编译器正在生成机器代码,因此 r1 和 r2 的依赖链可以并行调度,因为 Haswell 有 2 个 FMA 管道。

r3 必须在 r1 之后调度,因此在这种情况下,第二个 FMA 管道是空闲的。

我认为如果我展开循环以执行 6 组 FMA 而不是 3 组,那么我可以让所有 FMA 管道在每次迭代时都处于忙碌状态。

不幸的是,当我在这种情况下检查程序集转储时,MSFT 编译器没有选择允许我正在寻找的并行调度类型的寄存器分配,并且我证实我没有得到我正在寻找的性能提升为了。

有没有办法可以更改我的 C 代码(使用内在函数)以使编译器能够生成更好的代码?

0 投票
2 回答
5809 浏览

assembly - 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符,“vfmadd132pd”、“231”和“213”?

有人可以向我解释为什么融合乘法累加指令有 3 种变体:vfmadd132pd,vfmadd231pdvfmadd213pd, 而只有一个 C 内在函数_mm256_fmadd_pd

为简单起见,(在 AT&T 语法中)有什么区别

我没有从英特尔的内在指南中得到任何想法。我问是因为我在我编写的一段 C 代码的汇编器输出中看到了所有这些。谢谢。


一个干净的答案(在下面重新格式化答案)

对于变体ijk,的含义vfmaddijkpd

  • 英特尔语法:op(i) * op(j) + op(k) -> op(1)
  • AT&T 语法:op(4-i) * op(4-j) + op(4-k) -> op(3)

其中op(n)表示指令后的第 n 个操作数。所以两者之间有一个逆变换:

0 投票
1 回答
1176 浏览

c# - C# 可以使用融合乘加吗?

如果 C# 编译器/抖动在所使用的硬件上可用,是否使用融合乘加操作?如果是这样,是否需要设置任何特定的编译器设置才能利用它?

0 投票
4 回答
9816 浏览

c++ - 如何从 AVX 寄存器中获取数据?

使用 MSVC 2013 和 AVX 1,我在寄存器中有 8 个浮点数:

现在我想调用inline void print(float) {...}所有 8 个花车。看起来英特尔AVX intrisics 会使这变得相当复杂:

但是 MSVC 甚至没有这两个内在函数中的任何一个。当然,我可以将值写回内存并从那里加载,但我怀疑在汇编级别没有必要溢出寄存器。

奖金问:我当然想写

但 MSVC 不明白许多内在函数需要循环展开。如何在 8x32 浮点数上编写循环__m256 foo

0 投票
3 回答
2162 浏览

floating-point - 我可以使用 AVX FMA 单元进行位精确的 52 位整数乘法吗?

AXV2 没有任何大于 32 位源的整数乘法。它确实提供32 x 32 -> 32乘法,以及32 x 32 -> 64乘法1,但没有 64 位源。

假设我需要输入大于 32 位但小于或等于 52 位的无符号乘法 - 我可以简单地使用浮点DP 乘法或 FMA 指令,并且当整数输入和结果可以用 52 位或更少的位表示(即,在 [0, 2^52-1] 范围内)?

我想要产品的所有 104 位的更一般的情况怎么样?或者整数乘积超过 52 位的情况(即,乘积在位索引 > 52 中具有非零值) - 但我只想要低 52 位?在后一种情况下,MUL它将给我更高的位并舍入一些较低的位(也许这就是 IFMA 的帮助?)。

编辑:事实上,根据这个答案,它也许可以做任何高达 2^53 的事情——我忘记1了尾数之前的隐含前导有效地给了你一点。


1有趣的是,正如 Mysticial在评论中解释的那样,64 位产品PMULDQ操作的延迟是 32 位版本的一半,吞吐量是 32 位版本的两倍。PMULLD

0 投票
1 回答
1717 浏览

floating-point - 了解 FMA 指令性能

我想了解如何最大限度地利用我的 CPU 上的操作数。我正在做一个简单的矩阵乘法程序,并且我有一个 Skylake 处理器。我正在查看维基百科页面以获取有关此架构的失败信息,但我很难理解它。

据我了解,FMA 指令允许 3 路 FP 输入对吗?并允许在它们之间的加法和乘法之间混合。但是当我只添加两个浮点数时会发生什么?它只是将它乘以一吗?我可以在 1 个周期中添加 3 个浮点数,还是会拆分?我看到 skylake,单精度输入有 32 个 FLOPs/cycle,但是“两个 8 宽 FMA 指令”是什么意思?

预先感谢您的解释

0 投票
3 回答
973 浏览

c++ - 处理融合乘加浮点不准确的通用方法

昨天我正在跟踪我的项目中的一个错误,几个小时后,我已经缩小到一段代码,它或多或少是在做这样的事情:

编译执行后:

从我的角度来看,有些地方是错误的,因为我要求对两个按位相同的对进行 2 次减法(我希望得到两个零),然后将它们平方(再次两个零)并将它们加在一起(零)。

事实证明,问题的根本原因是使用了 fused-multiply-add 操作,这使得结果不准确(从我的角度来看)。一般来说,我不反对这种优化,因为它承诺给出准确的结果,但在这种情况下,1.34925e-06 与我期望的 0 相差甚远。

测试用例非常“脆弱”——如果您启用更多打印或更多断言,它将停止断言,因为编译器不再使用 fused-multiply-add。例如,如果我取消注释所有行:

由于我认为这是编译器中的一个错误,因此我已经报告了这一点,但由于解释这是正确的行为而关闭了它。

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79436

所以我想知道-应该如何编写这样的计算来避免这个问题?我在考虑一个通用的解决方案,但比:

我想修复或改进我的代码 - 如果有任何需要修复/改进的东西 - 而不是-ffp-contract=off为我的整个项目设置,因为无论如何在编译器库内部使用了 fused-multiply-add (我在 sinf 中看到了很多这样的内容( ) 和 cosf()),所以这将是一个“部分解决方法”,而不是一个解决方案......我也想避免像“不要使用浮点”这样的解决方案(;

0 投票
1 回答
498 浏览

c++ - _mm_fmadd_pd 程序收到信号SIGILL,非法指令

我收到以下代码的奇怪错误:

将代码编译为:

当我运行可执行文件时,我收到以下消息:

使用 gdb 以获取更多详细信息:

但是,当使用 valgrind 时,如下所示:

该程序似乎正在运行。我在这里缺少什么?如何以稳健的方式使用 _mm_fmadd_pd?无论在 Intel 或 AMD 处理器中运行,是否都可以使示例正常工作?无论使用g ++还是icpc都可以编译吗?