浮点矩阵与二进制矩阵相乘并获得双精度结果的有效方法

计算科学 矩阵 正则
2021-12-02 19:10:01

我有一个A大小为(n2, n1)的矩阵,我将它乘以一个B大小为 的矩阵(n1, n0)我已将这个单矩阵乘法确定为我的Fortran代码中的瓶颈。在大约 2000 行代码中,这一行占用了大约 77% 的运行时间。

A是具有浮点值的双精度矩阵。B目前是一个双精度矩阵,仅包含值1.00.0我可以轻松地制作这个整数,甚至是二进制,但我使用它是real为了在matmul(A,B).

执行此矩阵乘法以减少运行时间的更好方法是什么?

在任何人建议之前,我正在使用DGEMM和编译-O3and -mavxforgfortran-O3with -xhoston ifort

迄今为止,我在 上实施该程序的最大数据N = 5000n2 = 1668n1 = 1701、 和n0 = 1631该算法已实现Matlab并具有更短的运行时间。Matlab 版本大约是 2.5 秒,而这个 fortran 程序大约是 7 秒。由于这个单矩阵乘法是如此之大,我认为 Matlab 正在对变量类型做一些有趣的事情。

我已经用ifortusing编译了这个,MKL并且目前正在链接-lblas到 using -fexternal-blas,依赖于matmul执行底层BLAS例程。ldd我的二进制可执行文件的结果是:

linux-vdso.so.1 =>  (0x00002aaaaaacb000)
liblapack.so.3 => /usr/lib64/atlas/liblapack.so.3 (0x00002aaaaaccd000)
libblas.so.3 => /usr/lib64/libblas.so.3 (0x00002aaaab4f0000)
libgfortran.so.3 => /usr/lib64/libgfortran.so.3 (0x00002aaaab747000)
libm.so.6 => /lib64/libm.so.6 (0x00002aaaaba39000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003f78c00000)
libc.so.6 => /lib64/libc.so.6 (0x00002aaaabcbe000)
libf77blas.so.3 => /usr/lib64/atlas/libf77blas.so.3 (0x00002aaaac052000)
libcblas.so.3 => /usr/lib64/atlas/libcblas.so.3 (0x00002aaaac272000)
/lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)
libatlas.so.3 => /usr/lib64/atlas/libatlas.so.3 (0x00002aaaac492000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00002aaaacaee000)

B结构的方式是它有零和一。左下部分(不是真正的下三角形)有一个,右上部分(不是三角形)是零。

Matlab 代码似乎将B矩阵视为logical.

1个回答

中非零条目的百分比是多少?如果大部分条目是 0,那么视为稀疏矩阵可能会更好。 BB

你还没有告诉我们矩阵的大小。n0 和 n1 是什么?或者至少是它们的数量级?

您还没有说您当前使用的是什么 BLAS 实现。您对编译标志的具体评论表明您可能正在使用参考 BLAS 实现,与诸如 ATLAS、OpenBLAS、ACML 和 MKL 等 BLAS 例程的优化缓存感知和多线程实现相比,这将是一个非常糟糕的选择。