【问题标题】:Floating-point number vs fixed-point number: speed on Intel I5 CPU浮点数与定点数:Intel I5 CPU 上的速度
【发布时间】:2017-02-02 07:33:15
【问题描述】:

我有一个 C/C++ 程序,其中涉及密集的 32 位浮点 矩阵数学计算,例如加法、减法、乘法、除法等。

我可以通过将 32 位浮点 数转换为 16 位定点 数来加快我的程序吗?我可以获得多少速度增益?

目前我正在使用 Intel I5 CPU。我正在使用 Openblas 执行矩阵计算。我应该如何重新实现诸如 cblas_dgemm 之类的 Openblas 函数来执行定点计算?

我知道 SSE(Simple SIMD Extensions)一次对 4x32=8x16=128 位数据进行操作,即 4 个 32 位浮点类型或 8 个 16 位定点类型。我猜从 32 位浮点数转换为 16 位定点数后,我的程序会快两倍。

【问题讨论】:

  • 不太可能,尤其是在 Haswell 及其浮点 FMA 指令上,除非您有非常具体的用例可以从中受益,例如 pmaddubswPMULHRSW
  • 冒着明显的风险,你能访问 GPU 吗?如果是这样,您可能想查看github.com/xianyi/clOpenBLAS
  • 嗨,Shawn,这是我遇到的一个有趣的资源nicolas.limare.net/pro/notes/2014/12/12_arit_speed;它也引用了agner.org/optimize,这可能有用;再次抱歉,这不是一个直接的答案,感觉有点迟钝:)
  • 我可以通过查看 Agner Fog 的表格来确认在 Haswell+ 上,浮动是要走的路。 Haswell 可以使用 2 个八元素向量 FMA/周期/内核维持 32 个 FLOP/周期/内核,但只能维持 1 个 pmaddubsw 或 pmulhrsw + 1 个 paddw/周期/内核(2 个 16 元素向量运算 = 32 个 16 位整数运算/周期/核心总数)。因此,您只需使用 OpenBLAS 即可获得更高的精度和更低的复杂性。
  • 啊,你是机器学习者!你本可以预先自愿的(!)。这是CNN吗?如果是这样,请考虑查看Winograd convolutionIntel's DNN package。除此之外,定点是一个活跃的研究领域,但英特尔处理器不适合利用。正如道格所说,它真正使英特尔 CPU 受益的唯一用例是,如果您完全是内存瓶颈,即使这样也只有

标签: performance matrix sse simd openblas


【解决方案1】:

总结:现代 FPU 硬件很难用定点击败,即使每个向量的元素数量是两倍。

现代 BLAS 库通常针对缓存性能(缓存阻塞/循环平铺)以及指令吞吐量进行了很好的调整。这让他们非常很难被击败。特别是 DGEMM 对这种优化有很大的空间,因为它对 O(N^2) 数据进行 O(N^3) 工作,因此值得只转置一个输入的缓存大小的块,以及类似的东西。

可能有助于通过以 16 位半浮点格式存储浮点数来减少内存瓶颈。没有硬件支持以该格式对它们进行数学运算,只需在加载/存储时在该格式和普通 32 位元素浮点向量之间进行转换:VCVTPH2PS (__m256 _mm256_cvtph_ps(__m128i))VCVTPS2PH (__m128i _mm256_cvtps_ph(__m256 m1, const int imm8_rounding_control)。这两条指令组成了F16C extension,首先由 AMD Bulldozer 和 Intel IvyBridge 支持。

如果有任何 BLAS 库支持该格式,则 IDK。


定点:

SSE/AVX 没有任何整数除法指令。但是,如果您只是除以常量,则可能不需要真正的 div 指令。所以这是定点的一大绊脚石。

定点的另一个大缺点是在乘法后移动以纠正小数点(二进制?)位置的额外成本。这会影响到每个向量的元素数量是 16 位定点的两倍。

SSE/AVX 实际上有相当多的压缩 16 位乘法选择(比​​任何其他元素大小都要好)。压缩乘法产生低半部分、高半部分(有符号或无符号),甚至是从顶部以下的 2 位中取 16 位的压缩乘法,并带有舍入 (PMULHRSW.html)。 Skylake 每时钟运行两个,具有 5 个周期延迟。还有整数乘加指令,但它们在成对的乘法结果之间进行水平加法。 (参见Agner Fog's insn tables,以及 标记wiki 以获得性能链接。)Haswell 和以前的没有那么多整数向量加法和乘法执行单元。通常是总 uop 吞吐量的代码瓶颈,而不是特定的执行端口。 (但一个好的 BLAS 库甚至可能有手动调整的 asm。)

如果您的输入和输出是整数,则使用整数向量通常比转换为浮点数更快。 (例如,请参阅我在 Scaling byte pixel values (y=ax+b) with SSE2 (as floats)? 上的回答,我使用 16 位定点来处理 8 位整数)。

但是,如果您真的在使用浮点数,并且有很多乘法和除法要做,那么只需使用硬件 FPU。它们在现代 CPU 中非常强大,并且已经使定点在许多任务中基本过时。正如@Iwill 指出的那样,FMA 指令是 FP 吞吐量(有时是延迟)的另一个巨大提升。


整数加/减/比较指令(但不是乘法)的延迟也低于其对应的 FP。

【讨论】:

  • 整数加/减减少不仅延迟更低,而且吞吐量更高!在 Haswell 上,您可以在端口 1 和 5 上支持两个 padd*,在端口 2 和 3 上支持两个 vmovaps,每个 CC。在 16 位定点上,可以达到 32 次加法/CC,而浮点加法,即使使用 FMA d = a*1.0+c 实现,也只能达到 16 次加法/CC。对于奖励积分,padd* 可以饱和,不会受到任何惩罚。
  • @IwillnotexistIdonotexist:是的,对于添加/子来说,事情非常棒,你可以获得每个向量两倍的元素的全部好处。
猜你喜欢
  • 2011-11-23
  • 2015-10-06
  • 2016-06-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-02
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多