Commit 0abf67bc authored by MIJIEUX Thomas's avatar MIJIEUX Thomas

Instrument orthogonalization to measure flops

parent ebe4b169
...@@ -33,6 +33,7 @@ template<class> class Block; ...@@ -33,6 +33,7 @@ template<class> class Block;
#include "fabulous/kernel/blas.hpp" #include "fabulous/kernel/blas.hpp"
#include "fabulous/kernel/svd.hpp" #include "fabulous/kernel/svd.hpp"
#include "fabulous/kernel/flops.hpp"
namespace fabulous { namespace fabulous {
...@@ -42,6 +43,8 @@ namespace fabulous { ...@@ -42,6 +43,8 @@ namespace fabulous {
template<class S> template<class S>
class Block class Block
{ {
private:
mutable int64_t _last_flops;
protected: protected:
int _m; int _m;
int _n; int _n;
...@@ -80,7 +83,8 @@ public: ...@@ -80,7 +83,8 @@ public:
} }
Block(int m, int n, int ld, S *ptr): Block(int m, int n, int ld, S *ptr):
_m(m), _n(n), _ld(ld), _ptr(ptr) _last_flops{0},
_m{m}, _n{n}, _ld{ld}, _ptr{ptr}
{ {
assert( ld >= m ); assert( ld >= m );
assert( ld > 0 ); assert( ld > 0 );
...@@ -93,9 +97,10 @@ public: ...@@ -93,9 +97,10 @@ public:
} }
Block(int m, int n, int ld, S* ptr, SPtr sptr): Block(int m, int n, int ld, S* ptr, SPtr sptr):
_m(m), _n(n), _ld(ld), _last_flops{0},
_sptr(sptr), _m{m}, _n{n}, _ld{ld},
_ptr(ptr) _sptr{sptr},
_ptr{ptr}
{ {
assert( ld >= m ); assert( ld >= m );
assert( ld > 0 ); assert( ld > 0 );
...@@ -108,9 +113,10 @@ public: ...@@ -108,9 +113,10 @@ public:
} }
Block(int m, int n, int ld, SPtr sptr): Block(int m, int n, int ld, SPtr sptr):
_m(m), _n(n), _ld(ld), _last_flops{0},
_sptr(sptr), _m{m}, _n{n}, _ld{ld},
_ptr(_sptr.get()) _sptr{sptr},
_ptr{_sptr.get()}
{ {
assert( ld >= m ); assert( ld >= m );
assert( ld > 0 ); assert( ld > 0 );
...@@ -151,7 +157,7 @@ public: ...@@ -151,7 +157,7 @@ public:
{ {
const S *ptr = get_vect(k); const S *ptr = get_vect(k);
S res = S{0.0}; S res = S{0.0};
A.DotProduct(1, 1, ptr, _ld, ptr, _ld, &res, 1); _last_flops = A.DotProduct(1, 1, ptr, _ld, ptr, _ld, &res, 1);
return std::sqrt(fabulous::real(res)); return std::sqrt(fabulous::real(res));
} }
...@@ -162,6 +168,8 @@ public: ...@@ -162,6 +168,8 @@ public:
const S *ptr = get_vect(k); const S *ptr = get_vect(k);
S res = S{0.0}; S res = S{0.0};
lapacke::dot(_m, ptr, 1, ptr, 1, &res); lapacke::dot(_m, ptr, 1, ptr, 1, &res);
_last_flops = lapacke::dot_flops<S>(_m);
return std::sqrt(fabulous::real(res)); return std::sqrt(fabulous::real(res));
} }
...@@ -424,6 +432,15 @@ public: ...@@ -424,6 +432,15 @@ public:
return nb_krylov_direction; return nb_krylov_direction;
} }
/**
* \brief return number of flops performed by last operation
*/
int64_t get_last_flops() const
{
return _last_flops;
}
}; // end class Block }; // end class Block
template< class U > template< class U >
......
...@@ -6,6 +6,7 @@ template<class> class BlockWP; ...@@ -6,6 +6,7 @@ template<class> class BlockWP;
}; };
#include "fabulous/kernel/blas.hpp" #include "fabulous/kernel/blas.hpp"
#include "fabulous/kernel/flops.hpp"
#include "fabulous/data/Block.hpp" #include "fabulous/data/Block.hpp"
namespace fabulous { namespace fabulous {
...@@ -73,10 +74,11 @@ public: ...@@ -73,10 +74,11 @@ public:
* *
* \param[out] C the C block of the projected matrix to be filled * \param[out] C the C block of the projected matrix to be filled
*/ */
void compute_C(Block<S> &C) int64_t compute_C(Block<S> &C)
{ {
int64_t nb_flops = 0;
if (!_cursor) if (!_cursor)
return; return nb_flops;
lapacke::Tgemm( // C := P^{H} * \widetilde{W} lapacke::Tgemm( // C := P^{H} * \widetilde{W}
get_size_P(), get_size_W(), get_nb_row(), get_size_P(), get_size_W(), get_nb_row(),
...@@ -85,6 +87,8 @@ public: ...@@ -85,6 +87,8 @@ public:
C.get_ptr(), C.get_leading_dim(), C.get_ptr(), C.get_leading_dim(),
S{1.0}, S{0.0} S{1.0}, S{0.0}
); );
nb_flops += lapacke::Tgemm_flops<S>(get_size_P(), get_size_W(), get_nb_row());
lapacke::gemm( // ~W = ~W - P_j*C lapacke::gemm( // ~W = ~W - P_j*C
get_nb_row(), get_size_W(), get_size_P(), get_nb_row(), get_size_W(), get_size_P(),
get_P_ptr(), get_leading_dim(), get_P_ptr(), get_leading_dim(),
...@@ -92,6 +96,8 @@ public: ...@@ -92,6 +96,8 @@ public:
get_W_ptr(), get_leading_dim(), get_W_ptr(), get_leading_dim(),
S{-1.0}, S{1.0} S{-1.0}, S{1.0}
); );
nb_flops += lapacke::gemm_flops<S>(get_nb_row(), get_size_W(), get_size_P());
return nb_flops;
} }
/** /**
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "fabulous/utils/Utils.hpp" #include "fabulous/utils/Utils.hpp"
#include "fabulous/data/Block.hpp" #include "fabulous/data/Block.hpp"
#include "fabulous/kernel/qrf.hpp" #include "fabulous/kernel/qrf.hpp"
#include "fabulous/kernel/flops.hpp"
namespace fabulous { namespace fabulous {
...@@ -26,7 +27,7 @@ namespace qr { ...@@ -26,7 +27,7 @@ namespace qr {
* \note R MUST BE already allocated ( Q.get_nb_col() x Q.get_nb_col() ) * \note R MUST BE already allocated ( Q.get_nb_col() x Q.get_nb_col() )
*/ */
template<class S, class Matrix> template<class S, class Matrix>
void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A) int64_t InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A)
{ {
int M = Q.get_nb_row(); int M = Q.get_nb_row();
int N = Q.get_nb_col(); int N = Q.get_nb_col();
...@@ -34,17 +35,21 @@ void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A) ...@@ -34,17 +35,21 @@ void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A)
assert( R.get_nb_col() == Q.get_nb_col() ); assert( R.get_nb_col() == Q.get_nb_col() );
assert( R.get_nb_col() == R.get_nb_row() ); assert( R.get_nb_col() == R.get_nb_row() );
int64_t nb_flops = 0;
for (int j = 0; j < N; ++j) { for (int j = 0; j < N; ++j) {
for (int i = 0; i < j; ++i) { for (int i = 0; i < j; ++i) {
S dot; // dot = DOT(Q_i, Q_j) S dot; // dot = DOT(Q_i, Q_j)
A.DotProduct(1, 1, Q.get_vect(i), LD, Q.get_vect(j), LD, &dot, 1); nb_flops += A.DotProduct(1, 1, Q.get_vect(i), LD,
Q.get_vect(j), LD, &dot, 1);
// Qj = Qj - dot(Qj,Qi)*Qi // Qj = Qj - dot(Qj,Qi)*Qi
lapacke::axpy(M, -dot, Q.get_vect(i), 1, Q.get_vect(j), 1); lapacke::axpy(M, -dot, Q.get_vect(i), 1, Q.get_vect(j), 1);
nb_flops += lapacke::axpy_flops<S>(M);
R.at(i, j) = dot; R.at(i, j) = dot;
} }
auto norm = Q.get_norm(j, A); auto norm = Q.get_norm(j, A);
nb_flops += Q.get_last_flops();
R.at(j, j) = norm; R.at(j, j) = norm;
if (norm == 0.0) { if (norm == 0.0) {
#ifndef FABULOUS_IB_EXACT_BREAKDOWN_CONTINUE #ifndef FABULOUS_IB_EXACT_BREAKDOWN_CONTINUE
...@@ -55,8 +60,11 @@ void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A) ...@@ -55,8 +60,11 @@ void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A)
norm = 1.0; norm = 1.0;
#endif #endif
} }
lapacke::scal(M, S{1.0} / norm, Q.get_vect(j), 1); // Qj = (1/n)Qj lapacke::scal(M, S{1.0} / norm, Q.get_vect(j), 1);
nb_flops += lapacke::scal_flops<S>(M);
// Qj = (1/n)Qj
} }
return nb_flops;
} }
/** /**
...@@ -74,7 +82,7 @@ void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A) ...@@ -74,7 +82,7 @@ void InPlaceQRFactoMGS_User(Block<S> &Q, Block<S> &R, const Matrix &A)
* or the user passed a block of size (0x0) and R will no be computed * or the user passed a block of size (0x0) and R will no be computed
*/ */
template<class S> template<class S>
void InPlaceQRFacto(Block<S> &Q, Block<S> &R) int64_t InPlaceQRFacto(Block<S> &Q, Block<S> &R)
{ {
int M = Q.get_nb_row(); int M = Q.get_nb_row();
int N = Q.get_nb_col(); int N = Q.get_nb_col();
...@@ -87,21 +95,24 @@ void InPlaceQRFacto(Block<S> &Q, Block<S> &R) ...@@ -87,21 +95,24 @@ void InPlaceQRFacto(Block<S> &Q, Block<S> &R)
std::vector<S> tau; std::vector<S> tau;
lapacke::geqrf(M, N, Q.get_ptr(), LD, tau); lapacke::geqrf(M, N, Q.get_ptr(), LD, tau);
int64_t nb_flops = lapacke::geqrf_flops<S>(M, N);
if (R.get_nb_col() != 0) { if (R.get_nb_col() != 0) {
lapacke::lacpy( 'U', M, N, Q.get_ptr(), LD, lapacke::lacpy( 'U', M, N, Q.get_ptr(), LD,
R.get_ptr(), R.get_leading_dim()); R.get_ptr(), R.get_leading_dim());
} }
lapacke::orgqr(M, N, N, Q.get_ptr(), LD, tau.data()); lapacke::orgqr(M, N, N, Q.get_ptr(), LD, tau.data());
nb_flops += lapacke::orgqr_flops<S>(M, N, N);
return nb_flops;
} }
template<class S> template<class S>
void OutOfPlaceQRFacto(Block<S> &A, Block<S> &Q, Block<S> &R) int64_t OutOfPlaceQRFacto(Block<S> &A, Block<S> &Q, Block<S> &R)
{ {
assert( &Q != &A ); assert( &Q != &A );
assert( Q.get_ptr() != A.get_ptr() ); assert( Q.get_ptr() != A.get_ptr() );
Q.copy(A); Q.copy(A);
InPlaceQRFacto(Q, R); return InPlaceQRFacto(Q, R);
} }
}; // end namespace QR }; // end namespace QR
......
...@@ -20,10 +20,7 @@ void Tgemm(int m, int n, int k, ...@@ -20,10 +20,7 @@ void Tgemm(int m, int n, int k,
S *C, int ldc, S *C, int ldc,
S alpha = S{1.0}, S beta = S{0.0}) S alpha = S{1.0}, S beta = S{0.0})
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
} }
template<class S> template<class S>
...@@ -33,37 +30,25 @@ void gemm(int m, int n, int k, ...@@ -33,37 +30,25 @@ void gemm(int m, int n, int k,
S *C, int ldc, S *C, int ldc,
S alpha = S{1.0}, S beta = S{0.0}) S alpha = S{1.0}, S beta = S{0.0})
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
} }
template<class S> template<class S>
void scal(int N, S coef, S *X, int incX) void scal(int N, S coef, S *X, int incX)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
} }
template<class S> template<class S>
void axpy(int N, S coef, const S *X, int incX, S *Y, int incY) void axpy(int N, S coef, const S *X, int incX, S *Y, int incY)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
} }
template<class S> template<class S>
void dot(int N, const S *X, int incX, const S *Y, int incY, S *ret) void dot(int N, const S *X, int incX, const S *Y, int incY, S *ret)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
} }
/** /**
...@@ -81,20 +66,14 @@ void dot(int N, const S *X, int incX, const S *Y, int incY, S *ret) ...@@ -81,20 +66,14 @@ void dot(int N, const S *X, int incX, const S *Y, int incY, S *ret)
template<class S> template<class S>
int trsm(int m, int nrhs, const S *A, int lda, S *B, int ldb) int trsm(int m, int nrhs, const S *A, int lda, S *B, int ldb)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
template<class S> template<class S>
int lacpy(char uplo, int m, int n, S *A, int lda, S *B, int ldb) int lacpy(char uplo, int m, int n, S *A, int lda, S *B, int ldb)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
......
#ifndef FABULOUS_FLOPS_HPP
#define FABULOUS_FLOPS_HPP
#include <cstdint>
#include "fabulous/utils/Arithmetic.hpp"
namespace fabulous {
namespace lapacke {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
template<class S>
int64_t Tgemm_flops(int m, int n, int k)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
template<class S>
int64_t gemm_flops(int m, int n, int k)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
template<class S>
int64_t axpy_flops(int m)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
template<class S>
int64_t scal_flops(int m)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
template<class S>
int64_t dot_flops(int m)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
template<class S>
int64_t geqrf_flops(int m, int n)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
template<class S>
int64_t orgqr_flops(int m, int n, int k)
{
FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
return -1;
}
#pragma GCC diagnostic pop
};
};
#endif // FABULOUS_FLOPS_HPP
...@@ -27,10 +27,7 @@ namespace lapacke { ...@@ -27,10 +27,7 @@ namespace lapacke {
template<class S> template<class S>
int gels(int m, int n, int nrhs, S *A, int lda, S *B, int ldb) int gels(int m, int n, int nrhs, S *A, int lda, S *B, int ldb)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
......
...@@ -37,10 +37,7 @@ int ggev(int n, S *A, int lda, S *B, int ldb, ...@@ -37,10 +37,7 @@ int ggev(int n, S *A, int lda, S *B, int ldb,
S *vl, int ldvl , S *vl, int ldvl ,
S *vr, int ldvr) S *vr, int ldvr)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
......
...@@ -10,7 +10,6 @@ namespace lapacke { ...@@ -10,7 +10,6 @@ namespace lapacke {
/******************* BASIC QR FACTORIZATION ************************/ /******************* BASIC QR FACTORIZATION ************************/
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter" #pragma GCC diagnostic ignored "-Wunused-parameter"
...@@ -25,10 +24,7 @@ namespace lapacke { ...@@ -25,10 +24,7 @@ namespace lapacke {
template<class S> template<class S>
int geqrf(int m, int n, S *A, int lda, std::vector<S> &tau) int geqrf(int m, int n, S *A, int lda, std::vector<S> &tau)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return 1; return 1;
} }
...@@ -47,10 +43,7 @@ int geqrf(int m, int n, S *A, int lda, std::vector<S> &tau) ...@@ -47,10 +43,7 @@ int geqrf(int m, int n, S *A, int lda, std::vector<S> &tau)
template<class S> template<class S>
int orgqr(int m, int n, int p, S *A, int lda, S *tau) int orgqr(int m, int n, int p, S *A, int lda, S *tau)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
...@@ -78,10 +71,7 @@ template<class S> ...@@ -78,10 +71,7 @@ template<class S>
int ormqr(char trans, int m, int n, int k, int ormqr(char trans, int m, int n, int k,
const S *A, int lda, const S *tau, S *C, int ldc) const S *A, int lda, const S *tau, S *C, int ldc)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
......
...@@ -31,10 +31,7 @@ namespace lapacke { ...@@ -31,10 +31,7 @@ namespace lapacke {
template< class S > template< class S >
int tpqrt(int m, int n, int l, int nb, S *A, int lda, S *B, int ldb, Block<S> &T) int tpqrt(int m, int n, int l, int nb, S *A, int lda, S *B, int ldb, Block<S> &T)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
...@@ -66,10 +63,7 @@ int tpmqrt(char trans, int m, int n, int k, int l, int nb, ...@@ -66,10 +63,7 @@ int tpmqrt(char trans, int m, int n, int k, int l, int nb,
const Block<S> &T, S *A, int lda, S *B, int ldb) const Block<S> &T, S *A, int lda, S *B, int ldb)
{ {
static_assert( FABULOUS_DISABLE_INVALID_ARITHMETIC(S);
sizeof(S) != sizeof(S),
"support for float, double (real and complex) only"
);
return -1; return -1;
} }
......
...@@ -16,7 +16,7 @@ namespace fabulous { ...@@ -16,7 +16,7 @@ namespace fabulous {
/** /**
* \brief Orthogonalization methods for BLOCK variants WITHOUT Inexact Breakdown * \brief Orthogonalization methods for BLOCK variants WITHOUT Inexact Breakdown
*/ */
template< class HESS > template<class HESS>
class OrthogonalizerBlockSTD : public OrthogonalizerBlockCOMMON class OrthogonalizerBlockSTD : public OrthogonalizerBlockCOMMON
{ {
private: private:
...@@ -35,16 +35,17 @@ private: ...@@ -35,16 +35,17 @@ private:
* \param[in,out] W block to be orthogonalized against current base * \param[in,out] W block to be orthogonalized against current base
* \param ortho_scheme the orthogonalization scheme, * \param ortho_scheme the orthogonalization scheme,
*/ */
template< class S > template<class S>
void run(HESS &hess, Base<S> &base, Block<S> &W) int64_t run(HESS &hess, Base<S> &base, Block<S> &W)
{ {
hess.increase(W.get_nb_col()); hess.increase(W.get_nb_col());
Block<S> H = hess.get_H(); Block<S> H = hess.get_H();
Block<S> R = hess.get_R(); Block<S> R = hess.get_R();
dispatch(base, H, W); int64_t nb_flops = dispatch(base, H, W);
qr::InPlaceQRFacto(W, R); nb_flops += qr::InPlaceQRFacto(W, R);
return nb_flops;
} }
}; };
......
...@@ -16,7 +16,7 @@ namespace fabulous { ...@@ -16,7 +16,7 @@ namespace fabulous {
/** /**
* \brief Orthogonalization methods for BLOCK variants WITH Inexact Breakdown * \brief Orthogonalization methods for BLOCK variants WITH Inexact Breakdown
*/ */
template< class HESS > template<class HESS>
class OrthogonalizerBlockIB : public OrthogonalizerBlockCOMMON class OrthogonalizerBlockIB : public OrthogonalizerBlockCOMMON
{ {
private: private:
...@@ -36,7 +36,7 @@ private: ...@@ -36,7 +36,7 @@ private:
* \param ortho_scheme the orthogonalization scheme, * \param ortho_scheme the orthogonalization scheme,
*/ */
template<class S> template<class S>
void run(HESS &L, Base<S> &base, BlockWP<S> &WP) int64_t run(HESS &L, Base<S> &base, BlockWP<S> &WP)
{ {
L.increase(WP.get_size_W()); L.increase(WP.get_size_W());
...@@ -45,9 +45,10 @@ private: ...@@ -45,9 +45,10 @@ private:
Block<S> C = L.get_C(); // hessenberg's parts Block<S> C = L.get_C(); // hessenberg's parts
Block<S> W = WP.get_W(); // candidate part Block<S> W = WP.get_W(); // candidate part
dispatch(base, H, W); int64_t nb_flops = dispatch(base, H, W);
WP.compute_C(C); // Orthogonalisation of (candidate) W against P nb_flops += WP.compute_C(C); // Orthogonalisation of (candidate) W against P
qr::InPlaceQRFacto(W, D); nb_flops += qr::InPlaceQRFacto(W, D);
return nb_flops;
} }
}; // end class OrthogonalizerBlockIB }; // end class OrthogonalizerBlockIB
......
...@@ -10,6 +10,8 @@ class OrthogonalizerBlockCOMMON; ...@@ -10,6 +10,8 @@ class OrthogonalizerBlockCOMMON;
#include "fabulous/data/Base.hpp" #include "fabulous/data/Base.hpp"
#include "fabulous/data/Block.hpp" #include "fabulous/data/Block.hpp"
#include "fabulous/orthogonalization/OrthoParam.hpp" #include "fabulous/orthogonalization/OrthoParam.hpp"
#include "fabulous/kernel/blas.hpp"
#include "fabulous/kernel/flops.hpp"
namespace fabulous { namespace fabulous {
...@@ -18,9 +20,12 @@ namespace fabulous { ...@@ -18,9 +20,12 @@ namespace fabulous {
*/ */
class OrthogonalizerBlockCOMMON : public OrthoParam class OrthogonalizerBlockCOMMON : public OrthoParam
{