diff options
author | Sebastien Boisvert <seb@boisvert.info> | 2020-06-11 23:43:25 +0000 |
---|---|---|
committer | Rasmus Munk Larsen <rmlarsen@google.com> | 2020-06-11 23:43:25 +0000 |
commit | 39cbd6578fbf3a98d8a213c8ec3f5147557d065e (patch) | |
tree | cc04e0117d47268dbbf3a79cd851a7bcf7d5b1f0 | |
parent | a7d2552af8b34f6befba9988c36fe5d9723892e6 (diff) |
Fix #1911: add benchmark for move semantics with fixed-size matrix
$ clang++ -O3 bench/bench_move_semantics.cpp -I. -std=c++11 \
-o bench_move_semantics
$ ./bench_move_semantics
float copy semantics: 1755.97 ms
float move semantics: 55.063 ms
double copy semantics: 2457.65 ms
double move semantics: 55.034 ms
-rw-r--r-- | Eigen/src/Core/DenseStorage.h | 12 | ||||
-rw-r--r-- | bench/bench_move_semantics.cpp | 57 | ||||
-rw-r--r-- | test/MovableScalar.h | 35 | ||||
-rw-r--r-- | test/rvalue_types.cpp | 39 |
4 files changed, 143 insertions, 0 deletions
diff --git a/Eigen/src/Core/DenseStorage.h b/Eigen/src/Core/DenseStorage.h index a8bb8a624..6966513b3 100644 --- a/Eigen/src/Core/DenseStorage.h +++ b/Eigen/src/Core/DenseStorage.h @@ -200,6 +200,18 @@ template<typename T, int Size, int _Rows, int _Cols, int _Options> class DenseSt if (this != &other) m_data = other.m_data; return *this; } +#if EIGEN_HAS_RVALUE_REFERENCES + EIGEN_DEVICE_FUNC DenseStorage(DenseStorage&& other) EIGEN_NOEXCEPT + : m_data(std::move(other.m_data)) + { + } + EIGEN_DEVICE_FUNC DenseStorage& operator=(DenseStorage&& other) EIGEN_NOEXCEPT + { + if (this != &other) + m_data = std::move(other.m_data); + return *this; + } +#endif EIGEN_DEVICE_FUNC DenseStorage(Index size, Index rows, Index cols) { EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({}) eigen_internal_assert(size==rows*cols && rows==_Rows && cols==_Cols); diff --git a/bench/bench_move_semantics.cpp b/bench/bench_move_semantics.cpp new file mode 100644 index 000000000..323d80417 --- /dev/null +++ b/bench/bench_move_semantics.cpp @@ -0,0 +1,57 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2020 Sebastien Boisvert <seb@boisvert.info> +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include "BenchTimer.h" +#include "../test/MovableScalar.h" + +#include <Eigen/Core> + +#include <iostream> +#include <utility> + +template <typename MatrixType> +void copy_matrix(MatrixType& m) +{ + MatrixType tmp(m); + m = tmp; +} + +template <typename MatrixType> +void move_matrix(MatrixType&& m) +{ + MatrixType tmp(std::move(m)); + m = std::move(tmp); +} + +template<typename Scalar> +void bench(const std::string& label) +{ + using MatrixType = Eigen::Matrix<Eigen::MovableScalar<Scalar>,1,10>; + Eigen::BenchTimer t; + + int tries = 10; + int rep = 1000000; + + MatrixType data = MatrixType::Random().eval(); + MatrixType dest; + + BENCH(t, tries, rep, copy_matrix(data)); + std::cout << label << " copy semantics: " << 1e3*t.best(Eigen::CPU_TIMER) << " ms" << std::endl; + + BENCH(t, tries, rep, move_matrix(std::move(data))); + std::cout << label << " move semantics: " << 1e3*t.best(Eigen::CPU_TIMER) << " ms" << std::endl; +} + +int main() +{ + bench<float>("float"); + bench<double>("double"); + return 0; +} + diff --git a/test/MovableScalar.h b/test/MovableScalar.h new file mode 100644 index 000000000..6a90d037a --- /dev/null +++ b/test/MovableScalar.h @@ -0,0 +1,35 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2020 Sebastien Boisvert <seb@boisvert.info> +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef EIGEN_MISC_MOVABLE_SCALAR_H +#define EIGEN_MISC_MOVABLE_SCALAR_H + +#include <vector> + +namespace Eigen +{ +template <typename Scalar, typename Base = std::vector<Scalar>> +struct MovableScalar : public Base +{ + MovableScalar() = default; + ~MovableScalar() = default; + MovableScalar(const MovableScalar&) = default; + MovableScalar(MovableScalar&& other) = default; + MovableScalar& operator=(const MovableScalar&) = default; + MovableScalar& operator=(MovableScalar&& other) = default; + MovableScalar(Scalar scalar) : Base(100, scalar) {} + + operator Scalar() const { return this->size() > 0 ? this->back() : Scalar(); } +}; + +template<> struct NumTraits<MovableScalar<float>> : GenericNumTraits<float> {}; +} + +#endif + diff --git a/test/rvalue_types.cpp b/test/rvalue_types.cpp index 1e1f8560a..2eef47d1f 100644 --- a/test/rvalue_types.cpp +++ b/test/rvalue_types.cpp @@ -10,6 +10,9 @@ #define EIGEN_RUNTIME_NO_MALLOC #include "main.h" +#if EIGEN_HAS_CXX11 +#include "MovableScalar.h" +#endif #include <Eigen/Core> @@ -75,11 +78,43 @@ void rvalue_transpositions(Index rows) Eigen::internal::set_is_malloc_allowed(true); } + +template <typename MatrixType> +void rvalue_move(const MatrixType& m) +{ + // lvalue reference is copied + MatrixType b(m); + VERIFY_IS_EQUAL(b, m); + + // lvalue reference is copied + MatrixType c{m}; + VERIFY_IS_EQUAL(c, m); + + // lvalue reference is copied + MatrixType d = m; + VERIFY_IS_EQUAL(d, m); + + // rvalue reference is moved + MatrixType e_src(m); + VERIFY_IS_EQUAL(e_src, m); + MatrixType e_dst(std::move(e_src)); + VERIFY_IS_EQUAL(e_src, MatrixType()); + VERIFY_IS_EQUAL(e_dst, m); + + // rvalue reference is moved + MatrixType f_src(m); + VERIFY_IS_EQUAL(f_src, m); + MatrixType f_dst = std::move(f_src); + VERIFY_IS_EQUAL(f_src, MatrixType()); + VERIFY_IS_EQUAL(f_dst, m); +} #else template <typename MatrixType> void rvalue_copyassign(const MatrixType&) {} template<typename TranspositionsType> void rvalue_transpositions(Index) {} +template <typename MatrixType> +void rvalue_move(const MatrixType&) {} #endif EIGEN_DECLARE_TEST(rvalue_types) @@ -106,5 +141,9 @@ EIGEN_DECLARE_TEST(rvalue_types) CALL_SUBTEST_3((rvalue_transpositions<PermutationMatrix<Dynamic, Dynamic, Index> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)))); CALL_SUBTEST_4((rvalue_transpositions<Transpositions<Dynamic, Dynamic, int> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)))); CALL_SUBTEST_4((rvalue_transpositions<Transpositions<Dynamic, Dynamic, Index> >(internal::random<int>(1,EIGEN_TEST_MAX_SIZE)))); + +#if EIGEN_HAS_CXX11 + CALL_SUBTEST_5(rvalue_move(Eigen::Matrix<MovableScalar<float>,1,3>::Random().eval())); +#endif } } |