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