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