为什么Eigens mean()方法比sum()快得多?

时间:2015-10-27 19:53:25

标签: c++ eigen

这是一个相当理论化的问题,但我对它很感兴趣,如果有人对他或她愿意分享这方面的专业知识,我会很高兴。

我有一个带有2000行和600列的浮点矩阵,想要从每行中减去列的平均值。我测试了以下两行并比较了它们的运行时间:

MatrixXf centered = data.rowwise() - (data.colwise().sum() / data.cols());
MatrixXf centered = data.rowwise() - data.colwise().mean();

我想,mean()不会做一些不同于将每列的总和除以行数的事情,但是当我的计算机上第一行的执行需要12.3秒时,第二行的完成时间为0.09秒。

我正在使用Eigen version 3.2.6,目前是最新版本,我的矩阵按行主要顺序存储。

有人知道Eigen的内部结构可以解释这种巨大的性能差异吗?

编辑:我应该在上面的代码中添加data实际上是Eigen::Map< Eigen::MatrixXf<Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >类型,并将Eigen的功能映射到原始缓冲区。

编辑2:根据GuyGreer的建议,我将提供一些示例代码来重现我的发现:

#include <iostream>
#include <chrono>
#include <Eigen/Core>
using namespace std;
using namespace std::chrono;
using namespace Eigen;

int main(int argc, char * argv[])
{
    MatrixXf data(10000, 1000), centered;
    data.setRandom();
    auto start = high_resolution_clock::now();
    if (argc > 1)
        centered = data.rowwise() - data.colwise().mean();
    else
        centered = data.rowwise() - (data.colwise().sum() / data.rows());
    auto stop = high_resolution_clock::now();
    cout << duration_cast<milliseconds>(stop - start).count() << " ms" << endl;
    return 0;
}

编译:

g++ -O3 -std=c++11 -o test test.cc

运行没有参数的结果程序,因此使用sum(),在我的机器上运行126秒,而使用test 1运行mean()只需要0.03秒!

编辑3:事实证明(参见注释),sum()不是花费这么长时间,而是将结果向量除以行数。所以新的问题是:为什么Eigen需要超过2分钟才能将一列1000个列除以一个标量?

1 个答案:

答案 0 :(得分:7)

不知何故,每次都重新计算部分减少(总和)和除法,因为php错误地丢失了关于部分减少的评估成本的一些关键信息...明确评估平均值修复了问题:

operator/

当然,此评估应由Eigen为您完成,由变更集42ab43a确定。此修复程序将成为下一个3.2.7和3.3版本的一部分。