small_blas_gemv_benchmark.cc 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // Ceres Solver - A fast non-linear least squares minimizer
  2. // Copyright 2023 Google Inc. All rights reserved.
  3. // http://ceres-solver.org/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Google Inc. nor the names of its contributors may be
  14. // used to endorse or promote products derived from this software without
  15. // specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. // POSSIBILITY OF SUCH DAMAGE.
  28. //
  29. // Authors: sameeragarwal@google.com (Sameer Agarwal)
  30. #include "Eigen/Dense"
  31. #include "benchmark/benchmark.h"
  32. #include "ceres/small_blas.h"
  33. namespace ceres {
  34. // Benchmarking matrix-vector multiply routines and optimizing memory
  35. // access requires that we make sure that they are not just sitting in
  36. // the cache. So, as the benchmarking routine iterates, we need to
  37. // multiply new/different matrice and vectors. Allocating/creating
  38. // these objects in the benchmarking loop is too heavy duty, so we
  39. // create them before hand and cycle through them in the
  40. // benchmark. This class, given the size of the matrix creates such
  41. // matrix and vector objects for use in the benchmark.
  42. class MatrixVectorMultiplyData {
  43. public:
  44. MatrixVectorMultiplyData(int rows, int cols)
  45. : num_elements_(1000),
  46. rows_(rows),
  47. cols_(cols),
  48. a_(num_elements_ * rows, 1.001),
  49. b_(num_elements_ * rows * cols, 1.5),
  50. c_(num_elements_ * cols, 1.00003) {}
  51. int num_elements() const { return num_elements_; }
  52. double* GetA(int i) { return &a_[i * rows_]; }
  53. double* GetB(int i) { return &b_[i * rows_ * cols_]; }
  54. double* GetC(int i) { return &c_[i * cols_]; }
  55. private:
  56. const int num_elements_;
  57. const int rows_;
  58. const int cols_;
  59. std::vector<double> a_;
  60. std::vector<double> b_;
  61. std::vector<double> c_;
  62. };
  63. // Helper function to generate the various matrix sizes for which we
  64. // run the benchmark.
  65. static void MatrixSizeArguments(benchmark::internal::Benchmark* benchmark) {
  66. std::vector<int> rows = {1, 2, 3, 4, 6, 8};
  67. std::vector<int> cols = {1, 2, 3, 4, 8, 12, 15};
  68. for (int r : rows) {
  69. for (int c : cols) {
  70. benchmark->Args({r, c});
  71. }
  72. }
  73. }
  74. static void BM_MatrixVectorMultiply(benchmark::State& state) {
  75. const int rows = state.range(0);
  76. const int cols = state.range(1);
  77. MatrixVectorMultiplyData data(rows, cols);
  78. const int num_elements = data.num_elements();
  79. int iter = 0;
  80. for (auto _ : state) {
  81. // A += B * C;
  82. internal::MatrixVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
  83. data.GetB(iter), rows, cols, data.GetC(iter), data.GetA(iter));
  84. iter = (iter + 1) % num_elements;
  85. }
  86. }
  87. BENCHMARK(BM_MatrixVectorMultiply)->Apply(MatrixSizeArguments);
  88. static void BM_MatrixTransposeVectorMultiply(benchmark::State& state) {
  89. const int rows = state.range(0);
  90. const int cols = state.range(1);
  91. MatrixVectorMultiplyData data(cols, rows);
  92. const int num_elements = data.num_elements();
  93. int iter = 0;
  94. for (auto _ : state) {
  95. internal::MatrixTransposeVectorMultiply<Eigen::Dynamic, Eigen::Dynamic, 1>(
  96. data.GetB(iter), rows, cols, data.GetC(iter), data.GetA(iter));
  97. iter = (iter + 1) % num_elements;
  98. }
  99. }
  100. BENCHMARK(BM_MatrixTransposeVectorMultiply)->Apply(MatrixSizeArguments);
  101. } // namespace ceres
  102. BENCHMARK_MAIN();