Visual Servoing Platform version 3.5.0
perfMatrixTranspose.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2019 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 http://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
55bool g_runBenchmark = false;
56int g_tileSize = 16;
57
58vpMatrix generateMatrix(unsigned int sz1, unsigned int sz2)
59{
60 vpMatrix M(sz1, sz2);
61
62 for (unsigned int i = 0; i < M.getRows(); i++) {
63 for (unsigned int j = 0; j < M.getCols(); j++) {
64 M[i][j] = i * M.getCols() + j;
65 }
66 }
67
68 return M;
69}
70
71vpMatrix generateMatrixTranspose(unsigned int sz1, unsigned int sz2)
72{
73 vpMatrix M(sz2, sz1);
74
75 for (unsigned int j = 0; j < M.getCols(); j++) {
76 for (unsigned int i = 0; i < M.getRows(); i++) {
77 M[i][j] = j * M.getRows() + i;
78 }
79 }
80
81 return M;
82}
83
84vpMatrix transposeIterateSrc(const vpMatrix& A)
85{
86 vpMatrix At;
87
88 At.resize(A.getCols(), A.getRows(), false, false);
89
90 for (unsigned int i = 0; i < A.getRows(); i++) {
91 double *coli = A[i];
92 for (unsigned int j = 0; j < A.getCols(); j++) {
93 At[j][i] = coli[j];
94 }
95 }
96
97 return At;
98}
99
100vpMatrix transposeIterateDst(const vpMatrix& A)
101{
102 vpMatrix At;
103
104 At.resize(A.getCols(), A.getRows(), false, false);
105
106 for (unsigned int j = 0; j < A.getCols(); j++) {
107 double *coli = At[j];
108 for (unsigned int i = 0; i < A.getRows(); i++) {
109 coli[i] = A[i][j];
110 }
111 }
112
113 return At;
114}
115
116vpMatrix transposeTilingSO(const vpMatrix& A, unsigned int tileSize=16)
117{
118 vpMatrix At;
119
120 At.resize(A.getCols(), A.getRows(), false, false);
121
122 for (unsigned int i = 0; i < A.getRows(); i += tileSize) {
123 for (unsigned int j = 0; j < A.getCols(); j++) {
124 for (unsigned int b = 0; b < tileSize && i + b < A.getRows(); b++) {
125 At[j][i + b] = A[i + b][j];
126 }
127 }
128 }
129
130 return At;
131}
132
133vpMatrix transposeTiling(const vpMatrix& A, int tileSize = 16)
134{
135 vpMatrix At;
136
137 At.resize(A.getCols(), A.getRows(), false, false);
138
139 const int nrows = static_cast<int>(A.getRows());
140 const int ncols = static_cast<int>(A.getCols());
141
142 for (int i = 0; i < nrows;) {
143 for (; i <= nrows - tileSize; i += tileSize) {
144 int j = 0;
145 for (; j <= ncols - tileSize; j += tileSize) {
146 for (int k = i; k < i + tileSize; k++) {
147 for (int l = j; l < j + tileSize; l++) {
148 At[l][k] = A[k][l];
149 }
150 }
151 }
152
153 for (int k = i; k < i + tileSize; k++) {
154 for (int l = j; l < ncols; l++) {
155 At[l][k] = A[k][l];
156 }
157 }
158 }
159
160 for (; i < nrows; i++) {
161 for (int j = 0; j < ncols; j++) {
162 At[j][i] = A[i][j];
163 }
164 }
165 }
166
167 return At;
168}
169
170}
171
172TEST_CASE("Benchmark vpMatrix transpose", "[benchmark]") {
173 if (g_runBenchmark) {
174 const std::vector<std::pair<int, int>> sizes = { {701, 1503}, {1791, 837}, {1201, 1201}, {1024, 1024}, {2000, 2000},
175 {10, 6}, {25, 6}, {100, 6}, {200, 6}, {500, 6}, {1000, 6}, {1500, 6}, {2000, 6},
176 {6, 10}, {6, 25}, {6, 100}, {6, 200}, {6, 500}, {6, 1000}, {6, 1500}, {6, 2000},
177 {640, 1000}, {800, 640}, {640, 500}, {500, 640}, {640, 837}
178 };
179
180 for (auto sz : sizes) {
181 vpMatrix M = generateMatrix(sz.first, sz.second);
182 vpMatrix Mt_true = generateMatrixTranspose(sz.first, sz.second);
183
184 std::ostringstream oss;
185 oss << sz.first << "x" << sz.second;
186 oss << " - M.t()";
187 BENCHMARK(oss.str().c_str()) {
188 vpMatrix Mt = M.t();
189 REQUIRE(Mt == Mt_true);
190 return Mt;
191 };
192
193 oss.str("");
194 oss << sz.first << "x" << sz.second;
195 oss << " - transposeIterateSrc(M)";
196 BENCHMARK(oss.str().c_str()) {
197 vpMatrix Mt = transposeIterateSrc(M);
198 REQUIRE(Mt == Mt_true);
199 return Mt;
200 };
201
202 oss.str("");
203 oss << sz.first << "x" << sz.second;
204 oss << " - transposeIterateDst(M)";
205 BENCHMARK(oss.str().c_str()) {
206 vpMatrix Mt = transposeIterateDst(M);
207 REQUIRE(Mt == Mt_true);
208 return Mt;
209 };
210
211 oss.str("");
212 oss << sz.first << "x" << sz.second;
213 oss << " - transposeTilingSO(M, tileSize=" << g_tileSize << ")";
214 BENCHMARK(oss.str().c_str()) {
215 vpMatrix Mt = transposeTilingSO(M, g_tileSize);
216 REQUIRE(Mt == Mt_true);
217 return Mt;
218 };
219
220 oss.str("");
221 oss << sz.first << "x" << sz.second;
222 oss << " - transposeTiling(M, tileSize=" << g_tileSize << ")";
223 BENCHMARK(oss.str().c_str()) {
224 vpMatrix Mt = transposeTiling(M, g_tileSize);
225 REQUIRE(Mt == Mt_true);
226 return Mt;
227 };
228
229#if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
230 cv::Mat matM(sz.first, sz.second, CV_64FC1);
231
232 for (unsigned int i = 0; i < M.getRows(); i++) {
233 for (unsigned int j = 0; j < M.getCols(); j++) {
234 matM.at<double>(i, j) = M[i][j];
235 }
236 }
237
238 oss.str("");
239 oss << sz.first << "x" << sz.second;
240 oss << " - OpenCV";
241 BENCHMARK(oss.str().c_str()) {
242 cv::Mat matMt = matM.t();
243 return matMt;
244 };
245#endif
246
247#ifdef VISP_HAVE_EIGEN3
248 Eigen::MatrixXd eigenM(sz.first, sz.second);
249
250 for (unsigned int i = 0; i < M.getRows(); i++) {
251 for (unsigned int j = 0; j < M.getCols(); j++) {
252 eigenM(i, j) = M[i][j];
253 }
254 }
255
256 oss.str("");
257 oss << sz.first << "x" << sz.second;
258 oss << " - Eigen";
259 BENCHMARK(oss.str().c_str()) {
260 Eigen::MatrixXd eigenMt = eigenM.transpose();
261 return eigenMt;
262 };
263#endif
264 }
265 } else {
266 vpMatrix M = generateMatrix(11, 17);
267 vpMatrix Mt_true = generateMatrixTranspose(11, 17);
268
269 vpMatrix Mt = M.t();
270 REQUIRE(Mt == Mt_true);
271 }
272}
273
274int main(int argc, char *argv[])
275{
276 Catch::Session session; // There must be exactly one instance
277
278 // Build a new parser on top of Catch's
279 using namespace Catch::clara;
280 auto cli = session.cli() // Get Catch's composite command line parser
281 | Opt(g_runBenchmark) // bind variable to a new option, with a hint string
282 ["--benchmark"] // the option names it will respond to
283 ("run benchmark?") // description string for the help output
284 | Opt(g_tileSize, "tileSize")
285 ["--tileSize"]
286 ("Tile size?");
287
288 // Now pass the new composite back to Catch so it uses that
289 session.cli(cli);
290
291 // Let Catch (using Clara) parse the command line
292 session.applyCommandLine(argc, argv);
293
294 int numFailed = session.run();
295
296 // numFailed is clamped to 255 as some unices only use the lower 8 bits.
297 // This clamping has already been applied, so just return it here
298 // You can also do any post run clean-up here
299 return numFailed;
300}
301#else
302#include <iostream>
303
304int main()
305{
306 return 0;
307}
308#endif
unsigned int getCols() const
Definition: vpArray2D.h:279
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition: vpArray2D.h:304
unsigned int getRows() const
Definition: vpArray2D.h:289
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:154
vpMatrix t() const
Definition: vpMatrix.cpp:464
vpMatrix transpose() const
Definition: vpMatrix.cpp:474