c++ 如何在两个子矩阵相乘时获得性能增强?

qzlgjiam  于 2023-01-15  发布在  其他
关注(0)|答案(2)|浏览(117)

我有一个程序要将同一个容器矩阵中的两个子矩阵相乘。我试图通过使用OpenMP API进行并行化来提高性能。下面是我使用的乘法算法。

#pragma omp parallel for
for(size_t i = 0; i < matrixA.m_edgeSize; i++) {
    for(size_t k = 0; k < matrixA.m_edgeSize; k++) {
        for(size_t j = 0; j < matrixA.m_edgeSize; j++) {
            resultMatrix(i, j) += matrixA(i, k) * matrixB(k, j);
        }
    }
}

该算法对两个输入子矩阵的元素进行逐行访问,以提高缓存的空间局部性。
还有什么其他OpenMP指令可以用来从这个简单的算法中获得更好的性能?有没有其他指令可以用来优化两个子矩阵的重叠区域上的操作?

  • 您可以假设所有子矩阵的大小相同,并且都是方形的。生成的子矩阵位于另一个容器矩阵中。*
wvt8vs2t

wvt8vs2t1#

对于矩阵-矩阵乘积,i,j,k索引的任何排列都可以顺序地计算正确的结果。并行计算就不是这样了。在原始代码中,k迭代不会写入唯一的位置,因此您不能只折叠外部两个循环。执行k,j交换,然后它 * 是 * 允许的。
当然,OpenMP可以让你从一个内核的5%效率提升到所有内核的5%。你真的想阻止循环。但这要困难得多。请参阅后藤和货车de Geijn的论文。

kzmpq1sx

kzmpq1sx2#

我添加了一些与主矩阵相关的内容。您是否使用此代码将两个更大的矩阵相乘?然后其中一个子矩阵在不同的迭代之间重用,并可能受益于CPU缓存。例如,如果一个矩阵有4个子矩阵,则每个子矩阵使用两次,以获得结果矩阵的值。
为了从缓存中获得最大的好处,重用的数据应该保存在同一个线程(内核)的缓存中。要做到这一点,也许最好将工作分配级别移动到选择两个子矩阵的位置。
所以,事情是这样的:

select sub-matrix A
    #pragma omp parallel for
    select sub-matrix B
    for(size_t i = 0; i < matrixA.m_edgeSize; i++) {
        for(size_t k = 0; k < matrixA.m_edgeSize; k++) {
            for(size_t j = 0; j < matrixA.m_edgeSize; j++) {
                resultMatrix(i, j) += matrixA(i, k) * matrixB(k, j);
            }
        }
    }

可以更快地工作,因为整个数据总是停留在同一线程(核心)中。

相关问题