【问题标题】:Why is it faster to perform float by float matrix multiplication compared to int by int?与 int 乘 int 相比,为什么执行浮点乘浮点矩阵乘法更快?
【发布时间】:2018-01-04 12:49:31
【问题描述】:

有两个 int 矩阵 A 和 B,有超过 1000 行和 10K 列,我经常需要将它们转换为浮点矩阵以获得加速(4 倍或更多)。

我想知道为什么会这样?我意识到浮点矩阵乘法有很多优化和矢量化,例如 AVX 等。但是,对于整数(如果我没记错的话)有诸如 AVX2 之类的指令。而且,不能将 SSE 和 AVX 用于整数吗?

为什么在矩阵代数库(例如 Numpy 或 Eigen)下没有启发式算法来捕获这一点并像浮点数一样更快地执行整数矩阵乘法?

关于接受的答案:虽然@sascha 的答案非常翔实和相关,但@chatz 的答案是无论是否存在 BLAS 整数矩阵运算,int 乘法都很慢的实际原因。 p>

【问题讨论】:

  • 这将有助于使问题更具体,但由于更多人需要它来实现浮动,因此需要付出更多努力来优化浮动(在软件和硬件方面)。
  • 本题需要具体的示例代码来演示性能差异(见minimal reproducible example)。特别是考虑到代码被标记为 [c++] 和 [numpy] 完全不清楚你指的是什么。

标签: c++ numpy matrix eigen avx


【解决方案1】:

所有这些向量向量和矩阵向量操作都在内部使用BLAS。 BLAS,针对不同的拱门、CPU、指令和缓存大小进行了数十年的优化,没有整数类型!

Here is some branch of OpenBLAS 正在处理它(还有一些 tiny discussion at google-groups linking it)。

我想我听说过英特尔的 MKL(英特尔的 BLAS 实现)might be working on integer-types too。 This talk 看起来很有趣(在那个论坛中提到过),虽然它很短,而且可能更接近 小型整数类型,在嵌入式深度学习中很有用)。

【讨论】:

  • 貌似Blaze支持整数
  • Eigen 使用整数,当你用 g++ -O3 -march=somethingrecent 编译它时,它是矢量化的,你会看到像 vpmulld 这样的指令。
  • @NULL 我也没有使用过它,但我看过一个关于它的演讲,他们确实提供了一些不错的性能数据。
  • @NULL 我对这项任务没有太多经验。但看起来,如果性能对您来说如此重要,因为似乎存在差异,您必须检查所有可用的软件。也许有一天 OpenBLAS 或 MKL 会添加原生支持,但那是未来。在某些用例中,我会害怕基于浮点数的操作,但如果这对您有用(没有数字问题),那就太好了。
  • Eigen 不依赖于单独的 BLAS 实现。默认情况下,它使用自己的实现(但是,您可以告诉它使用外部 BLAS)。
【解决方案2】:

如果你编译这两个简单的函数,本质上只是计算一个产品(使用 Eigen 库)

#include <Eigen/Core>

int mult_int(const Eigen::MatrixXi& A, Eigen::MatrixXi& B)
{
    Eigen::MatrixXi C= A*B;
    return C(0,0);
}

int mult_float(const Eigen::MatrixXf& A, Eigen::MatrixXf& B)
{
    Eigen::MatrixXf C= A*B;
    return C(0,0);
}

使用标志-mavx2 -S -O3,您将看到非常相似的汇编代码,用于整数和浮点版本。 然而,主要区别在于 vpmulld 的延迟是 vmulps 的 2-3 倍,吞吐量仅为 vmulps 的 1/2 或 1/4。 (关于最新的英特尔架构)

参考:Intel Intrinsics Guide,“吞吐量”是指吞吐量倒数,即每次操作使用多少时钟周期,如果没有发生延迟(稍微简化)。

【讨论】:

  • 非常有趣!从来没有想过vpmulld 和vmulps 在吞吐量和延迟方面会如此不同。
  • 出乎意料但不足为奇。浮点矩阵运算在计算机图形学中大量使用,引发了对硬件优化的极大兴趣。应用范围从显而易见的(视频游戏和网络应用程序)到面向研究的模拟引擎和数学建模。此外,如果您认为这些速度很快,您可以在显卡上对这些类型的操作进行编程,从而获得更高的浮点操作吞吐量(一个很好的例子是 nVidia 的 CUDA 平台)。显卡专为大规模并行浮点运算而设计。
  • 此外,如果您使用-march=native,FP 可以使用 FMA 指令 - 所有 AVX2 CPU(除了来自 Via 的 CPU)也具有 FMA。 x86 没有整数 mul-add 指令,只有 FP。 matmul 中的大多数 FLOP 都可以使用 FMA 完成,如果您可以保持执行单元的馈送(每个 FMA 仅 1 个负载,否则会成为负载吞吐量的瓶颈),吞吐量几乎会再次增加一倍。
猜你喜欢
  • 2019-01-07
  • 2015-02-06
  • 2011-05-06
  • 2014-02-14
  • 1970-01-01
  • 2011-07-05
  • 2013-07-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多