From 4376306e471c4a77991c89b2f9874bc6a65feb83 Mon Sep 17 00:00:00 2001 From: Ben Cumming <bcumming@cscs.ch> Date: Tue, 23 Aug 2016 11:34:08 +0200 Subject: [PATCH] Support for multi-threaded sort * `nest::mc::threading::sort` is analogous to `std::sort` * when using TBB the `tbb::parallel_sort` is used * otherwise `std::sort` is used * used to parallelise connection construction during setup * now all initialization and simulation is multi-threaded * added a unit test --- src/communication/communicator.hpp | 2 +- src/threading/serial.hpp | 16 +++++++++++++++- src/threading/tbb.hpp | 15 +++++++++++++++ tests/unit/test_algorithms.cpp | 22 ++++++++++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/communication/communicator.hpp b/src/communication/communicator.hpp index c2036d91..802d94f9 100644 --- a/src/communication/communicator.hpp +++ b/src/communication/communicator.hpp @@ -69,7 +69,7 @@ public: /// must be called after all connections have been added void construct() { if (!std::is_sorted(connections_.begin(), connections_.end())) { - std::sort(connections_.begin(), connections_.end()); + threading::sort(connections_); } } diff --git a/src/threading/serial.hpp b/src/threading/serial.hpp index da2740a6..d3205817 100644 --- a/src/threading/serial.hpp +++ b/src/threading/serial.hpp @@ -62,10 +62,24 @@ struct parallel_for { } }; +template <typename RandomIt> +void sort(RandomIt begin, RandomIt end) { + std::sort(begin, end); +} + +template <typename RandomIt, typename Compare> +void sort(RandomIt begin, RandomIt end, Compare comp) { + std::sort(begin, end, comp); +} + +template <typename Container> +void sort(Container& c) { + std::sort(c.begin(), c.end()); +} + template <typename T> using parallel_vector = std::vector<T>; - inline std::string description() { return "serial"; } diff --git a/src/threading/tbb.hpp b/src/threading/tbb.hpp index 853ceefd..91a7b59b 100644 --- a/src/threading/tbb.hpp +++ b/src/threading/tbb.hpp @@ -51,6 +51,21 @@ using parallel_vector = tbb::concurrent_vector<T>; using task_group = tbb::task_group; +template <typename RandomIt> +void sort(RandomIt begin, RandomIt end) { + tbb::parallel_sort(begin, end); +} + +template <typename RandomIt, typename Compare> +void sort(RandomIt begin, RandomIt end, Compare comp) { + tbb::parallel_sort(begin, end, comp); +} + +template <typename Container> +void sort(Container& c) { + tbb::parallel_sort(c.begin(), c.end()); +} + } // threading } // mc } // nest diff --git a/tests/unit/test_algorithms.cpp b/tests/unit/test_algorithms.cpp index b371b9d6..9d370dda 100644 --- a/tests/unit/test_algorithms.cpp +++ b/tests/unit/test_algorithms.cpp @@ -6,6 +6,28 @@ #include "../test_util.hpp" #include "util/debug.hpp" +/// tests the sort implementation in threading +/// is only parallel if TBB is being used +TEST(algorithms, parallel_sort) +{ + auto n = 10000; + std::vector<int> v(n); + std::iota(v.begin(), v.end(), 1); + + std::random_device rd; + std::shuffle(v.begin(), v.end(), std::mt19937(rd())); + + // assert that the original vector has in fact been permuted + EXPECT_FALSE(std::is_sorted(v.begin(), v.end())); + + nest::mc::threading::sort(v); + + EXPECT_TRUE(std::is_sorted(v.begin(), v.end())); + for(auto i=0; i<n; ++i) { + EXPECT_EQ(i+1, v[i]); + } +} + TEST(algorithms, sum) { -- GitLab