Add a new function to sort edges
sort_edge_srcfirst_ will sort the edge with respect to the src state, then sort each sub list with respect to the given predicate, possibly in parallel. * spot/graph/graph.hh: Here
This commit is contained in:
parent
e064726b64
commit
71c2a7b1a6
1 changed files with 70 additions and 0 deletions
|
|
@ -28,6 +28,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
@ -1226,6 +1227,75 @@ namespace spot
|
||||||
std::stable_sort(edges_.begin() + 1, edges_.end(), p);
|
std::stable_sort(edges_.begin() + 1, edges_.end(), p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Sort all edges by src first, then, within edges of the same
|
||||||
|
/// source use the predicate
|
||||||
|
///
|
||||||
|
/// This will invalidate all iterators, and also destroy edge
|
||||||
|
/// chains. Call chain_edges_() immediately afterwards unless you
|
||||||
|
/// know what you are doing.
|
||||||
|
/// \note: for performance this will work in parallel (if enabled)
|
||||||
|
/// and make a temporary copy of the edges (needs more ram)
|
||||||
|
/// \pre This needs the edge_vector to be in a coherent state when called
|
||||||
|
template<class Predicate = std::less<edge_storage_t>>
|
||||||
|
void sort_edges_srcfirst_(Predicate p = Predicate())
|
||||||
|
{
|
||||||
|
//std::cerr << "\nbefore\n";
|
||||||
|
//dump_storage(std::cerr);
|
||||||
|
const auto N = num_states();
|
||||||
|
// Read threads once
|
||||||
|
const unsigned nthreads = get_nthreads();
|
||||||
|
|
||||||
|
auto idx_list = std::vector<unsigned>(N+1);
|
||||||
|
auto new_edges = edge_vector_t();
|
||||||
|
new_edges.reserve(edges_.size());
|
||||||
|
if (SPOT_UNLIKELY(edges_.empty()))
|
||||||
|
throw std::runtime_error("Empty edge vector!");
|
||||||
|
new_edges.resize(1);
|
||||||
|
// This causes edge 0 to be considered as dead.
|
||||||
|
new_edges[0].next_succ = 0;
|
||||||
|
// Copy the edges such that they are sorted by src
|
||||||
|
for (auto s = 0u; s < N; ++s)
|
||||||
|
{
|
||||||
|
idx_list[s] = new_edges.size();
|
||||||
|
for (const auto& e : out(s))
|
||||||
|
new_edges.push_back(e);
|
||||||
|
}
|
||||||
|
idx_list[N] = new_edges.size();
|
||||||
|
// New edge sorted by source
|
||||||
|
// If we have few edge or only one threads
|
||||||
|
// Benchmark few?
|
||||||
|
auto bne = new_edges.begin();
|
||||||
|
if (nthreads == 1 || edges_.size() < 1000)
|
||||||
|
{
|
||||||
|
for (auto s = 0u; s < N; ++s)
|
||||||
|
std::stable_sort(bne + idx_list[s],
|
||||||
|
bne + idx_list[s+1],
|
||||||
|
p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static auto tv = std::vector<std::thread>();
|
||||||
|
SPOT_ASSERT(tv.empty());
|
||||||
|
tv.resize(nthreads);
|
||||||
|
for (unsigned id = 0; id < nthreads; ++id)
|
||||||
|
tv[id] = std::thread(
|
||||||
|
[bne, id, N, &idx_list, p, nthreads]()
|
||||||
|
{
|
||||||
|
for (auto s = id; s < N; s+=nthreads)
|
||||||
|
std::stable_sort(bne + idx_list[s],
|
||||||
|
bne + idx_list[s+1],
|
||||||
|
p);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
for (auto& t : tv)
|
||||||
|
t.join();
|
||||||
|
tv.clear();
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
std::swap(edges_, new_edges);
|
||||||
|
// Like after normal sort_edges, they need to be chained before usage
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Sort edges of the given states
|
/// \brief Sort edges of the given states
|
||||||
///
|
///
|
||||||
/// \tparam Predicate : Comparison type
|
/// \tparam Predicate : Comparison type
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue