aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Sebastien Boisvert <seb@boisvert.info>2020-06-11 23:43:25 +0000
committerGravatar Rasmus Munk Larsen <rmlarsen@google.com>2020-06-11 23:43:25 +0000
commit39cbd6578fbf3a98d8a213c8ec3f5147557d065e (patch)
treecc04e0117d47268dbbf3a79cd851a7bcf7d5b1f0
parenta7d2552af8b34f6befba9988c36fe5d9723892e6 (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.h12
-rw-r--r--bench/bench_move_semantics.cpp57
-rw-r--r--test/MovableScalar.h35
-rw-r--r--test/rvalue_types.cpp39
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
}
}