|  |  | 
|  | #include <iostream> | 
|  | #include <Eigen/Core> | 
|  | #include <bench/BenchTimer.h> | 
|  |  | 
|  | using namespace Eigen; | 
|  | using namespace std; | 
|  |  | 
|  | #define END 9 | 
|  |  | 
|  | template <int S> | 
|  | struct map_size { | 
|  | enum { ret = S }; | 
|  | }; | 
|  | template <> | 
|  | struct map_size<10> { | 
|  | enum { ret = 20 }; | 
|  | }; | 
|  | template <> | 
|  | struct map_size<11> { | 
|  | enum { ret = 50 }; | 
|  | }; | 
|  | template <> | 
|  | struct map_size<12> { | 
|  | enum { ret = 100 }; | 
|  | }; | 
|  | template <> | 
|  | struct map_size<13> { | 
|  | enum { ret = 300 }; | 
|  | }; | 
|  |  | 
|  | template <int M, int N, int K> | 
|  | struct alt_prod { | 
|  | enum { | 
|  | ret = M == 1 && N == 1 ? InnerProduct | 
|  | : K == 1         ? OuterProduct | 
|  | : M == 1         ? GemvProduct | 
|  | : N == 1         ? GemvProduct | 
|  | : GemmProduct | 
|  | }; | 
|  | }; | 
|  |  | 
|  | void print_mode(int mode) { | 
|  | if (mode == InnerProduct) std::cout << "i"; | 
|  | if (mode == OuterProduct) std::cout << "o"; | 
|  | if (mode == CoeffBasedProductMode) std::cout << "c"; | 
|  | if (mode == LazyCoeffBasedProductMode) std::cout << "l"; | 
|  | if (mode == GemvProduct) std::cout << "v"; | 
|  | if (mode == GemmProduct) std::cout << "m"; | 
|  | } | 
|  |  | 
|  | template <int Mode, typename Lhs, typename Rhs, typename Res> | 
|  | EIGEN_DONT_INLINE void prod(const Lhs& a, const Rhs& b, Res& c) { | 
|  | c.noalias() += typename ProductReturnType<Lhs, Rhs, Mode>::Type(a, b); | 
|  | } | 
|  |  | 
|  | template <int M, int N, int K, typename Scalar, int Mode> | 
|  | EIGEN_DONT_INLINE void bench_prod() { | 
|  | typedef Matrix<Scalar, M, K> Lhs; | 
|  | Lhs a; | 
|  | a.setRandom(); | 
|  | typedef Matrix<Scalar, K, N> Rhs; | 
|  | Rhs b; | 
|  | b.setRandom(); | 
|  | typedef Matrix<Scalar, M, N> Res; | 
|  | Res c; | 
|  | c.setRandom(); | 
|  |  | 
|  | BenchTimer t; | 
|  | double n = 2. * double(M) * double(N) * double(K); | 
|  | int rep = 100000. / n; | 
|  | rep /= 2; | 
|  | if (rep < 1) rep = 1; | 
|  | do { | 
|  | rep *= 2; | 
|  | t.reset(); | 
|  | BENCH(t, 1, rep, prod<CoeffBasedProductMode>(a, b, c)); | 
|  | } while (t.best() < 0.1); | 
|  |  | 
|  | t.reset(); | 
|  | BENCH(t, 5, rep, prod<Mode>(a, b, c)); | 
|  |  | 
|  | print_mode(Mode); | 
|  | std::cout << int(1e-6 * n * rep / t.best()) << "\t"; | 
|  | } | 
|  |  | 
|  | template <int N> | 
|  | struct print_n; | 
|  | template <int M, int N, int K> | 
|  | struct loop_on_m; | 
|  | template <int M, int N, int K, typename Scalar, int Mode> | 
|  | struct loop_on_n; | 
|  |  | 
|  | template <int M, int N, int K> | 
|  | struct loop_on_k { | 
|  | static void run() { | 
|  | std::cout << "K=" << K << "\t"; | 
|  | print_n<N>::run(); | 
|  | std::cout << "\n"; | 
|  |  | 
|  | loop_on_m<M, N, K>::run(); | 
|  | std::cout << "\n\n"; | 
|  |  | 
|  | loop_on_k<M, N, K + 1>::run(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <int M, int N> | 
|  | struct loop_on_k<M, N, END> { | 
|  | static void run() {} | 
|  | }; | 
|  |  | 
|  | template <int M, int N, int K> | 
|  | struct loop_on_m { | 
|  | static void run() { | 
|  | std::cout << M << "f\t"; | 
|  | loop_on_n<M, N, K, float, CoeffBasedProductMode>::run(); | 
|  | std::cout << "\n"; | 
|  |  | 
|  | std::cout << M << "f\t"; | 
|  | loop_on_n<M, N, K, float, -1>::run(); | 
|  | std::cout << "\n"; | 
|  |  | 
|  | loop_on_m<M + 1, N, K>::run(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <int N, int K> | 
|  | struct loop_on_m<END, N, K> { | 
|  | static void run() {} | 
|  | }; | 
|  |  | 
|  | template <int M, int N, int K, typename Scalar, int Mode> | 
|  | struct loop_on_n { | 
|  | static void run() { | 
|  | bench_prod<M, N, K, Scalar, Mode == -1 ? alt_prod<M, N, K>::ret : Mode>(); | 
|  |  | 
|  | loop_on_n<M, N + 1, K, Scalar, Mode>::run(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <int M, int K, typename Scalar, int Mode> | 
|  | struct loop_on_n<M, END, K, Scalar, Mode> { | 
|  | static void run() {} | 
|  | }; | 
|  |  | 
|  | template <int N> | 
|  | struct print_n { | 
|  | static void run() { | 
|  | std::cout << map_size<N>::ret << "\t"; | 
|  | print_n<N + 1>::run(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | struct print_n<END> { | 
|  | static void run() {} | 
|  | }; | 
|  |  | 
|  | int main() { | 
|  | loop_on_k<1, 1, 1>::run(); | 
|  |  | 
|  | return 0; | 
|  | } |