67#ifndef __PBeFS_HDAStar
68 #define __PBeFS_HDAStar
95#include "ADS/parallel/Channels.h"
97#include "ADS/parallel/Mailbox.h"
138template< Domain D ,
class Dist = StateHashDistribution< D > ,
139 ADS::WorkerExecutor Executor = ADS::ThreadPool ,
140 class Open = std::conditional_t<
141 std::is_
integral_v< cost_t< D > > ,
142 BucketOpenList< Node< state_t< D > , cost_t< D > > > ,
143 HeapOpenList< Node< state_t< D > , cost_t< D > > > > >
172 HDAStar(
const D & domain ,
const Dist & dist ,
174 : f_domain( domain ) , f_dist( dist ) , f_options( options ) {
190 const unsigned p = f_options.threads;
192 Shared sh( p , f_options.batch );
195 const State s0 = f_domain.initial_state();
196 sh.root.emplace(
Msg{ s0 ,
Cost( 0 ) ,
Cost( f_domain.heuristic( s0 ) ) ,
199 sh.root_owner = f_dist.owner( s0 , p );
201 std::vector< std::unique_ptr< Worker > > w( p );
202 for(
unsigned i = 0 ; i < p ; ++i )
203 w[ i ] = std::make_unique< Worker >( *
this , sh , i );
205 run_workers( f_ex , p , [ & ](
unsigned i ) { w[ i ]->run(); } );
209 for(
auto & x : w ) {
214 st.
sent += x->f_st.sent;
215 st.
messages += sh.mail.batches( x->f_id );
216 st.
stored += x->f_pool.size();
218 st.
stored_by.push_back( x->f_pool.size() );
220 if( sh.limit_hit.load() )
225 sol.cost = sh.goal->
g;
236 using Mailbox = ADS::Mailbox< Msg , ADS::DefaultChannels< Msg , Executor > >;
243 Shared(
unsigned np , std::size_t batch ) : p( np ) , mail( np , batch )
248 std::optional< Msg > root;
249 unsigned root_owner = 0;
250 alignas(
cache_line ) std::atomic< Cost > incumbent{
252 std::atomic< bool > limit_hit{
false };
253 std::mutex goal_mutex;
254 NodeT * goal =
nullptr;
260 struct alignas( cache_line ) Worker {
262 Worker(
const HDAStar & a , Shared & s ,
unsigned i )
263 : f_a( a ) , f_sh( s ) , f_id( i ) , f_dist( a.f_dist ) {}
267 if( f_id == f_sh.root_owner )
268 insert( *f_sh.root , f_a.f_domain.hash( f_sh.root->s ) );
269 unsigned since_flush = 0;
270 ADS::Backoff backoff;
271 while( ! f_sh.mail.stopped() ) {
273 f_sh.mail.poll( f_id , [ & ]( Msg && m ) {
274 v_in.push_back( std::move( m ) );
276 if(
const std::size_t n = v_in.size() ) {
280 for( std::size_t k = 0 ; k < n ; ++k ) {
281 v_hash[ k ] = f_a.f_domain.hash( v_in[ k ].s );
282 f_table.prefetch( v_hash[ k ] );
284 for( std::size_t k = 0 ; k < n ; ++k )
285 insert( v_in[ k ] , v_hash[ k ] );
288 if(
NodeT * n = next() ) {
291 if( ++since_flush >= f_a.f_options.flush_period ) {
293 f_sh.mail.flush( f_id );
295 if( f_a.f_options.node_limit &&
296 ( f_pool.size() >= f_a.f_options.node_limit ) ) {
297 f_sh.limit_hit.store(
true );
305 if( f_sh.mail.quiescent( f_id ) )
312 NodeT * next(
void ) {
313 while( ! f_open.empty() ) {
314 const OpenEntry< NodeT > e = f_open.top();
319 if( e.node->g + e.node->h >= f_sh.incumbent.load(
320 std::memory_order_relaxed ) )
329 void expand(
NodeT * n ) {
336 if( f_a.f_domain.is_goal( n->state ) ) {
337 std::lock_guard< std::mutex > lock( f_sh.goal_mutex );
338 if( n->g < f_sh.incumbent.load() ) {
339 f_sh.incumbent.store( n->g );
351 const Cost g = n->g + c;
352 if( g + ht >= f_sh.incumbent.load( std::memory_order_relaxed ) )
354 const auto [ dst , key ] = owner( t );
356 insert( Msg{ t , g , ht , n , ot , key } , f_a.f_domain.hash( t ) );
359 f_sh.mail.send( f_id , dst , Msg{ t , g , ht , n , ot , key } );
366 void insert(
const Msg & m , std::uint64_t h ) {
367 if( m.g + m.h >= f_sh.incumbent.load( std::memory_order_relaxed ) )
369 auto [ x , fresh ] = f_table.find_or_insert( m.s , h , [ & ] {
370 NodeT * y = f_pool.allocate();
371 *y = NodeT{ m.s , m.g , m.h , m.parent , false , false , m.o.op ,
380 x->parent = m.parent;
396 std::vector< Msg > v_in;
397 std::vector< std::uint64_t > v_hash;
405 ParallelOptions f_options;
406 Executor * f_ex =
nullptr;
Header file for the class template AStar, the sequential A* search of Hart, Nilsson and Raphael (1968...
Header file for the work distribution functions of hash-based parallel A*: each one maps a state to i...
Header file for the small helpers shared by the searches: a stopwatch, the placement of the workers o...
Hash Distributed A* on a shared-memory machine.
Definition HDAStar.h:144
state_t< D > State
the state type
Definition HDAStar.h:152
Solution< State, Cost > SolutionT
the solution type
Definition HDAStar.h:155
Node< State, Cost > NodeT
the node type
Definition HDAStar.h:154
cost_t< D > Cost
the cost type
Definition HDAStar.h:153
HDAStar(const D &domain, const Dist &dist, const ParallelOptions &options={})
constructor, taking the Domain and the distribution (which must outlive the HDAStar)
Definition HDAStar.h:172
SolutionT solve(void) const
searches the Domain, returning the Solution
Definition HDAStar.h:188
void set_executor(Executor &ex) noexcept
sets the Executor that runs the workers, which must outlive the searches; without it,...
Definition HDAStar.h:183
the arena of the nodes, on the Arena of ADS, on huge pages
Definition NodePool.h:48
the closed list, on the PointerTable of ADS, on huge pages
Definition NodeTable.h:49
a wall-clock stopwatch, started at construction
Definition SearchUtils.h:175
double seconds(void) const
the seconds elapsed since the construction
Definition SearchUtils.h:182
namespace for the Parallel Best-First Search library
Definition AStar.h:83
void for_each_child(const D &d, const state_t< D > &s, cost_t< D > h, std::uint8_t op, F &&f)
the successors of s but its parent, when D knows the operators
Definition Domain.h:276
typename D::cost_type cost_t
the cost type of a Domain
Definition Domain.h:245
std::uint32_t distribution_key(const X &x, const state_t< D > &s)
the key of s for x, 0 if X is not an IncrementalDistribution
Definition Distribution.h:399
constexpr std::size_t cache_line
the size of a cache line, used to keep the data of the workers apart
Definition SearchUtils.h:66
@ solved
an optimal path has been found
Definition Solution.h:47
@ node_limit
the limit on the stored nodes was reached first
Definition Solution.h:49
constexpr Cost infinite_cost(void) noexcept
the largest value of a cost type, used as "no incumbent yet"
Definition Node.h:100
typename D::state_type state_t
the state type of a Domain
Definition Domain.h:241
void run_workers(Executor *ex, unsigned p, F &&f)
runs the workers f( 0 ) , ... , f( p - 1 ) at once on an Executor
Definition SearchUtils.h:121
constexpr std::uint8_t no_op
the operator of the root, which no state was generated by
Definition Domain.h:205
auto trace_path(const NodeT *goal)
the states from the root to goal, following the parent pointers
Definition Node.h:126
auto successor_owners(const X &x, const state_t< D > &s, std::uint32_t k, unsigned p)
the owner among p workers and the key of each successor of s
Definition Distribution.h:414
a node travelling to its owner
Definition HDAStar.h:158
State s
Definition HDAStar.h:159
Cost g
Definition HDAStar.h:160
NodeT * parent
Definition HDAStar.h:162
Cost h
Definition HDAStar.h:161
OperatorOf< D > o
Definition HDAStar.h:163
std::uint32_t key
Definition HDAStar.h:164
a node of the search graph
Definition Node.h:74
Cost g
the cost of the best path found from the root
Definition Node.h:77
the options of the parallel searches: those of the sequential search, and the parameters of the paral...
Definition HDAStar.h:114
the parameters shared by the parallel searches
Definition SearchUtils.h:94
void normalize(void) noexcept
sets to 1 any parameter that is 0
Definition SearchUtils.h:102
the options shared by all the searches
Definition Solution.h:119
the counters of a search
Definition Solution.h:64
std::uint64_t messages
batches of nodes sent
Definition Solution.h:72
std::vector< std::uint64_t > expanded_by
expansions of each worker
Definition Solution.h:75
std::uint64_t sent
nodes sent to another worker
Definition Solution.h:71
std::uint64_t generated
successors generated
Definition Solution.h:68
std::uint64_t reexpanded
expansions of a node already expanded
Definition Solution.h:67
std::uint64_t stored
distinct nodes stored at the end
Definition Solution.h:73
double seconds
wall-clock time of the search
Definition Solution.h:74
std::uint64_t duplicates
generated states already known with a not larger
Definition Solution.h:69
std::vector< std::uint64_t > stored_by
nodes stored by each worker
Definition Solution.h:76
std::uint64_t expanded
expansions, re-expansions included
Definition Solution.h:66
a path from the initial state to a goal, and its cost
Definition Solution.h:100