Это довольно теоретический вопрос, но я очень заинтересован в этом и был бы рад, если бы у кого-то были некоторые экспертные знания по этому поводу, которые он или она хочет разделить.Почему метод Eigens mean() намного быстрее, чем 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
, что может объяснить эту огромную разницу в производительности?
Edit: Я хотел бы добавить, что data
в коде выше на самом деле типа Eigen::Map< Eigen::MatrixXf<Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
и отображает функциональность Эйгена к необработанному буферу.
Edit 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;
}
Compile с:
g++ -O3 -std=c++11 -o test test.cc
Запуск результирующей программы без аргументов, так что используется sum()
, занимает 126 секунд на моей машине, при запуске test 1
с использованием mean()
занимает всего 0,03 секунды!
Edit 3: Как оказалось (см комментарии), не sum()
, который занимает так много времени, но деление результирующего вектора на число строк. Итак, новый вопрос: почему Эйген занимает более 2 минут, чтобы разделить вектор на 1000 столбцов на один скаляр?
Вы выполняете два вычисления один за другим в одном и том же пробеге? Если это так, это может быть проблема кэширования, попробуйте поменять порядок. – toth
Нет, я тестировал их отдельно. – Callidior
Я никогда не использовал Eigen и поэтому не смогу вам помочь, но я думаю, что было бы полезно людям, если бы вы предоставили сквозной тест, который они могут запустить, демонстрируя то, о чем вы просите. Таким образом, люди могут лучше проверить себя, что происходит. – SirGuy