拥有两个int矩阵A和B,超过1000行和1万列,我经常需要将它们转换为浮点矩阵以获得加速(4倍或更多)。
我想知道这是为什么?我意识到有很多优化和矢量化,例如AVX等与浮点矩阵乘法相关的内容。但是,如果我没有弄错的话,还有像AVX2这样的整数指令。那么,不能使用SSE和AVX进行整数计算吗?
为什么像Numpy或Eigen这样的矩阵代数库中没有启发式方法来捕获此类情况并像浮点数一样快地执行整数矩阵乘法呢?
如果你编译这两个简单函数,它们主要就是计算一个乘积(使用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架构上)
参考:Intel Intrinsics Guide,“吞吐量”指的是倒数吞吐量,即如果没有延迟发生,每个操作使用多少个时钟周期(有些简化)。
vpmulld
和 vmulps
在吞吐量和延迟方面会有这么大的差异。 - NULL-march=native
,FP可以使用FMA指令。除了Via的一个CPU之外,所有AVX2 CPU也都有FMA。x86没有整数乘加指令,只有FP。在matmul中的大部分FLOP可以通过FMAs完成,如果您可以保持执行单元的供给(每个FMA只有1个负载),则吞吐量几乎增加了一倍,否则会限制负载吞吐量。 - Peter Cordes所有的向量-向量和矩阵-向量运算都在内部使用BLAS。BLAS已经经过数十年的优化,针对不同的架构、CPU、指令和缓存大小进行了优化,但它没有整型!
这里有一些OpenBLAS的分支正在处理此问题(还有一些在Google-groups上讨论链接)。
我想我听说英特尔的MKL(英特尔的BLAS实现)也可能正在处理整型。这个演讲看起来很有意思(在那个论坛中提到),虽然它很短,可能更多地是接近于嵌入式深度学习中有用的小整型)。
g++ -O3 -march=somethingrecent
进行编译时,它会被向量化,你可以看到类似于vpmulld
的指令。 - Marc Glisse