Visual Servoing Platform  version 3.6.1 under development (2024-12-17)
perfMatrixTranspose.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Benchmark matrix transpose.
32  */
33 
38 #include <visp3/core/vpConfig.h>
39 
40 #if defined(VISP_HAVE_CATCH2)
41 
42 #include <catch_amalgamated.hpp>
43 
44 #include <visp3/core/vpMatrix.h>
45 
46 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
47 #include <opencv2/core.hpp>
48 #endif
49 
50 #ifdef VISP_HAVE_EIGEN3
51 #include <Eigen/Dense>
52 #endif
53 
54 #ifdef ENABLE_VISP_NAMESPACE
55 using namespace VISP_NAMESPACE_NAME;
56 #endif
57 
58 namespace
59 {
60 
61 bool g_runBenchmark = false;
62 int g_tileSize = 16;
63 
64 vpMatrix generateMatrix(unsigned int sz1, unsigned int sz2)
65 {
66  vpMatrix M(sz1, sz2);
67 
68  for (unsigned int i = 0; i < M.getRows(); i++) {
69  for (unsigned int j = 0; j < M.getCols(); j++) {
70  M[i][j] = i * M.getCols() + j;
71  }
72  }
73 
74  return M;
75 }
76 
77 vpMatrix generateMatrixTranspose(unsigned int sz1, unsigned int sz2)
78 {
79  vpMatrix M(sz2, sz1);
80 
81  for (unsigned int j = 0; j < M.getCols(); j++) {
82  for (unsigned int i = 0; i < M.getRows(); i++) {
83  M[i][j] = j * M.getRows() + i;
84  }
85  }
86 
87  return M;
88 }
89 
90 vpMatrix transposeIterateSrc(const vpMatrix &A)
91 {
92  vpMatrix At;
93 
94  At.resize(A.getCols(), A.getRows(), false, false);
95 
96  for (unsigned int i = 0; i < A.getRows(); i++) {
97  double *coli = A[i];
98  for (unsigned int j = 0; j < A.getCols(); j++) {
99  At[j][i] = coli[j];
100  }
101  }
102 
103  return At;
104 }
105 
106 vpMatrix transposeIterateDst(const vpMatrix &A)
107 {
108  vpMatrix At;
109 
110  At.resize(A.getCols(), A.getRows(), false, false);
111 
112  for (unsigned int j = 0; j < A.getCols(); j++) {
113  double *coli = At[j];
114  for (unsigned int i = 0; i < A.getRows(); i++) {
115  coli[i] = A[i][j];
116  }
117  }
118 
119  return At;
120 }
121 
122 vpMatrix transposeTilingSO(const vpMatrix &A, unsigned int tileSize = 16)
123 {
124  vpMatrix At;
125 
126  At.resize(A.getCols(), A.getRows(), false, false);
127 
128  for (unsigned int i = 0; i < A.getRows(); i += tileSize) {
129  for (unsigned int j = 0; j < A.getCols(); j++) {
130  for (unsigned int b = 0; b < tileSize && i + b < A.getRows(); b++) {
131  At[j][i + b] = A[i + b][j];
132  }
133  }
134  }
135 
136  return At;
137 }
138 
139 vpMatrix transposeTiling(const vpMatrix &A, int tileSize = 16)
140 {
141  vpMatrix At;
142 
143  At.resize(A.getCols(), A.getRows(), false, false);
144 
145  const int nrows = static_cast<int>(A.getRows());
146  const int ncols = static_cast<int>(A.getCols());
147 
148  for (int i = 0; i < nrows;) {
149  for (; i <= nrows - tileSize; i += tileSize) {
150  int j = 0;
151  for (; j <= ncols - tileSize; j += tileSize) {
152  for (int k = i; k < i + tileSize; k++) {
153  for (int l = j; l < j + tileSize; l++) {
154  At[l][k] = A[k][l];
155  }
156  }
157  }
158 
159  for (int k = i; k < i + tileSize; k++) {
160  for (int l = j; l < ncols; l++) {
161  At[l][k] = A[k][l];
162  }
163  }
164  }
165 
166  for (; i < nrows; i++) {
167  for (int j = 0; j < ncols; j++) {
168  At[j][i] = A[i][j];
169  }
170  }
171  }
172 
173  return At;
174 }
175 
176 } // namespace
177 
178 TEST_CASE("Benchmark vpMatrix transpose", "[benchmark]")
179 {
180  if (g_runBenchmark) {
181  const std::vector<std::pair<int, int> > sizes = {
182  {701, 1503}, {1791, 837}, {1201, 1201}, {1024, 1024}, {2000, 2000}, {10, 6}, {25, 6}, {100, 6}, {200, 6},
183  {500, 6}, {1000, 6}, {1500, 6}, {2000, 6}, {6, 10}, {6, 25}, {6, 100}, {6, 200}, {6, 500},
184  {6, 1000}, {6, 1500}, {6, 2000}, {640, 1000}, {800, 640}, {640, 500}, {500, 640}, {640, 837} };
185 
186  for (auto sz : sizes) {
187  vpMatrix M = generateMatrix(sz.first, sz.second);
188  vpMatrix Mt_true = generateMatrixTranspose(sz.first, sz.second);
189 
190  std::ostringstream oss;
191  oss << sz.first << "x" << sz.second;
192  oss << " - M.t()";
193  BENCHMARK(oss.str().c_str())
194  {
195  vpMatrix Mt = M.t();
196  REQUIRE(Mt == Mt_true);
197  return Mt;
198  };
199 
200  oss.str("");
201  oss << sz.first << "x" << sz.second;
202  oss << " - transposeIterateSrc(M)";
203  BENCHMARK(oss.str().c_str())
204  {
205  vpMatrix Mt = transposeIterateSrc(M);
206  REQUIRE(Mt == Mt_true);
207  return Mt;
208  };
209 
210  oss.str("");
211  oss << sz.first << "x" << sz.second;
212  oss << " - transposeIterateDst(M)";
213  BENCHMARK(oss.str().c_str())
214  {
215  vpMatrix Mt = transposeIterateDst(M);
216  REQUIRE(Mt == Mt_true);
217  return Mt;
218  };
219 
220  oss.str("");
221  oss << sz.first << "x" << sz.second;
222  oss << " - transposeTilingSO(M, tileSize=" << g_tileSize << ")";
223  BENCHMARK(oss.str().c_str())
224  {
225  vpMatrix Mt = transposeTilingSO(M, g_tileSize);
226  REQUIRE(Mt == Mt_true);
227  return Mt;
228  };
229 
230  oss.str("");
231  oss << sz.first << "x" << sz.second;
232  oss << " - transposeTiling(M, tileSize=" << g_tileSize << ")";
233  BENCHMARK(oss.str().c_str())
234  {
235  vpMatrix Mt = transposeTiling(M, g_tileSize);
236  REQUIRE(Mt == Mt_true);
237  return Mt;
238  };
239 
240 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
241  cv::Mat matM(sz.first, sz.second, CV_64FC1);
242 
243  for (unsigned int i = 0; i < M.getRows(); i++) {
244  for (unsigned int j = 0; j < M.getCols(); j++) {
245  matM.at<double>(i, j) = M[i][j];
246  }
247  }
248 
249  oss.str("");
250  oss << sz.first << "x" << sz.second;
251  oss << " - OpenCV";
252  BENCHMARK(oss.str().c_str())
253  {
254  cv::Mat matMt = matM.t();
255  return matMt;
256  };
257 #endif
258 
259 #ifdef VISP_HAVE_EIGEN3
260  Eigen::MatrixXd eigenM(sz.first, sz.second);
261 
262  for (unsigned int i = 0; i < M.getRows(); i++) {
263  for (unsigned int j = 0; j < M.getCols(); j++) {
264  eigenM(i, j) = M[i][j];
265  }
266  }
267 
268  oss.str("");
269  oss << sz.first << "x" << sz.second;
270  oss << " - Eigen";
271  BENCHMARK(oss.str().c_str())
272  {
273  Eigen::MatrixXd eigenMt = eigenM.transpose();
274  return eigenMt;
275  };
276 #endif
277  }
278  }
279  else {
280  vpMatrix M = generateMatrix(11, 17);
281  vpMatrix Mt_true = generateMatrixTranspose(11, 17);
282 
283  vpMatrix Mt = M.t();
284  REQUIRE(Mt == Mt_true);
285  }
286 }
287 
288 int main(int argc, char *argv[])
289 {
290  Catch::Session session;
291  auto cli = session.cli()
292  | Catch::Clara::Opt(g_runBenchmark)["--benchmark"]("run benchmark?")
293  | Catch::Clara::Opt(g_tileSize, "tileSize")["--tileSize"]("Tile size?");
294 
295  session.cli(cli);
296  session.applyCommandLine(argc, argv);
297 
298  int numFailed = session.run();
299 
300  return numFailed;
301 }
302 #else
303 #include <iostream>
304 
305 int main() { return EXIT_SUCCESS; }
306 #endif
unsigned int getCols() const
Definition: vpArray2D.h:337
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:362
unsigned int getRows() const
Definition: vpArray2D.h:347
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
vpMatrix transpose() const
vpMatrix t() const