Это довольно теоретический вопрос, но я очень заинтересован в этом и был бы рад, если бы у кого-то были какие-то экспертные знания по этому поводу, которые он или она хочет поделиться.
У меня есть матрица с поплавками с 2000 строками и 600 cols и хочу вычесть среднее значение столбцов из каждой строки. Я тестировал следующие две строки и сравнивал их время выполнения:
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 столбцов на один скаляр?