这是一个相当理论上的问题,但是我对此很感兴趣,如果有人愿意分享一些专业知识,他将很高兴。
我有一个包含2000行和600 col的浮点数矩阵,并希望从每一行中减去列的均值。我已经测试了以下两行,并比较了它们的运行时:
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
在不带参数的情况下运行生成的程序,即use sum()
,在我的机器上需要126秒,而仅test 1
使用mean()
0.03秒就可以运行!
编辑3:事实证明(请参见注释),不是sum()
花费那么长时间,而是将所得向量除以行数。因此,新问题是:为什么本征要花2分钟以上的时间将一个1000列的向量除以一个标量?
不知何故,每次都会重新计算部分约简(总和)和除法,因为关于部分约简的评估成本的一些关键信息由于错误地丢失了operator/
……明确评估均值解决了这个问题:
centered = data.rowwise() - (data.colwise().sum() / data.cols()).eval();
当然,此评估应由Eigen为您完成,如变更集42ab43a所固定。此修复程序将成为后续的3.2.7和3.3版本的一部分。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句