Questa è una domanda piuttosto teorica, ma sono piuttosto interessato a questo e sarei lieto se qualcuno avesse qualche conoscenza esperta su questo che lui o lei è disposto a condividere.Perché il metodo mean() di Eigens è molto più veloce di sum()?
Ho una matrice di galleggianti con 2000 righe e 600 colonne e voglio sottrarre la media delle colonne di ogni riga. Ho verificato le seguenti due linee e confrontato la loro compressione:
MatrixXf centered = data.rowwise() - (data.colwise().sum()/data.cols());
MatrixXf centered = data.rowwise() - data.colwise().mean();
ho pensato, mean()
non sarebbe fare qualcosa di diverso dal dividendo la somma di ogni colonna per il numero di righe, ma mentre l'esecuzione della prima linea prende 12,3 secondi sul mio computer, la seconda riga finisce in 0,09 secondi.
Sto usando Eigen version 3.2.6
, che attualmente è l'ultima versione e le mie matrici sono archiviate in ordine di riga principale.
Qualcuno sa qualcosa degli interni di Eigen
che potrebbe spiegare questa enorme differenza di prestazioni?
Edit: Dovrei aggiungere che data
nel codice di cui sopra è in realtà di tipo Eigen::Map< Eigen::MatrixXf<Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >
e mappe funzionalità di Eigen in un buffer crudo.
Edit 2: Come suggerito da GuyGreer, fornirò alcuni esempi di codice per riprodurre i miei risultati:
#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;
}
Compilare con:
g++ -O3 -std=c++11 -o test test.cc
Esecuzione del programma risultante senza argomenti, quindi utilizza sum()
, impiega 126 secondi sulla mia macchina, mentre è in esecuzione test 1
utilizzando mean()
richiede solo 0,03 secondi!
Edit 3: Come si è scoperto (vedi commenti), non è sum()
che richiede molto tempo, ma la divisione del vettore risultante dal numero di righe. Quindi la nuova domanda è: perché Eigen impiega più di 2 minuti per dividere un vettore con 1000 colonne per singolo scalare?
Stai eseguendo i due calcoli uno dopo l'altro nella stessa esecuzione? Se è così, potrebbe essere un problema di cache, prova a scambiare l'ordine in giro. – toth
No, li ho testati separatamente. – Callidior
Non ho mai usato Eigen e quindi non sarò in grado di aiutarti, ma penso che sarebbe utile per le persone se fornissi un test end-to-end che possano essere eseguiti dimostrando ciò che stai chiedendo. In questo modo le persone possono controllare meglio se stessi cosa sta succedendo. – SirGuy