我正在尝试使用MPI进行矩阵乘法,并想寻求一些帮助来强调一个问题。该计算机具有6个内核,即32KB L1高速缓存,256KB L2高速缓存和15MB L3高速缓存。乘法是这样的:
vector<vector<double>> mult_mpi(vector<vector<double>> m,
vector<vector<double>> n) {
int rows = m.size();
int size = n.size();
vector<vector<double>> r(rows, vector<double>(size));
for (int i = 0; i < rows; ++i)
for (int k = 0; k < size; ++k)
for (int j = 0; j < size; ++j)
r[i][j] += m[i][k] * n[k][j];
return r;
}
我对int
有相同的看法:
vector<vector<int>> mult_mpi(vector<vector<int>> m, vector<vector<int>> n);
然后我作了一些图,不同的线条颜色表示节点数。
下图显示了将两个int矩阵相乘所花费的时间:
下图显示了将两个双矩阵相乘所花费的时间:
为什么双重情况下4个节点和6个节点的时间相同?我是否会遇到内存带宽的限制?
我在最后一个小时内多次尝试,结果相同。还用top
检查了机器负载,但在我看来,我一个人在那里。
答案 0 :(得分:1)
确定要不分配4K向量<>的时间吗?
vector<vector< >>
不适合挤压最佳性能。关于内存访问,矩阵乘法是有关可伸缩性和“计算密度”的最佳操作之一。实际上,运算的数量为O(N ^ 3),而数据的数量为O(N ^ 2)。
实际上,它用于对top500 fastest systems进行基准测试:HPL用于“高性能linpack”,是linpack线性代数的参考实现。猜猜是什么...基准测试中使用的运算是DGEMM,即“双精度GEneral Matrix矩阵相乘”。
DGEMM是BLAS库中操作的名称,它是线性代数的事实上的标准。如今,有许多本地优化的BLAS库,包括商业(INTEL MKL,IBM ESSL等)和开源(ATLAS),但是它们都使用相同的原始BLAS接口(最初是fortran,现在也为C)。 。 (注意:the original implementation未优化)
基于BLAS的还有LAPACK个库:系统求解器,本征系统,...还有优化的lapack库,但是通常使用优化的BLAS库会压缩90%的性能。
我非常了解一个功能强大的基于MPI的并行库(不是唯一一个... HPL是另一个)。SCALAPACK,它包含PBLAS(并行BLAS),并且在其中... DGEMM的优化并行版本。
SCALAPACK随SLUG一起提供,在这里您可以找到关于块循环分布的绝佳解释,这是用于压缩在并行系统上排列线性代数问题的最佳性能的数据分布策略。
但是,要获得最佳性能,您将需要将MPI可执行文件与本地优化的BLAS库链接。或写自己的书,但您并不孤单,所以不要重新发明轮子。
获得局部优化不是按行,按列而是按块访问矩阵。为了优化高速缓存和/或TLB的使用而调整了块大小(我记得刚才libgoto,另一个blas库,该库已进行了优化,以最大程度地减少了某些英特尔MKL系统达到和超过的TLB丢失率。 .. 过去)。例如,在此ATLAS paper中查找更多信息。
无论如何,如果您真的想要...我将开始分析其他车轮的锻造方式,然后再尝试制造我的车轮;)