为什么Eigens-mean()方法比sum()快得多
Why is Eigens mean() method so much faster than sum()?
这是一个相当理论化的问题,但我对此很感兴趣,如果有人愿意分享这方面的专业知识,我会很高兴。
我有一个由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:根据GuyGrier的建议,我将提供一些示例代码来重现我的发现:
#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秒,而使用mean()
运行test 1
只需要0.03秒!
编辑3:事实证明(请参阅注释),花费这么长时间的不是sum()
,而是结果向量除以行数。因此,新的问题是:为什么Eigen需要2分钟以上的时间才能将一个有1000列的向量除以一个标量?
不知何故,每次都会重新计算部分约简(和)和除法,因为operator/
错误地丢失了关于部分约简评估成本的一些关键信息。。。明确评估平均值解决了问题:
centered = data.rowwise() - (data.colwise().sum() / data.cols()).eval();
当然,这个评估应该由Eigen为您完成,正如变更集42ab43a所固定的那样。此修复程序将成为下一个3.2.7和3.3版本的一部分。
- 为什么通过引用返回向量比通过移动返回要快得多?
- 禁用优化后,quick-bench.com 基准测试要快得多
- C++ OpenMP 斐波那契:1 个线程的执行速度比 4 个线程快得多
- 为什么迭代 std::array 比迭代 std::vector 快得多?
- 为什么<wstring>使用自定义 wcscmp 和 wmemcmp 比较器对向量进行排序比默认快得多?
- C 为什么在原始双阵列中的分配似乎比双变量分配要快得多
- Linux 在从文件中读取数据并放入矢量时比 Windows 快得多.txt.我将如何加速Windows以做同样的事情
- 为什么 C 数组比 std::array 快得多?
- 为什么 pcre 正则表达式比 c++11 正则表达式快得多
- 为什么数组比向量快得多
- 为什么 ifstream::read 比使用迭代器快得多
- 为什么其中一个比另一个快得多
- GDI+Image比C#Image快得多
- 为什么堆栈内存的 memcpy 比堆内存快得多
- 为什么使用TBB的OpenCV函数比基于Boost的实现快得多
- 为什么多个文件的编译速度比合并文件快得多
- 为什么Windows C++多线程IOPS比IOMeter快得多
- 为什么STL算法使用指针比std::向量迭代器快得多
- 为什么使用 mkdir () 函数比使用 system ('mkdir 路径')快得多?
- 为什么Eigens-mean()方法比sum()快得多