Commit b98831fb authored by MIJIEUX Thomas's avatar MIJIEUX Thomas

Add timer to measure independently ortho, MVP and LeastSquare

parent 4b9adb93
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* DONE Implement DR+QR * DONE Implement DR+QR
* HOLD Reproducible installation * HOLD Reproducible installation
** DONE Instruction in INSTALL.org ** DONE Instruction in INSTALL.org
** DONE Update spack package
** HOLD merge request to make Chameleon headers compatible with C++ complex types ** HOLD merge request to make Chameleon headers compatible with C++ complex types
* TODO reproducible results and visualization * TODO reproducible results and visualization
** TODO Improve Logging ** TODO Improve Logging
...@@ -17,7 +18,7 @@ ...@@ -17,7 +18,7 @@
*** TODO Add timer for Least square *** TODO Add timer for Least square
*** TODO Add timer for Matrix Vector Product *** TODO Add timer for Matrix Vector Product
** TODO Improve RESULTS.org ** TODO Improve RESULTS.org
Eventually, anyone must be able to gather into the file all interesting results Eventually, anyone must be able to gather all interesting results into RESULTS.org
just by evaluating code blocks and/or tangling file from RESULTS.org just by evaluating code blocks from RESULTS.org and/or tangling RESULTS.org
* TODO Implement IB+DR * TODO Implement IB+DR
* TODO Implement IB+DR+QR * TODO Implement IB+DR+QR
...@@ -95,13 +95,16 @@ private: ...@@ -95,13 +95,16 @@ private:
void compute_real_residual(Matrix &A, const Block &X, const Block &B, Block &R) void compute_real_residual(Matrix &A, const Block &X, const Block &B, Block &R)
{ {
R.copy(B); // R <- B R.copy(B); // R <- B
_logger.notify_mvp_begin();
A.MatBlockVect(X, R, S{-1.0}, S{1.0}); // R <- B-A*X A.MatBlockVect(X, R, S{-1.0}, S{1.0}); // R <- B-A*X
_logger.notify_mvp_end();
_nb_mvp += X.get_nb_col(); _nb_mvp += X.get_nb_col();
} }
template< class Matrix, class Block > template< class Matrix, class Block >
void W_AMV(Matrix &A, Block &V, Block &W) // W = A*M*V void W_AMV(Matrix &A, Block &V, Block &W) // W = A*M*V
{ {
_logger.notify_mvp_begin();
if (A.useRightPrecond()) { if (A.useRightPrecond()) {
Block MV{W.get_nb_row(), V.get_nb_col()}; Block MV{W.get_nb_row(), V.get_nb_col()};
A.PrecondBlockVect(V, MV); // MV = M * V A.PrecondBlockVect(V, MV); // MV = M * V
...@@ -109,6 +112,7 @@ private: ...@@ -109,6 +112,7 @@ private:
} else { } else {
A.MatBlockVect(V, W); // W = A * V A.MatBlockVect(V, W); // W = A * V
} }
_logger.notify_mvp_end();
_nb_mvp += V.get_nb_col(); _nb_mvp += V.get_nb_col();
} }
...@@ -152,6 +156,15 @@ private: ...@@ -152,6 +156,15 @@ private:
return false; return false;
} }
std::tuple<P,P,bool>
check_least_square_residual(const std::vector<P> &epsilon)
{
_logger.notify_least_square_check_begin();
auto minmaxconv = _hess.check_least_square_residual(epsilon);
_logger.notify_least_square_check_end();
return minmaxconv;
}
public: public:
template<class RestartParam> template<class RestartParam>
ArnoldiDR(Logger<P> &logger, Restarter<RestartParam, S> &restarter, ArnoldiDR(Logger<P> &logger, Restarter<RestartParam, S> &restarter,
...@@ -190,8 +203,8 @@ public: ...@@ -190,8 +203,8 @@ public:
* *
* \return whether the convergence was reached * \return whether the convergence was reached
*/ */
template<class Matrix, class Block, class Restarter> template<class Matrix, class Restarter>
bool run( const Matrix &A, Block &X, const Block &B, bool run( const Matrix &A, Block<S> &X, const Block<S> &B,
const int max_krylov_space_size, const int max_krylov_space_size,
const std::vector<P> &epsilon, const std::vector<P> &epsilon,
Restarter &restarter, Restarter &restarter,
...@@ -199,14 +212,14 @@ public: ...@@ -199,14 +212,14 @@ public:
{ {
print_header(max_krylov_space_size); print_header(max_krylov_space_size);
Block R1{}; // R1 = RHS of projected problem Block<S> R1{}; // R1 = RHS of projected problem
_logger.notify_iteration_begin(_iteration_count, _size_krylov_space); _logger.notify_iteration_begin(_iteration_count, _size_krylov_space);
if (restarter && _base.get_nb_block() > 0) { if (restarter && _base.get_nb_block() > 0) {
restarter.run(R1, _hess); restarter.run(R1, _hess);
//check_arnoldi_formula(A, _base, _hess); //check_arnoldi_formula(A, _base, _hess);
} else { //No DR, or first run of arnoldi } else { //No DR, or first run of arnoldi
_base.reset(); _base.reset();
Block R0 = _base.get_W(_nbRHS); Block<S> R0 = _base.get_W(_nbRHS);
compute_real_residual(A, X, B, R0); compute_real_residual(A, X, B, R0);
_base.increase(_nbRHS); _base.increase(_nbRHS);
R1.realloc(_nbRHS, _nbRHS); R1.realloc(_nbRHS, _nbRHS);
...@@ -223,18 +236,20 @@ public: ...@@ -223,18 +236,20 @@ public:
while (!convergence && _size_krylov_space < max_krylov_space_size) { while (!convergence && _size_krylov_space < max_krylov_space_size) {
++ _iteration_count; ++ _iteration_count;
_logger.notify_iteration_begin(_iteration_count, _size_krylov_space); _logger.notify_iteration_begin(_iteration_count, _size_krylov_space);
Block Vj = _base.get_Vj(); // V_j Block<S> Vj = _base.get_Vj(); // V_j
assert( Vj.get_nb_col() == _nbRHS ); assert( Vj.get_nb_col() == _nbRHS );
Block W = _base.get_W(_nbRHS); // W (candidate) Block<S> W = _base.get_W(_nbRHS); // W (candidate)
W_AMV(A, Vj, W); // W := A*M*V_j W_AMV(A, Vj, W); // W := A*M*V_j
_logger.notify_ortho_begin();
ortho.run(_hess, _base, W, A); ortho.run(_hess, _base, W, A);
_logger.notify_ortho_end();
_base.increase(_nbRHS); // add W to base _base.increase(_nbRHS); // add W to base
_size_krylov_space = _base.get_nb_vect(); _size_krylov_space = _base.get_nb_vect();
//_hess.display_hess_bitmap("Hess Before Least Square"); //_hess.display_hess_bitmap("Hess Before Least Square");
auto MinMaxConv = _hess.check_least_square_residual(epsilon); auto MinMaxConv = check_least_square_residual(epsilon);
bool proj_convergence = std::get<2>(MinMaxConv); bool proj_convergence = std::get<2>(MinMaxConv);
convergence = check_real_residual_if(proj_convergence, A, B, X, epsilon); convergence = check_real_residual_if(proj_convergence, A, B, X, epsilon);
_logger.notify_iteration_end( _logger.notify_iteration_end(
...@@ -251,10 +266,10 @@ public: ...@@ -251,10 +266,10 @@ public:
_base.reset(); _base.reset();
} else if (restarter && !convergence) { } else if (restarter && !convergence) {
int M = _hess.get_nb_vect() + _nbRHS; int M = _hess.get_nb_vect() + _nbRHS;
Block LS{M, _nbRHS}; Block<S> LS{M, _nbRHS};
_hess.compute_proj_residual(LS); _hess.compute_proj_residual(LS);
restarter.save_LS(LS); restarter.save_LS(LS);
Block H = _hess.get_hess_block(); Block<S> H = _hess.get_hess_block();
restarter.save_hess(H); restarter.save_hess(H);
} }
......
...@@ -49,7 +49,7 @@ private: ...@@ -49,7 +49,7 @@ private:
private: private:
Logger<P> &_logger; Logger<P> &_logger;
HESSENBERG<S> L; HESSENBERG<S> _F;
bool _solution_computed; bool _solution_computed;
Block<S> _solution; Block<S> _solution;
Block<S> _last_Y; Block<S> _last_Y;
...@@ -77,7 +77,6 @@ public: ...@@ -77,7 +77,6 @@ public:
int get_nb_mvp() const { return _nb_mvp; } int get_nb_mvp() const { return _nb_mvp; }
int get_nb_iteration() const { return _iteration_count; } int get_nb_iteration() const { return _iteration_count; }
private: private:
template< class Matrix, class Block, class Base > template< class Matrix, class Block, class Base >
void X_plus_MVY(Matrix &A, Block &X, Base &V, Block &Y) void X_plus_MVY(Matrix &A, Block &X, Base &V, Block &Y)
...@@ -99,11 +98,13 @@ private: ...@@ -99,11 +98,13 @@ private:
} }
template<class Matrix, class Block> template<class Matrix, class Block>
void compute_solution(Matrix &A, Block &X) void compute_real_residual(Matrix &A, Block &X, const Block &B, Block &R)
{ {
Block Y = L.alloc_least_square_sol(); R.copy(B); // R <- B
L.solve_least_square(Y); _logger.notify_mvp_begin();
X_plus_MVY(A, X, _base, Y); // X_n = X_0 + M*V*Y A.MatBlockVect(X, R, S{-1.0}, S{1.0}); // R <- B-A*X
_logger.notify_mvp_end();
_nb_mvp += X.get_nb_col();
} }
template< class Matrix, class Block, class BlockWP > template< class Matrix, class Block, class BlockWP >
...@@ -111,6 +112,7 @@ private: ...@@ -111,6 +112,7 @@ private:
{ {
Block W = WP.get_W(); Block W = WP.get_W();
_logger.notify_mvp_begin();
if (A.useRightPrecond()) { if (A.useRightPrecond()) {
Block MV{W.get_nb_row(), V.get_nb_col()}; Block MV{W.get_nb_row(), V.get_nb_col()};
A.PrecondBlockVect(V, MV); // MV = M * V A.PrecondBlockVect(V, MV); // MV = M * V
...@@ -118,15 +120,16 @@ private: ...@@ -118,15 +120,16 @@ private:
} else { } else {
A.MatBlockVect(V, W); // W = A * V A.MatBlockVect(V, W); // W = A * V
} }
_logger.notify_mvp_end();
_nb_mvp += V.get_nb_col(); _nb_mvp += V.get_nb_col();
} }
template<class Matrix, class Block> template<class Matrix, class Block>
void compute_real_residual(Matrix &A, Block &X, const Block &B, Block &R) void compute_solution(Matrix &A, Block &X)
{ {
R.copy(B); // R <- B Block Y = _F.alloc_least_square_sol();
A.MatBlockVect(X, R, S{-1.0}, S{1.0}); // R <- A*X-B _F.solve_least_square(Y);
_nb_mvp += X.get_nb_col(); X_plus_MVY(A, X, _base, Y); // X_n = X_0 + M*V*Y
} }
template<class Matrix, class Block> template<class Matrix, class Block>
...@@ -182,7 +185,7 @@ private: ...@@ -182,7 +185,7 @@ private:
W2 = W1_W2.sub_block(0, _nb_direction_kept, _nbRHS, _nb_direction_discarded); W2 = W1_W2.sub_block(0, _nb_direction_kept, _nbRHS, _nb_direction_discarded);
U1_2.OutOfPlaceQRFacto(W1_W2, R); // Qr facto of bottom block of U U1_2.OutOfPlaceQRFacto(W1_W2, R); // Qr facto of bottom block of U
L.update_phi(W1_W2, _nb_direction_kept); _F.update_phi(W1_W2, _nb_direction_kept);
// Update Phi with \W_1 and \W_2, doc Annexe Eq 2.7 // Update Phi with \W_1 and \W_2, doc Annexe Eq 2.7
Block V = _base.get_W(_nb_direction_kept); Block V = _base.get_W(_nb_direction_kept);
...@@ -192,7 +195,7 @@ private: ...@@ -192,7 +195,7 @@ private:
// L_{j+1,} = | \W_1^{H} | * H_j // L_{j+1,} = | \W_1^{H} | * H_j
// Gj = | \W_2^{H} | * H_j // Gj = | \W_2^{H} | * H_j
L.update_bottom_line(W1_W2); _F.update_bottom_line(W1_W2);
} }
void handle_IB_on_R0( Block<S> &U, BlockWP<S> &WP, void handle_IB_on_R0( Block<S> &U, BlockWP<S> &WP,
...@@ -235,17 +238,16 @@ private: ...@@ -235,17 +238,16 @@ private:
Lambda1.get_ptr(), Lambda1.get_leading_dim(), Lambda1.get_ptr(), Lambda1.get_leading_dim(),
S{1.0}, S{0.0} S{1.0}, S{0.0}
); );
L.init_lambda(Lambda1); _F.init_lambda(Lambda1);
L.init_phi(_nb_direction_kept); // Create and initialize Phi (\Phi_1) _F.init_phi(_nb_direction_kept); // Create and initialize Phi (\Phi_1)
} }
template< class Matrix, class Block, class BlockWP, template< class Matrix, class Block, class BlockWP, class Epsilon >
class Epsilon, class Hess >
std::tuple<P,P,bool> std::tuple<P,P,bool>
inexact_breakdown_on_R0( inexact_breakdown_on_R0(
const Matrix &A, Block &R0, const Matrix &A, Block &R0,
const Epsilon &epsilon, const Epsilon &inv_epsilon, const Epsilon &epsilon, const Epsilon &inv_epsilon,
Hess &L, BlockWP &WP) BlockWP &WP)
{ {
Block Q0 = R0; Block Q0 = R0;
Block Lambda0{_nbRHS, _nbRHS}; Block Lambda0{_nbRHS, _nbRHS};
...@@ -259,7 +261,7 @@ private: ...@@ -259,7 +261,7 @@ private:
_old_nb_direction_kept = _nb_direction_kept; _old_nb_direction_kept = _nb_direction_kept;
_nb_direction_discarded = _nbRHS - _nb_direction_kept; _nb_direction_discarded = _nbRHS - _nb_direction_kept;
// Test if needed to launch algorithm again // Test if algorithm need to be launched again
if (_nb_direction_kept == 0) { if (_nb_direction_kept == 0) {
_IB_happened = true; _IB_happened = true;
std::cout << "\t\tTOTAL INEXACT BREAKDOWN on R0\n"; std::cout << "\t\tTOTAL INEXACT BREAKDOWN on R0\n";
...@@ -277,7 +279,7 @@ private: ...@@ -277,7 +279,7 @@ private:
Block W = _base.get_W(_nbRHS); Block W = _base.get_W(_nbRHS);
W.copy(Q0); W.copy(Q0);
_base.increase(_nbRHS); _base.increase(_nbRHS);
L.init_lambda(Lambda0); _F.init_lambda(Lambda0);
} }
_block_size_sum.clear(); _block_size_sum.clear();
_block_size_sum.push_back(_nb_direction_kept); _block_size_sum.push_back(_nb_direction_kept);
...@@ -291,10 +293,10 @@ private: ...@@ -291,10 +293,10 @@ private:
const std::vector<P> &epsilon, const std::vector<P> &inv_epsilon, const std::vector<P> &epsilon, const std::vector<P> &inv_epsilon,
const Matrix &A, const Block<S> &X) const Matrix &A, const Block<S> &X)
{ {
Block<S> Y = L.alloc_least_square_sol(); Block<S> Y = _F.alloc_least_square_sol();
Block<S> PR{L.get_nb_hess_line(), _nbRHS}; Block<S> PR{_F.get_nb_hess_line(), _nbRHS};
L.solve_least_square(Y); _F.solve_least_square(Y);
L.compute_proj_residual(PR); _F.compute_proj_residual(PR);
Block<S> U; Block<S> U;
_nb_direction_kept = PR.decomposition_SVD(U, epsilon, inv_epsilon); _nb_direction_kept = PR.decomposition_SVD(U, epsilon, inv_epsilon);
...@@ -303,8 +305,8 @@ private: ...@@ -303,8 +305,8 @@ private:
if (_nb_direction_kept == 0) { // Suspicious ... if (_nb_direction_kept == 0) { // Suspicious ...
if (!proj_convergence) { // Even more suspicious if (!proj_convergence) { // Even more suspicious
FABULOUS_FATAL_ERROR( FABULOUS_FATAL_ERROR(
"Directions kepts during SVD of residuals is equal to 0, " "Directions kepts during SVD of projected residual is "
"but residual itself has not converged. " " equal to 0, but residual itself has not converged. "
"That should not be possible." "That should not be possible."
); );
} else { } else {
...@@ -335,13 +337,21 @@ private: ...@@ -335,13 +337,21 @@ private:
_size_krylov_space = _base.get_nb_vect(); _size_krylov_space = _base.get_nb_vect();
} }
std::tuple<P,P,bool>
check_least_square_residual(const std::vector<P> &epsilon)
{
_logger.notify_least_square_check_begin();
auto minmaxconv = _F.check_least_square_residual(epsilon);
_logger.notify_least_square_check_end();
return minmaxconv;
}
public: public:
template<class RestartParam> template<class RestartParam>
ArnoldiIB(Logger<P> &logger, Restarter<RestartParam, S> &restarter, ArnoldiIB(Logger<P> &logger, Restarter<RestartParam, S> &restarter,
int dim, int nbRHS, int max_krylov_space_size): int dim, int nbRHS, int max_krylov_space_size):
_logger(logger), _logger(logger),
L{max_krylov_space_size+1, nbRHS}, _F{max_krylov_space_size+1, nbRHS},
_solution_computed{false}, _solution_computed{false},
_base{restarter.get_base()}, _base{restarter.get_base()},
_dim(dim), _dim(dim),
...@@ -377,8 +387,8 @@ public: ...@@ -377,8 +387,8 @@ public:
* *
* \return whether the convergence was reached * \return whether the convergence was reached
*/ */
template< class Matrix, class Block, class Restarter > template< class Matrix, class Restarter >
bool run( Matrix &A, Block &X, Block &B, bool run( Matrix &A, Block<S> &X, Block<S> &B,
const int max_krylov_space_size, const int max_krylov_space_size,
const std::vector<P> &epsilon, const std::vector<P> &epsilon,
Restarter&, Restarter&,
...@@ -397,10 +407,10 @@ public: ...@@ -397,10 +407,10 @@ public:
_logger.notify_iteration_begin(_iteration_count, _size_krylov_space); _logger.notify_iteration_begin(_iteration_count, _size_krylov_space);
// STEP1: Compute first block residual // STEP1: Compute first block residual
Block R0{_dim, _nbRHS}; Block<S> R0{_dim, _nbRHS};
compute_real_residual(A, X, B, R0); compute_real_residual(A, X, B, R0);
// auto minmaxR0 = R0.get_min_max_norm(A); // auto minmaxR0 = R0.get_min_max_norm(A);
auto MinMaxConv = inexact_breakdown_on_R0(A, R0, epsilon, inv_epsilon, L, WP); auto MinMaxConv = inexact_breakdown_on_R0(A, R0, epsilon, inv_epsilon, WP);
_logger.notify_iteration_end( _logger.notify_iteration_end(
_iteration_count, _size_krylov_space, _nb_mvp, MinMaxConv); _iteration_count, _size_krylov_space, _nb_mvp, MinMaxConv);
...@@ -416,21 +426,23 @@ public: ...@@ -416,21 +426,23 @@ public:
_size_krylov_space < max_krylov_space_size) // Main Loop _size_krylov_space < max_krylov_space_size) // Main Loop
{ {
++ _iteration_count; ++ _iteration_count;
if (! L.check_room( WP.get_size_W()) ) if (! _F.check_room( WP.get_size_W()) )
break; break;
_logger.notify_iteration_begin(_iteration_count, _size_krylov_space); _logger.notify_iteration_begin(_iteration_count, _size_krylov_space);
Block Vj = _base.get_Vj(); Block<S> Vj = _base.get_Vj();
W_AMV(A, Vj, WP); // W <- A*M*Vj: perform matrix multiplication W_AMV(A, Vj, WP); // W <- A*M*Vj: perform matrix multiplication
// Ortho and filling of L (the (IB) Hessenberg) // Ortho and filling of L (the (IB) Hessenberg)
ortho.run(L, _base, WP, A); _logger.notify_ortho_begin();
ortho.run(_F, _base, WP, A);
_logger.notify_ortho_end();
// WP.check_ortho_WP();// WP.get_W().check_ortho(); // WP.check_ortho_WP();// WP.get_W().check_ortho();
//L.display_hess_extended_bitmap(); //_F.display_hess_extended_bitmap();
// Y is the solution of LeastSquare problem: Y = argmin(||F*Y-\Lambda||) // Y is the solution of LeastSquare problem: Y = argmin(||F*Y-\Lambda||)
// PR is the projected residual PR <- F*Y-\Lambda // PR is the projected residual PR <- F*Y-\Lambda
auto MinMaxConv = L.check_least_square_residual(epsilon); auto MinMaxConv = check_least_square_residual(epsilon);
bool proj_convergence = std::get<2>(MinMaxConv); bool proj_convergence = std::get<2>(MinMaxConv);
convergence = check_real_residual_if(proj_convergence, A, X, B, epsilon); convergence = check_real_residual_if(proj_convergence, A, X, B, epsilon);
...@@ -441,7 +453,7 @@ public: ...@@ -441,7 +453,7 @@ public:
_size_krylov_space = _base.get_nb_vect(); _size_krylov_space = _base.get_nb_vect();
_logger.notify_iteration_end( _logger.notify_iteration_end(
_iteration_count, _size_krylov_space, _nb_mvp, MinMaxConv); _iteration_count, _size_krylov_space, _nb_mvp, MinMaxConv);
_logger.log_real_residual(A, B, X, _base, L); _logger.log_real_residual(A, B, X, _base, _F);
} }
if (_solution_computed) if (_solution_computed)
...@@ -464,7 +476,6 @@ public: ...@@ -464,7 +476,6 @@ public:
} }
}; };
}; // namespace fabulous }; // namespace fabulous
#endif // FABULOUS_ARNOLDI_IB_HPP #endif // FABULOUS_ARNOLDI_IB_HPP
...@@ -179,7 +179,9 @@ public: ...@@ -179,7 +179,9 @@ public:
template<class HESS > template<class HESS >
int run(Block<S> &R1, HESS &hess) int run(Block<S> &R1, HESS &hess)
{ {
double tic = Timer::get_time(); Timer time;
time.start();
int p = _LS.get_nb_col(); int p = _LS.get_nb_col();
int nm = _base.get_nb_vect() - p; int nm = _base.get_nb_vect() - p;
int dim = _base.get_nb_row(); int dim = _base.get_nb_row();
...@@ -315,11 +317,10 @@ public: ...@@ -315,11 +317,10 @@ public:
hess.set_rhs(R1);// important to do this before orthogonalization end hess.set_rhs(R1);// important to do this before orthogonalization end
hess.notify_orthogonalization_end(); hess.notify_orthogonalization_end();
double tac = Timer::get_time(); time.stop();
std::cout<<"\tElapsed Time for Computing the Deflation at restart :: " double length = time.get_length();
<<tac-tic<<" seconds\n"; std::cout<<"\tElapsed Time for Computing the Deflation at restart: "<<length<<" seconds\n";
std::cout<<Color::bold<<Color::yellow; std::cout<<Color::bold<<Color::yellow<<"\t\tDR done\n"<<Color::reset;
std::cout<<"\t\tDR done\n"<<Color::reset;
return newK; return newK;
} }
}; };
......
...@@ -16,7 +16,8 @@ namespace fabulous { ...@@ -16,7 +16,8 @@ namespace fabulous {
* \brief Struct containing information about one iterations * \brief Struct containing information about one iterations
*/ */
template<class P> template<class P>
struct LogEntry { struct LogEntry
{
int glob_iteration; /*!< global iteration taking restart into account */ int glob_iteration; /*!< global iteration taking restart into account */
int loc_iteration; /*!< current iteration in arnoldi procedure */ int loc_iteration; /*!< current iteration in arnoldi procedure */
int krylov_space_size; /*!< Index of Current iteration*/ int krylov_space_size; /*!< Index of Current iteration*/
...@@ -26,13 +27,16 @@ struct LogEntry { ...@@ -26,13 +27,16 @@ struct LogEntry {
P max; /*!< Arnoldi Maximum norm reached at this iteration*/ P max; /*!< Arnoldi Maximum norm reached at this iteration*/
P minReal; /*!< Real Minimal norm reached at this iteration*/ P minReal; /*!< Real Minimal norm reached at this iteration*/
P maxReal; /*!< Real Maximum norm reached at this iteration*/ P maxReal; /*!< Real Maximum norm reached at this iteration*/
double timestamp; /*!< Time spent for this iteration */ double time_spent; /*!< Time spent for this iteration */
double least_square_spent; /*!< Time spent for this iteration in least_square */
double mvp_spent; /*!< Time spent for this iteration in mvp */
double ortho_spent; /*!< Time spent for this iteration in orthogonalization */
static void print_header(std::ostream &o = std::cout) static void print_header(std::ostream &o = std::cout)
{ {
o <<"global_iteration\tlocal_iteration\tkrylov_space_size\tnb_mvp\t" o <<"global_iteration\tlocal_iteration\tkrylov_space_size\tnb_mvp\t"
"current_block_size\tminRes\tmaxRes\tminRealRes\tmaxRealRes\ttime\tID\n"; "current_block_size\tminRes\tmaxRes\tminRealRes\tmaxRealRes\ttime\t"
"least_square_time\tmvp_spent\tortho_spent\tID\n";
} }
void print(std::string ID, std::ostream &o = std::cout) void print(std::string ID, std::ostream &o = std::cout)
...@@ -46,7 +50,10 @@ struct LogEntry { ...@@ -46,7 +50,10 @@ struct LogEntry {
<< max<<"\t" << max<<"\t"
<< minReal<<"\t" << minReal<<"\t"
<< maxReal<<"\t" << maxReal<<"\t"
<< timestamp<<"\t" << time_spent<<"\t"
<< least_square_spent<<"\t"
<< mvp_spent<<"\t"
<< ortho_spent<<"\t"
<< ID << "\n"; << ID << "\n";
} }
}; };
...@@ -55,24 +62,36 @@ struct LogEntry { ...@@ -55,24 +62,36 @@ struct LogEntry {
* \brief Class that will store informations during the solve at each * \brief Class that will store informations during the solve at each
* iteration. * iteration.
*/ */
template<class P, class Entry=LogEntry<P> > template<class P>
class Logger { class Logger
Timer _timer; {
using Entry = LogEntry<P>;
bool _started;
double _total_time;
Timer _global_timer;
Timer _iterations_timer;
Timer _least_square_timer;
Timer _mvp_timer;
Timer _ortho_timer;
bool _log_real_residual; bool _log_real_residual;
int _global_iteration; int _global_iteration;
int _total_mvp; int _total_mvp;
int _local_mvp; int _last_mvp;
std::vector<Entry> _iterations; std::vector<Entry> _iterations;
std::vector<double> _array; std::vector<double> _array;
double _last_timestamp;
public: public:
Logger(bool log_real_residual = false): Logger(bool log_real_residual = false):
_started{false},
_total_time{0.0},
_log_real_residual{log_real_residual}, _log_real_residual{log_real_residual},
_global_iteration{0}, _global_iteration{0},
_total_mvp{0}, _total_mvp{0},
_local_mvp{0} _last_mvp{0}
{ {
} }
...@@ -81,51 +100,109 @@ public: ...@@ -81,51 +100,109 @@ public:
void reset() void reset()
{ {
_started = false;
_global_timer.reset();
_iterations_timer.reset();
_least_square_timer.reset();
_mvp_timer.reset();
_ortho_timer.reset();
_iterations.clear(); _iterations.clear();
_array.clear(); _array.clear();
_global_iteration = 0; _global_iteration = 0;
_total_mvp = 0; _total_mvp = 0;
_local_mvp = 0; _last_mvp = 0;
} }
const Entry &get_entry(int i) const { return _iterations.at(i); } const Entry &get_entry(int i) const { return _iterations.at(i); }
const std::vector<Entry> &get_iterations() const { return _iterations; } const std::vector<Entry> &get_iterations() const { return _iterations; }
double get_total_time() const { return _total_time; }
/* -------------------- notify BEGIN --------------------------------------*/
void notify_iteration_begin(int iteration_count, int size_krylov_space) void notify_iteration_begin(int iteration_count, int size_krylov_space)
{ {
_last_timestamp = _timer.get_time(); _iterations_timer.reset();
_least_square_timer.reset();
_mvp_timer.reset();
_ortho_timer.reset();
std::cout<<"\nStart of Iteration [" std::cout<<"\nStart of Iteration ["
<<Color::note<<iteration_count<<" :: " <<Color::note<<iteration_count<<" :: "