【问题标题】:C++ Matrix product: increased speed with little changesC++ 矩阵产品:提高速度,几乎没有变化
【发布时间】:2015-01-09 20:56:06
【问题描述】:

我正在编写一个将稀疏矩阵与完整矩阵相乘的代码。

我创建了 2 个类:SparseMatrix 和 Matrix,它们将数据存储为向量的共享指针向量。在 SparseMatrix 案例中,我将项目保存为一个对象,称为 SparseMatrixItem,具有 2 个属性:位置和值。在 Matrix 案例中,我只是保存该值。 它们可以是基于行或基于列的,由 bool 属性的值决定。

现在我正在尝试在 2 个矩阵之间编写标准产品的高效版本。在第一个实现中,我只考虑第一个矩阵是基于行的 SparseMatrix 而第二个是基于列的矩阵的情况。我通过重载运算符 * 将代码写入 SparseMatrix 类。

我发布我的实现:

template <typename scalar>
Matrix<scalar> SparseVectorMatrix<scalar>::operator*(Matrix<scalar> &input2) {
    Matrix<scalar> newMatrix(getNumberOfRows(),input2.getNumberOfColumns(),true);
    int numberOfRow=newMatrix.getNumberOfRows();
    int numberOfColumn=newMatrix.getNumberOfColumns();

    for (int i=0; i<numberOfRow; i++) {
    vector<SparseMatrixItem<scalar>>& readRow(*horizontalVectorMatrix[i]);
    vector<scalar>& writeRow(*newMatrix.internalMatrix[i]);

        for (int j=0; j<numeroColonne; j++) {
            vector<scalar>& readColumn1(*input2.internalMatrix[j]);
            writeRow[j]=fastScalarProduct(readRow, readColumn1);

        }
    }
}

我无法弄清楚的奇怪事实是,如果我更改 2 循环顺序,性能会大大提高。 我用 2 个矩阵对其进行测试:6040x4000 和 4000*6040,第一个实现耗时近 30 秒,而第二个实现仅耗时 12 秒。 我发了:

template <typename scalar>
Matrix<scalar> SparseVectorMatrix<scalar>::operator*(Matrix<scalar> &input2) {
    Matrix<scalar> newMatrix(getNumberOfRows(),input2.getNumberOfColumns(),true);
    int numberOfRow=newMatrix.getNumberOfRows();
    int numeroColonne=newMatrix.getNumberOfColumns();

    for (int j=0; j<numeroColonne; j++) {
        vector<scalar>& readColumn(*input2.internalMatrix[j]);
        vector<scalar>& writeColumn(*newMatrix.internalMatrix[j]);

        for (int i=0; i<numberOfRow; i++) {
            vector<SparseMatrixItem<scalar>>& readRow(*matriceOrizzontaleVettori[i]);
            writeColumn[i]=fastScalarProduct(readRow, readColumn);
        }
    }
}

我还发布了我使用的函数fastScalarProduct() 的代码:

template <typename scalar>
scalar SparseVectorMatrix<scalar>::fastScalarProduct
    ( vector<SparseMatrixItem<scalar>> &vector1
    , const vector<scalar> &vector2
    ) {
    int totalSum=0;
    int position;
    auto sizeVector1=vector1.size();

    for (int i=0; i<sizeVector1; i++) {
        position=vector1[i].position-1;
        if (vector2[position]) {
            totalSum+=(vector1[i].value)*vector2[position];
        }
    }
    return totalSum;
}

我用 MATLAB 尝试了相同的产品,它只需要或多或少 1.5 秒。我认为缓存内存存在问题,但由于我是这类问题的新手,所以我无法弄清楚真正的问题。

我也在尝试写一个高效的全矩阵乘积,我也面临同样的问题。

【问题讨论】:

    标签: c++ matrix sparse-matrix matrix-multiplication


    【解决方案1】:

    您说的“问题”与缓存有关是对的。我建议您阅读有关参考局部性 (http://en.wikipedia.org/wiki/Locality_of_reference) 的内容,它解释了为什么当迭代次数最多的循环位于迭代次数较少的循环内时,您的程序运行得更快。基本上,数组是线性数据结构,它们充分利用了空间局部性。

    至于在 matlab vs C++ 中运行算法所花费的时间,我建议你阅读这篇文章:Why is MATLAB so fast in matrix multiplication?

    【讨论】:

    • 您应该引用链接的维基百科文章的一些核心陈述。只是链接一个场外源(甚至是维基百科)在 SO 上并不是很受欢迎。需要说明的是:我已对您的答案表示赞同,但您应该考虑改进它。
    • 谢谢!是的,我已经阅读了 Matlab 上的帖子。现在我阅读了您的第一个链接,但是两个循环的长度相同:在我的测试中 numberOfColumn 和 numberOfRow 都是 6040。参考类型重要吗?
    猜你喜欢
    • 2016-10-30
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 2016-06-17
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    相关资源
    最近更新 更多