36 #include <visp3/core/vpConfig.h> 38 #ifdef VISP_HAVE_CATCH2 39 #define CATCH_CONFIG_ENABLE_BENCHMARKING 40 #define CATCH_CONFIG_RUNNER 43 #include <visp3/core/vpMatrix.h> 45 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) 46 #include <opencv2/core.hpp> 49 #ifdef VISP_HAVE_EIGEN3 50 #include <Eigen/Dense> 56 bool runBenchmark =
false;
58 double getRandomValues(
double min,
double max)
60 return (max - min) * ((double)rand() / (double)RAND_MAX) + min;
63 vpMatrix generateRandomMatrix(
unsigned int rows,
unsigned int cols,
double min=-1,
double max=1)
67 for (
unsigned int i = 0; i < M.getRows(); i++) {
68 for (
unsigned int j = 0; j < M.getCols(); j++) {
69 M[i][j] = getRandomValues(min, max);
76 vpColVector generateRandomVector(
unsigned int rows,
double min=-1,
double max=1)
80 for (
unsigned int i = 0; i < v.getRows(); i++) {
81 v[i] = getRandomValues(min, max);
102 unsigned int BcolNum = B.
getCols();
103 unsigned int BrowNum = B.
getRows();
104 unsigned int i, j, k;
105 for (i = 0; i < A.
getRows(); i++) {
106 double *rowptri = A[i];
108 for (j = 0; j < BcolNum; j++) {
110 for (k = 0; k < BrowNum; k++) {
111 s += rowptri[k] * B[k][j];
126 unsigned int i, j, k;
129 for (i = 0; i < A.
getCols(); i++) {
131 for (j = 0; j < i; j++) {
134 for (k = 0; k < A.
getRows(); k++) {
135 s += (*(ptr + i)) * (*(ptr + j));
143 for (k = 0; k < A.
getRows(); k++) {
144 s += (*(ptr + i)) * (*(ptr + i));
165 for (
unsigned int j = 0; j < A.
getCols(); j++) {
167 for (
unsigned int i = 0; i < A.
getRows(); i++) {
168 w[i] += A[i][j] * vj;
187 unsigned int VcolNum = V.
getCols();
188 unsigned int VrowNum = V.
getRows();
190 for (
unsigned int i = 0; i < A.
getRows(); i++) {
191 double *rowptri = A[i];
193 for (
unsigned int j = 0; j < VcolNum; j++) {
195 for (
unsigned int k = 0; k < VrowNum; k++)
196 s += rowptri[k] * V[k][j];
210 for (
unsigned int i = 0; i < A.
getRows(); i++) {
211 for (
unsigned int j = 0; j < A.
getCols(); j++) {
223 TEST_CASE(
"Benchmark matrix-matrix multiplication",
"[benchmark]") {
225 std::vector<std::pair<int, int>> sizes = { {6, 200}, {200, 6}, {207, 119}, {83, 201}, {600, 400}, {400, 600} };
227 for (
auto sz : sizes) {
228 vpMatrix A = generateRandomMatrix(sz.first, sz.second);
229 vpMatrix B = generateRandomMatrix(sz.second, sz.first);
231 std::ostringstream oss;
233 BENCHMARK(oss.str().c_str()) {
240 BENCHMARK(oss.str().c_str()) {
245 vpMatrix C_true = dgemm_regular(A, B);
247 REQUIRE(equalMatrix(C, C_true));
250 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) 251 cv::Mat matA(sz.first, sz.second, CV_64FC1);
252 cv::Mat matB(sz.second, sz.first, CV_64FC1);
254 for (
unsigned int i = 0; i < A.
getRows(); i++) {
255 for (
unsigned int j = 0; j < A.
getCols(); j++) {
256 matA.at<
double>(i, j) = A[i][j];
257 matB.at<
double>(j, i) = B[j][i];
262 oss <<
"(" << matA.rows <<
"x" << matA.cols <<
")x(" << matB.rows <<
"x" << matB.cols <<
") - OpenCV";
263 BENCHMARK(oss.str().c_str()) {
264 cv::Mat matC = matA * matB;
269 #ifdef VISP_HAVE_EIGEN3 270 Eigen::MatrixXd eigenA(sz.first, sz.second);
271 Eigen::MatrixXd eigenB(sz.second, sz.first);
273 for (
unsigned int i = 0; i < A.
getRows(); i++) {
274 for (
unsigned int j = 0; j < A.
getCols(); j++) {
275 eigenA(i, j) = A[i][j];
276 eigenB(j, i) = B[j][i];
281 oss <<
"(" << eigenA.rows() <<
"x" << eigenA.cols() <<
")x(" << eigenB.rows() <<
"x" << eigenB.cols() <<
") - Eigen";
282 BENCHMARK(oss.str().c_str()) {
283 Eigen::MatrixXd eigenC = eigenA * eigenB;
291 const unsigned int rows = 47, cols = 63;
292 vpMatrix A = generateRandomMatrix(rows, cols);
293 vpMatrix B = generateRandomMatrix(cols, rows);
295 vpMatrix C_true = dgemm_regular(A, B);
297 REQUIRE(equalMatrix(C, C_true));
301 TEST_CASE(
"Benchmark matrix-vector multiplication",
"[benchmark]") {
303 std::vector<std::pair<int, int>> sizes = { {6, 200}, {200, 6}, {207, 119}, {83, 201}, {600, 400}, {400, 600} };
305 for (
auto sz : sizes) {
306 vpMatrix A = generateRandomMatrix(sz.first, sz.second);
309 std::ostringstream oss;
311 BENCHMARK(oss.str().c_str()) {
318 BENCHMARK(oss.str().c_str()) {
325 REQUIRE(equalMatrix(C, C_true));
328 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) 329 cv::Mat matA(sz.first, sz.second, CV_64FC1);
330 cv::Mat matB(sz.second, 1, CV_64FC1);
332 for (
unsigned int i = 0; i < A.
getRows(); i++) {
333 for (
unsigned int j = 0; j < A.
getCols(); j++) {
334 matA.at<
double>(i, j) = A[i][j];
336 matB.at<
double>(j, 0) = B[j];
342 oss <<
"(" << matA.rows <<
"x" << matA.cols <<
")x(" << matB.rows <<
"x" << matB.cols <<
") - OpenCV";
343 BENCHMARK(oss.str().c_str()) {
344 cv::Mat matC = matA * matB;
349 #ifdef VISP_HAVE_EIGEN3 350 Eigen::MatrixXd eigenA(sz.first, sz.second);
351 Eigen::MatrixXd eigenB(sz.second, 1);
353 for (
unsigned int i = 0; i < A.
getRows(); i++) {
354 for (
unsigned int j = 0; j < A.
getCols(); j++) {
355 eigenA(i, j) = A[i][j];
363 oss <<
"(" << eigenA.rows() <<
"x" << eigenA.cols() <<
")x(" << eigenB.rows() <<
"x" << eigenB.cols() <<
") - Eigen";
364 BENCHMARK(oss.str().c_str()) {
365 Eigen::MatrixXd eigenC = eigenA * eigenB;
373 const unsigned int rows = 47, cols = 63;
374 vpMatrix A = generateRandomMatrix(rows, cols);
379 REQUIRE(equalMatrix(C, C_true));
383 TEST_CASE(
"Benchmark AtA",
"[benchmark]") {
385 std::vector<std::pair<int, int>> sizes = { {6, 200}, {200, 6}, {207, 119}, {83, 201}, {600, 400}, {400, 600} };
387 for (
auto sz : sizes) {
388 vpMatrix A = generateRandomMatrix(sz.first, sz.second);
390 std::ostringstream oss;
391 oss <<
"(" << A.
getRows() <<
"x" << A.
getCols() <<
") - Naive code";
392 BENCHMARK(oss.str().c_str()) {
399 BENCHMARK(oss.str().c_str()) {
406 REQUIRE(equalMatrix(AtA, AtA_true));
409 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) 410 cv::Mat matA(sz.first, sz.second, CV_64FC1);
412 for (
unsigned int i = 0; i < A.
getRows(); i++) {
413 for (
unsigned int j = 0; j < A.
getCols(); j++) {
414 matA.at<
double>(i, j) = A[i][j];
419 oss <<
"(" << matA.rows <<
"x" << matA.cols <<
") - OpenCV";
420 BENCHMARK(oss.str().c_str()) {
421 cv::Mat matAtA = matA.
t() * matA;
426 #ifdef VISP_HAVE_EIGEN3 427 Eigen::MatrixXd eigenA(sz.first, sz.second);
429 for (
unsigned int i = 0; i < A.
getRows(); i++) {
430 for (
unsigned int j = 0; j < A.
getCols(); j++) {
431 eigenA(i, j) = A[i][j];
436 oss <<
"(" << eigenA.rows() <<
"x" << eigenA.cols() <<
") - Eigen";
437 BENCHMARK(oss.str().c_str()) {
438 Eigen::MatrixXd eigenAtA = eigenA.
transpose() * eigenA;
446 const unsigned int rows = 47, cols = 63;
447 vpMatrix A = generateRandomMatrix(rows, cols);
451 REQUIRE(equalMatrix(AtA, AtA_true));
455 TEST_CASE(
"Benchmark matrix-velocity twist multiplication",
"[benchmark]") {
457 std::vector<std::pair<int, int>> sizes = { {20, 6}, {207, 6}, {600, 6}, {1201, 6} };
459 for (
auto sz : sizes) {
460 vpMatrix A = generateRandomMatrix(sz.first, sz.second);
463 std::ostringstream oss;
464 oss <<
"(" << A.
getRows() <<
"x" << A.
getCols() <<
")x(6x6) - Naive code";
465 BENCHMARK(oss.str().c_str()) {
466 vpMatrix AV = mat_mul_twist_matrix(A, V);
471 oss <<
"(" << A.
getRows() <<
"x" << A.
getCols() <<
")x(6x6) - ViSP";
472 BENCHMARK(oss.str().c_str()) {
477 vpMatrix AV_true = mat_mul_twist_matrix(A, V);
479 REQUIRE(equalMatrix(AV, AV_true));
482 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000) 483 cv::Mat matA(sz.first, sz.second, CV_64FC1);
484 cv::Mat matV(6, 6, CV_64FC1);
486 for (
unsigned int i = 0; i < A.
getRows(); i++) {
487 for (
unsigned int j = 0; j < A.
getCols(); j++) {
488 matA.at<
double>(i, j) = A[i][j];
491 for (
unsigned int i = 0; i < V.getRows(); i++) {
492 for (
unsigned int j = 0; j < V.getCols(); j++) {
493 matV.at<
double>(i, j) = V[i][j];
498 oss <<
"(" << matA.rows <<
"x" << matA.cols <<
")x(6x6) - OpenCV";
499 BENCHMARK(oss.str().c_str()) {
500 cv::Mat matAV = matA * matV;
505 #ifdef VISP_HAVE_EIGEN3 506 Eigen::MatrixXd eigenA(sz.first, sz.second);
507 Eigen::MatrixXd eigenV(6, 6);
509 for (
unsigned int i = 0; i < A.
getRows(); i++) {
510 for (
unsigned int j = 0; j < A.
getCols(); j++) {
511 eigenA(i, j) = A[i][j];
514 for (
unsigned int i = 0; i < V.getRows(); i++) {
515 for (
unsigned int j = 0; j < V.getCols(); j++) {
516 eigenV(i, j) = V[i][j];
521 oss <<
"(" << eigenA.rows() <<
"x" << eigenA.cols() <<
")x(6x6) - Eigen";
522 BENCHMARK(oss.str().c_str()) {
523 Eigen::MatrixXd eigenAV = eigenA * eigenV;
531 const unsigned int rows = 47, cols = 6;
532 vpMatrix A = generateRandomMatrix(rows, cols);
535 vpMatrix AV_true = mat_mul_twist_matrix(A, V);
537 REQUIRE(equalMatrix(AV, AV_true));
541 int main(
int argc,
char *argv[])
543 Catch::Session session;
546 using namespace Catch::clara;
547 auto cli = session.cli()
556 session.applyCommandLine(argc, argv);
558 int numFailed = session.run();
Implementation of a matrix and operations on matrices.
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
static bool equal(double x, double y, double s=0.001)
error that can be emited by ViSP classes.
unsigned int getRows() const
Type * data
Address of the first element of the data array.
unsigned int getCols() const
vpMatrix transpose() const
void resize(unsigned int i, bool flagNullify=true)
Implementation of column vector and the associated operations.
Class that consider the case of a translation vector.
Implementation of a rotation vector as axis-angle minimal representation.