| |
| #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; |
| } |