问题标签 [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 投票
1 回答
328 浏览

floating-point - 使用浮点计算将浮点数转换为十进制数

我正在尝试将浮点双精度值转换x为具有 12 个(正确舍入)有效数字的十进制值。我假设它x在 10^110 和 10^111 之间,因此它的十进制表示形式为x.xxxxxxxxxxxE110. 而且,只是为了好玩,我只尝试使用浮点运算。

我到达了下面的伪代码,其中所有操作都是双精度操作,符号1e98是最接近数学 10^98 的双精度数,1e98_2是最接近数学减法 10^98- 的结果的双精度数1e98。该符号适用于带有操作数, ,fmadd(X * Y + Z)的融合乘加运算。XYZ

对于上述伪代码所造成的混乱,我深表歉意,但对我来说还不是很清楚,因此有以下问题:

  1. 第一个 fmadd 是否按预期工作(计算 1e98 *(除法期间出错))?

  2. 标志。我无法说服自己他们是对的。但我也无法说服自己他们是错的。

  3. 关于这个算法可能产生错误结果的频率的任何想法,也许是争论?

  4. 如果它确实有效,如果将“q = y / 1e98”更改为“q = y * 1e-98”(保持所有其他指令相同),算法是否有可能继续工作?

我没有测试过这个算法。我没有任何带有 fmadd 指令的计算机,尽管我希望能找到一台这样我就可以执行上述操作。

0 投票
2 回答
2731 浏览

c++ - 将 AVX 与 GCC 一起使用:__builtin_ia32_addpd256 未声明

如果我#include <immintrin.h>收到此错误:

错误:“__builtin_ia32_addpd256”未在此范围内声明

我已经定义__AVX____FMA__宏来使 AVX 可用,但显然这还不够。如果我使用编译器标志-mavx而不是宏,则没有错误,但该解决方案是不可接受的。那么,我还应该定义什么来使用 AVX?

0 投票
2 回答
9934 浏览

c++ - 使用 -mavx 和 -mfma 编译时防止 GCC 自动使用 AVX 和 FMA 指令

如何使用 AVX 和 FMA 指令禁用自动矢量化?我仍然希望编译器自动使用 SSE 和 SSE2,而不是 FMA 和 AVX。

我使用 AVX 的代码检查其可用性,但 GCC 在自动矢量化时不这样做。因此,如果我-mfma在 Haswell 之前使用任何 CPU 编译并运行代码,我会得到SIGILL. 如何解决这个问题?

0 投票
2 回答
15687 浏览

c++ - GCC 中的 FMA3:如何启用

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

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

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

编辑:

根据 Mysticial 的评论,我继续使用 _mm256_fmadd_ps,现在 AVX2+FMA 版本更快。 我不确定为什么编译器不会为我这样做。 对于超过 1000x1000 的矩阵,我现在获得了大约 80 GFLOPS(没有 FMA 的峰值触发器的 110%)。万一有人不相信我的峰值翻牌计算就是我所做的。

使用两个内核时,我的 CPU 在 Turbo 模式下是 2.3 GHz。我为 ILP 获得 2,因为 Ivy Bridge 可以同时进行一次 AVX 乘法和一次 AVX 加法(我已经多次展开循环以确保这一点)。

我只得到了大约 55% 的峰值翻牌(使用 FMA)。我不知道为什么,但至少我现在看到了一些东西。

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

编辑:

有人需要重做 如何实现每个周期 4 次 FLOP 的理论最大值? 但是使用 Haswell 每个周期执行 8 个双浮点 FLOPS。

编辑

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

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

0 投票
3 回答
3067 浏览

fortran - 在对两个数组的乘积求和时,gfortran 或 ifort 编译器会明智地使用 SIMD 指令吗?

我有一些用 numpy 编写的代码,我正在考虑将其移植到 Fortran 以获得更好的性能。

我多次执行的一项操作是将两个数组的元素乘积相加:

看起来融合乘加指令会对此有所帮助。我目前的处理器不支持这些指令,所以我还不能测试。但是,我可能会升级到支持 FMA3(Intel Haswell 处理器)的新处理器。

有谁知道用“-march=native”(或等效的 ifort)编译程序是否足以让编译器(gfortran 或 ifort)明智地使用 SIMD 指令来优化该代码,或者你认为我会必须婴儿编译器或代码?

0 投票
1 回答
1043 浏览

c++ - 如何将多个 fma 操作链接在一起以提高性能?

假设在某些 C 或 C++ 代码中,我有一个名为的函数T fma( T a, T b, T c ),它执行 1 次乘法和 1 次加法,如下所示( a * b ) + c;我应该如何优化多个mul 和添加步骤?

例如,我的算法需要用 3 或 4 个 fma 操作链接并汇总在一起来实现,我如何编写这是一种有效的方法,我应该特别注意语法或语义的哪一部分?

我还想要一些关于关键部分的提示:避免更改 CPU 的舍入模式以避免刷新 cpu 管道。但我很确定,仅使用+多个调用之间的操作fma不应该改变这一点,我说“非常确定”,因为我没有太多 CPU 来测试这个,我只是遵循一些合乎逻辑的步骤.

我的算法类似于多个 fma 调用的总数

0 投票
1 回答
7892 浏览

c - 在一级缓存中获取 Haswell 的峰值带宽:仅获得 62%

我正在尝试在 Intel 处理器上为以下功能获取 L1 缓存中的全部带宽

这是来自STREAM的三元组函数。

使用具有此功能的 SandyBridge/IvyBridge 处理器(使用带有 NASM 的汇编),我得到了大约 95% 的峰值。但是,除非我展开循环,否则使用 Haswell 只能达到峰值的 62%。如果我展开 16 次,我会得到 92%。我不明白这一点。

我决定使用 NASM 在汇编中编写我的函数。汇编中的主循环如下所示。

事实证明,在Agner Fog 的 Optimizing Assembly 手册y[i] = y[i] +k*x[i]中的示例 12.7-12.11 中,他对 Pentium M、Core 2、Sandy Bridge、FMA4 和 FMA3做了几乎相同的事情(但针对)。我设法或多或少地自己重现了他的代码(实际上他在广播时在 FMA3 示例中有一个小错误)。他给出了除 FMA4 和 FMA3 之外的每个处理器的指令大小计数、融合操作、执行端口。我试图自己为 FMA3 制作这张桌子。

大小是指以字节为单位的指令长度。add和指令有半个微操作的原因jne是它们被融合到一个宏操作中(不要与仍然使用多个端口的微操作融合混淆)并且只需要端口6和一个微操作。 指令可以使用vfmadd231ps端口 0 或端口 1。我选择了端口 0。负载vmovaps可以使用端口 2 或 3。我选择了 2 并vfmadd231ps使用了端口 3。。为了与 Agner Fog 的表格保持一致,并且因为我认为说一条可以到达不同端口的指令在 1/2 的时间里平等地到达每个端口更有意义,所以我为端口分配了 1/2vmovaps并且vmadd231ps可以去至。

基于此表以及所有 Core2 处理器每个时钟周期都可以执行 4 μops 的事实,看起来这个循环应该每个时钟周期都可以,但我还没有设法获得它。有人可以向我解释为什么不展开就无法在 Haswell 上接近此功能的峰值带宽吗?如果不展开,这可能吗?如果可以,怎么做?让我明确一点,我真的在尝试最大化此功能的 ILP(我不仅想要最大带宽),所以这就是我不想展开的原因。

编辑: 这是一个更新,因为 Iwillnotexist Idonotexist 使用 IACA 显示商店从不使用端口 7。我设法在不展开的情况下打破 66% 的障碍,并且在每次迭代的一个时钟周期内完成此操作而无需展开(理论上)。让我们首先解决商店问题。

Stephen Canon 在评论中提到,端口 7 中的地址生成单元 (AGU) 只能处理简单的操作,例如[base + offset]and not [base + index]。在英特尔优化参考手册中,我发现的唯一内容是对 port7 的评论,上面写着“Simple_AGU”,但没有定义简单的含义。但后来 Iwillnotexist Idonotexist 在IACA的评论中发现,这个问题在 6 个月前已经提到过,英特尔的一名员工在 2014 年 3 月 11 日写道:

Port7 AGU 只能在具有简单内存地址(无索引寄存器)的存储上工作。

Stephen Canon 建议“使用存储地址作为加载操作数的偏移量”。我试过这样

这确实导致商店使用端口7。但是,它还有另一个问题,vmadd231ps即您可以从 IACA 看到的负载不熔断。它还需要cmp我原来的功能没有的指令。所以商店少用了一个微操作,但是cmp(或者更确切地说,add因为cmp宏与 融合jne)需要一个。IACA 报告块吞吐量为 1.5。在实践中,这只得到大约 57% 的峰值。

但我找到了一种让vmadd231ps指令也与负载融合的方法。这只能使用像这样寻址 [绝对 32 位地址 + 索引] 的静态数组来完成。Evgeny Kluev 最初提出了这一点

其中src1_endsrc2_enddst_end是静态数组的结束地址。

这用我期望的四个融合微操作重现了我的问题中的表格。如果将其放入 IACA,它会报告 1.0 的块吞吐量。从理论上讲,这应该与 SSE 和 AVX 版本一样好。在实践中,它得到了峰值的 72% 左右。这打破了 66% 的障碍,但距离我展开 16 次的 92% 仍有很长的路要走。因此,在 Haswell 上,接近顶峰的唯一选择就是展开。通过 Ivy Bridge 在 Core2 上这不是必需的,但在 Haswell 上是必需的。

结束编辑:

这是用于测试它的 C/C++ Linux 代码。NASM 代码发布在 C/C++ 代码之后。您唯一需要更改的是频率编号。在该行中double frequency = 1.3;,将 1.3 替换为处理器的工作(非标称)频率(如果 i5-4250U 在 BIOS 中禁用涡轮增压,则为 1.3 GHz)。

编译

C/C++ 代码

使用 System V AMD64 ABI 的 NASM 代码。

triad_fma_asm.asm:

triad_ava_asm.asm:

triad_sse_asm.asm:

0 投票
0 回答
103 浏览

c++ - 负累加器是否有任何 FMA 收益?

使用 c++ AMP,我正在尝试优化我的数学函数。遇到了一个与叉积有关的难题:

如您所见,我不得不翻转累积参数的符号。是否还有任何性能提升?- 是否算作额外指令?

我运行的基准测试似乎没有提高速度:/

0 投票
3 回答
2057 浏览

floating-point - fma() 是如何实现的

根据文档fma()math.h. 这非常好,而且我知道 FMA 的工作原理以及它的用途。但是,我不太确定这在实践中是如何实现的?我最感兴趣的是x86x86_64架构。

FMA 是否有浮点(非向量)指令,可能由 IEEE-754 2008 定义?

是使用 FMA3 还是 FMA4 指令?

当依赖精度时,是否存在确保使用真正的 FMA 的内在因素?

0 投票
1 回答
1306 浏览

c++ - Is there a simple way to use multiply accumulate in c++?

I've gotten great performance benefit from using the mad function in the c++AMP library. I was wondering if there is a similar function for regular c++ 11? All I found googling was stuff on AVX intrinsics but I'd rather avoid them due to them not being universally supported.

Also, they seem to be all made for processing 4+ mad operations at the same time and I'm not sure that constructing an environment for that to happen while actually just using 1 of them is even efficient.