Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
perfMatrixTranspose.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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
37
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 defined(VISP_HAVE_OPENCV) && (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
55using namespace VISP_NAMESPACE_NAME;
56#endif
57
58namespace
59{
60
61bool g_runBenchmark = false;
62int g_tileSize = 16;
63
64vpMatrix 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
77vpMatrix 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
90vpMatrix 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
106vpMatrix 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
122vpMatrix 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
139vpMatrix 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
178TEST_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 defined(VISP_HAVE_OPENCV) && (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
288int 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
305int main() { return EXIT_SUCCESS; }
306#endif
unsigned int getCols() const
Definition vpArray2D.h:423
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
unsigned int getRows() const
Definition vpArray2D.h:433
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
vpMatrix t() const