1 /* 2 This file is part of MADNESS. 3 4 Copyright (C) 2007,2010 Oak Ridge National Laboratory 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 20 For more information please contact: 21 22 Robert J. Harrison 23 Oak Ridge National Laboratory 24 One Bethel Valley Road 25 P.O. Box 2008, MS-6367 26 27 email: harrisonrj@ornl.gov 28 tel: 865-241-3937 29 fax: 865-572-0680 30 */ 31 32 /** 33 \file world.h 34 \brief Declares the \c World class for the parallel runtime environment. 35 \ingroup world 36 37 \todo More detailed description of this file. 38 39 \todo Are some of the forward declarations in this file necessary? A quick inspection suggests most of the functions before the World class don't need to be declared first... 40 */ 41 42 #ifndef MADNESS_WORLD_WORLD_H__INCLUDED 43 #define MADNESS_WORLD_WORLD_H__INCLUDED 44 45 #include <madness/madness_config.h> 46 47 // #ifdef SEEK_SET 48 // #undef SEEK_SET 49 // #endif 50 // #ifdef SEEK_CUR 51 // #undef SEEK_CUR 52 // #endif 53 // #ifdef SEEK_END 54 // #undef SEEK_END 55 // #endif 56 57 // Standard C++ header files needed by MADworld.h 58 #include <iostream> 59 #include <list> 60 #include <utility> 61 #include <cstddef> 62 63 #ifdef HAVE_RANDOM 64 #include <stdlib.h> 65 #endif 66 67 // Madness world header files needed by world 68 #include <madness/world/worldmpi.h> 69 #include <madness/world/worldhashmap.h> 70 #include <madness/world/worldprofile.h> 71 #include <madness/world/thread.h> 72 #include <madness/world/uniqueid.h> 73 #include <madness/world/nodefaults.h> 74 75 /// \addtogroup world 76 /// @{ 77 78 namespace madness { 79 80 class World; 81 class WorldTaskQueue; 82 class WorldAmInterface; 83 class WorldGopInterface; 84 85 /// redirects standard output and error to rank-specific files 86 87 /// @param[in] world the World object that determines rank of this process 88 /// @param[in] split if true, write standard output to log.<rank> and standard error to err.<rank>, 89 /// otherwise write both standard output and error to log.<rank>. The default is false. 90 void redirectio(const World& world, bool split = false); 91 92 /// Initialize the MADNESS runtime. 93 94 /// Call this once at the very top of your main program to initialize the 95 /// MADNESS runtime. This function should be called instead of \c MPI_Init() 96 /// or \c MPI_Init_thread(). 97 /// \param[in,out] argc Application argument count. 98 /// \param[in,out] argv Application argument values. 99 /// \return A reference to the default \c World, which is constructed with 100 /// \c MPI_COMM_WORLD. 101 World& initialize(int& argc, char**& argv); 102 103 /// Initialize the MADNESS runtime. 104 105 /// Call this once at the very top of your main program to initialize the 106 /// MADNESS runtime. This function should be called instead of \c MPI_Init() 107 /// or \c MPI_Init_thread(). 108 /// \param[in,out] argc Application argument count. 109 /// \param[in,out] argv Application argument values. 110 /// \param comm The communicator that should be used to construct the 111 /// \c World object. 112 /// \return A reference to the \c World constructed with \c comm. 113 World& initialize(int& argc, char**& argv, const SafeMPI::Intracomm& comm); 114 115 /// Initialize the MADNESS runtime. 116 117 /// Call this once at the very top of your main program to initialize the 118 /// MADNESS runtime. This function should be called instead of \c MPI_Init() 119 /// or \c MPI_Init_thread(). 120 /// \param[in,out] argc Application argument count. 121 /// \param[in,out] argv Application argument values. 122 /// \param comm The MPI communicator that should be used to construct the 123 /// \c World object. 124 /// \return A reference to the World constructed with \c comm. 125 World& initialize(int& argc, char**& argv, const MPI_Comm& comm); 126 127 /// Call this once at the very end of your main program instead of MPI_Finalize(). 128 void finalize(); 129 130 /// Check if the MADNESS runtime has been initialized (and not subsequently finalized). 131 132 /// @return true if \c madness::initialize had been called more recently than \c madness::finalize, false otherwise. 133 bool initialized(); 134 135 /// Print miscellaneous stats on a World. 136 137 /// This requires collective operations within the World. 138 /// \param[in] world The World to analyze. 139 void print_stats(World& world); 140 141 /// \todo Brief description needed. 142 143 /// \todo Detailed description needed. 144 /// \param path Description. 145 /// \param display Description. 146 extern void xterm_debug(const char* path, const char* display); 147 148 /// \todo Brief description needed. 149 150 /// \todo Detailed description needed. I imagine this prints/logs the supplied 151 /// error message and subsequently aborts the program. 152 /// \param[in] msg Message associated with the error. 153 void error(const char *msg); 154 155 /// Prints an error message, along with some data, and aborts the program. 156 157 /// \todo Does this function need to be static? (Esp. since it's in a header file...) 158 /// 159 /// \tparam T The type of data. 160 /// \param[in] msg The error message. 161 /// \param[in] data The data to be printed. 162 template <typename T> 163 static void error(const char *msg, const T& data); 164 165 166 /// A parallel world class. 167 168 /// World wraps a MPI communicator. Multiple worlds with different 169 /// communicators can co-exist. 170 /// 171 /// Here we use Pimpl to both hide implementation details and also 172 /// to partition the namespace for users as \c world.mpi, \c world.am, etc. 173 /// We also embed a reference to this instance in the \c am and \c task 174 /// instances so that they have access to everything. 175 /// 176 /// The downside is we cannot do much of anything here without 177 /// using wrapper functions to forward the calls to the hidden 178 /// class methods. 179 class World : private NO_DEFAULTS { 180 private: 181 friend class WorldAmInterface; 182 friend class WorldGopInterface; 183 friend World& initialize(int&, char**&, const SafeMPI::Intracomm&); 184 friend void finalize(); 185 186 // Static member variables 187 static unsigned long idbase; ///< Base for unique world ID range for this process. 188 static World* default_world; ///< Default world. 189 static std::list<World*> worlds; ///< Maintains list of active worlds. 190 191 /// \todo Brief description needed. 192 struct hashuniqueT { 193 /// \todo Brief description needed. 194 195 /// \todo Descriptions needed. 196 /// \param[in] id The ID. 197 /// \return Return description needed. operatorhashuniqueT198 inline std::size_t operator()(const uniqueidT& id) const { 199 return id.objid; // The object id's are guaranteed to be unique 200 } 201 }; 202 203 /// \todo Brief description needed. 204 struct hashvoidp { 205 /// \todo Brief description needed. 206 207 /// \todo Descriptions needed. 208 /// \param[in] p Missing description. 209 /// \return Return description needed. operatorhashvoidp210 inline std::size_t operator()(const void* p) const { 211 return std::size_t(p); // The ptr's are guaranteed to be unique 212 } 213 }; 214 215 // Mutex globalmutex; ///< Worldwide mutex 216 /// \todo Brief description of typedef needed. 217 typedef madness::ConcurrentHashMap<uniqueidT, void *, hashuniqueT> map_id_to_ptrT; 218 /// \todo Brief description of typedef needed. 219 typedef madness::ConcurrentHashMap<void *, uniqueidT, hashvoidp> map_ptr_to_idT; 220 map_id_to_ptrT map_id_to_ptr; ///< \todo Verify: Map from the hash ID to a pointer. 221 map_ptr_to_idT map_ptr_to_id; ///< \todo Verify: Map from a pointer to its unique hash ID. 222 223 224 unsigned long _id; ///< Universe wide unique ID of this world. 225 unsigned long obj_id; ///< Counter for generating unique IDs within this world. 226 void* user_state; ///< Holds a user-defined and managed local state. 227 228 // Default copy constructor and assignment won't compile 229 // (which is good) due to reference members. 230 231 public: 232 // !!! Order of declaration is important for correct order of initialization !!! 233 WorldMpiInterface& mpi; ///< MPI interface. 234 WorldAmInterface& am; ///< AM interface. 235 WorldTaskQueue& taskq; ///< Task queue. 236 WorldGopInterface& gop; ///< Global operations. 237 238 private: 239 unsigned int myrand_next; ///< State of crude internal random number generator. 240 241 public: 242 /// Constructs a \c World from a communicator. 243 244 /// This function does not check if another \c World exists that uses 245 /// the same communicator. Use instance() to check this. 246 /// 247 /// \param[in] comm The communicator. 248 World(const SafeMPI::Intracomm& comm); 249 250 /// Find the World (if it exists) corresponding to the given communicator. 251 252 /// \param[in] comm The communicator. 253 /// \return Pointer to the \c World that was constructed from \c comm; 254 /// if such a \c World does not exist, return 0. find_instance(const SafeMPI::Intracomm & comm)255 static World* find_instance(const SafeMPI::Intracomm& comm) { 256 typedef std::list<World*>::const_iterator citer; 257 for(citer it = worlds.begin(); it != worlds.end(); ++it) { 258 if ((*it)->mpi.comm() == comm) 259 return *it; 260 } 261 return 0; 262 } 263 264 /// Default \c World object accessor. 265 266 /// This function returns a reference to the default world object; this 267 /// is the same \c World object that is returned by 268 /// \c madness::initialize(). 269 /// \return A reference to the default \c World. get_default()270 static World& get_default() { 271 #ifdef MADNESS_DISABLE_WORLD_GET_DEFAULT 272 MADNESS_EXCEPTION("World::get_default() was called while disabled", 0); 273 #endif 274 MADNESS_ASSERT(default_world); 275 return *default_world; 276 } 277 278 /// Sets the user-managed local state. 279 280 /// Rather than having all remotely invoked actions carry all 281 /// of their data with them, they can access local state through 282 /// their \c World instance. The user is responsible for 283 /// consistently managing and freeing this data. 284 /// 285 /// A more PC C++ style would be for the app to put state in 286 /// a singleton. 287 /// \param[in] state The user-managed local state. set_user_state(void * state)288 void set_user_state(void* state) { user_state = state; } 289 290 /// Returns a pointer to the user-managed local state set by set_user_state(). 291 292 /// \return A pointer to the user-managed local state; NULL if 293 /// set_user_state() has not been invoked. get_user_state()294 void* get_user_state() { return user_state; } 295 296 /// Clears the user-defined state. 297 298 /// This has the same effect as `set_user_state(0)`. clear_user_state()299 void clear_user_state() { user_state = nullptr; } 300 301 /// Processes command line arguments. 302 303 /// Mostly intended for \c World test codes, but also provides the 304 /// `-dx option` to start `x` debugger. 305 /// \param[in] argc The number of command-line arguments. 306 /// \param[in,out] argv The command-line arguments. 307 void args(int argc, char**argv); 308 309 /// Returns the system-wide unique integer ID of this \c World. 310 /// 311 /// \return The system-wide unique integer ID of this \c World. id()312 unsigned long id() const { return _id; } 313 314 /// Returns the process rank in this \c World (same as MPI_Comm_rank()). 315 316 /// \return The process rank in this \c World. rank()317 ProcessID rank() const { return mpi.rank(); } 318 319 /// Returns the number of processes in this \c World (same as MPI_Comm_size()). 320 321 /// \return The number of processes in this \c World. nproc()322 ProcessID nproc() const { return mpi.nproc(); } 323 324 /// Returns the number of processes in this \c World (same as MPI_Comm_size()). 325 326 /// \return The number of processes in this \c World. size()327 ProcessID size() const { return mpi.size(); } 328 329 /// Returns the next universe-wide unique ID for objects created in this \c World. No comms. 330 331 /// You should consider using \c register_ptr(), \c unregister_ptr(), 332 /// \c id_from_ptr(), or \c ptr_from_id() rather than using this directly. 333 /// 334 /// Currently relies on this being called in the same order on 335 /// every process within the current \c World in order to avoid 336 /// synchronization. 337 /// 338 /// The value obj_id=0 is guaranteed to be invalid. 339 /// \return The next universe-wide unique ID for objects created in this \c World. unique_obj_id()340 uniqueidT unique_obj_id() { return uniqueidT(_id,obj_id++); } 341 342 /// Associate a local pointer with a universe-wide unique ID. 343 344 /// Use the routines \c register_ptr(), \c unregister_ptr(), 345 /// \c id_from_ptr(), \c ptr_from_id() to map distributed data 346 /// structures identified by the unique ID to/from 347 /// process-local data. 348 /// 349 /// \note The pointer will be internally cast to a (void *), 350 /// so don't use member pointers here. 351 /// 352 /// \note All unique objects of any type within a \c World must 353 /// presently be created in the same order on all processes so 354 /// as to provide the uniquess property without global 355 /// communication. 356 /// \tparam T The type of data to be associated. 357 /// \param[in] ptr Pointer to the data that will be associated 358 /// with a unique ID. 359 /// \return The unique ID associated with the supplied data. 360 template <typename T> register_ptr(T * ptr)361 uniqueidT register_ptr(T* ptr) { 362 MADNESS_ASSERT(sizeof(T*) == sizeof(void *)); 363 uniqueidT id = unique_obj_id(); 364 map_id_to_ptr.insert(std::pair<uniqueidT,void*>(id,static_cast<void*>(ptr))); 365 map_ptr_to_id.insert(std::pair<void*,uniqueidT>(static_cast<void*>(ptr),id)); 366 return id; 367 } 368 369 /// Unregister the unique ID for a local pointer. 370 371 /// \tparam T The type of data to unregister. 372 /// \param[in] ptr The local pointer to unregister. 373 /// \todo Are there any problems to report if ptr is not already registered? 374 template <typename T> unregister_ptr(T * ptr)375 void unregister_ptr(T* ptr) { 376 uniqueidT id = id_from_ptr(ptr); // Will be zero if invalid 377 map_id_to_ptr.erase(id); 378 map_ptr_to_id.erase((void *) ptr); 379 } 380 381 /// Unregister the unique ID for a local pointer via its ID. 382 383 /// This is the same as `unregister_ptr(world.ptr_from_id<T>(id));`. 384 /// \tparam T The type of data to unregister. 385 /// \param[in] id The unique ID of the data to unregister. 386 template <typename T> unregister_ptr(const uniqueidT id)387 void unregister_ptr(const uniqueidT id) { 388 T* const ptr = ptr_from_id<T>(id); 389 map_id_to_ptr.erase(id); 390 map_ptr_to_id.erase((void *) ptr); 391 } 392 393 /// Look up a local pointer from a world-wide unique ID. 394 395 /// \tparam T The type of the data to look up. 396 /// \param[in] id The unique ID of the data. 397 /// \return The local pointer or \c NULL if the ID is not found. 398 template <typename T> ptr_from_id(uniqueidT id)399 T* ptr_from_id(uniqueidT id) const { 400 map_id_to_ptrT::const_iterator it = map_id_to_ptr.find(id); 401 if (it == map_id_to_ptr.end()) 402 return nullptr; 403 else 404 return (T*)(it->second); 405 } 406 407 /// Look up an ID from a local pointer. 408 409 /// \tparam T The type of the data to look up. 410 /// \param[in] ptr The local pointer. 411 /// \return The unique ID or \c invalidid if the pointer is not found. 412 template <typename T> id_from_ptr(T * ptr)413 const uniqueidT& id_from_ptr(T* ptr) const { 414 static uniqueidT invalidid(0,0); 415 map_ptr_to_idT::const_iterator it = map_ptr_to_id.find(ptr); 416 if (it == map_ptr_to_id.end()) 417 return invalidid; 418 else 419 return it->second; 420 } 421 422 #ifndef MADNESS_DISABLE_SHARED_FROM_THIS 423 424 /// Look up a local pointer from a world-wide unique ID. 425 426 /// \tparam T The type of the data to look up. 427 /// \param[in] id The unique ID. 428 /// \return The pointer or a default constructed `std::shared_ptr` if 429 /// the ID is not found. 430 template <typename T> shared_ptr_from_id(uniqueidT id)431 std::shared_ptr<T> shared_ptr_from_id(uniqueidT id) const { 432 T* ptr = ptr_from_id<T>(id); 433 return (ptr ? ptr->shared_from_this() : std::shared_ptr<T>()); 434 } 435 436 /// Look up a unique ID from a local pointer. 437 438 /// \tparam T The type of the data to look up. 439 /// \param[in] ptr The local pointer. 440 /// \return The unique ID or an invalid ID if the pointer is not found. 441 template <typename T> id_from_ptr(std::shared_ptr<T> & ptr)442 const uniqueidT& id_from_ptr(std::shared_ptr<T>& ptr) const { 443 return id_from_ptr(ptr.get()); 444 } 445 446 #endif // MADNESS_DISABLE_SHARED_FROM_THIS 447 448 449 /// Convert a \c World ID to a \c World pointer. 450 451 /// The ID will only be valid if the process calling this routine 452 /// is a member of that \c World. Thus a \c NULL return value does not 453 /// necessarily mean that the \c World does not exist --- it could just 454 /// not include the calling process. 455 /// \param[in] id The ID of the \c World. 456 /// \return A pointer to the world associated with \c id, or \c NULL. world_from_id(unsigned long id)457 static World* world_from_id(unsigned long id) { 458 for (std::list<World *>::iterator it=worlds.begin(); it != worlds.end(); ++it) { 459 if ((*it) && (*it)->_id == id) return *it; 460 } 461 return nullptr; 462 } 463 464 private: 465 466 // Cannot use bind_nullary here since SafeMPI::Request::Test is non-const 467 /// \todo Brief description needed. 468 struct MpiRequestTester { 469 mutable SafeMPI::Request* r; ///< \todo Brief description needed. 470 471 /// \todo Brief description needed. 472 473 /// \todo Descriptions needed. 474 /// \param r Description needed. MpiRequestTesterMpiRequestTester475 MpiRequestTester(SafeMPI::Request& r) : r(&r) {} 476 477 /// \todo Brief description needed. 478 479 /// \todo Descriptions needed. 480 /// \return Description needed. operatorMpiRequestTester481 bool operator()() const { 482 return r->Test(); 483 } 484 }; 485 486 public: 487 488 /// Wait for a MPI request to complete. 489 490 /// \todo Descriptions needed. 491 /// \param[in,out] request The MPI request on which to wait. 492 /// \param dowork Work while waiting - default is true 493 static void inline await(SafeMPI::Request& request, bool dowork = true) { 494 ThreadPool::await(MpiRequestTester(request), dowork, true); // Last arg is sleep=true --- don't hard spin on MPI requests 495 } 496 497 /// Gracefully wait for a condition to become true. 498 499 /// In the mean time, execute any tasks in the queue. 500 /// \todo Descriptions needed. 501 /// \tparam Probe An object that, when called, returns the status. 502 /// \param[in] probe The conditional's test. 503 /// \param dowork Work while waiting - default is true 504 /// \param sleep Sleep instead of spin while waiting - default is false 505 template <typename Probe> 506 static void inline await(const Probe& probe, bool dowork = true, bool sleep=false) { 507 ThreadPool::await(probe, dowork); 508 } 509 510 /// Crude seed function for random number generation. 511 512 /// \param[in] seed The seed. 513 /// \todo Since we're switching to C++11, would it be worth using the new C++11 random number generation capabilities? 514 void srand(unsigned long seed = 0ul) { 515 if (seed == 0) seed = rank(); 516 #ifdef HAVE_RANDOM 517 srandom(seed); 518 #else 519 myrand_next = seed; 520 for (int i=0; i<1000; ++i) rand(); // Warmup 521 #endif // HAVE_RANDOM 522 } 523 524 525 /// Returns a CRUDE, LOW-QUALITY, random number (integer) uniformly distributed in [0,2**24). 526 527 /// Each process has a distinct seed for the generator. 528 /// \return The random number. 529 /// \todo Since we're switching to C++11, would it be worth using the new C++11 random number generation capabilities? rand()530 int rand() { 531 #ifdef HAVE_RANDOM 532 return int(random() & 0xfffffful); 533 #else 534 myrand_next = myrand_next * 1103515245UL + 12345UL; 535 return int((myrand_next>>8) & 0xfffffful); 536 #endif // HAVE_RANDOM 537 } 538 539 540 /// Returns a CRUDE, LOW-QUALITY, random number (real) uniformly distributed in [0,1). 541 542 /// Each process has a distinct seed for the generator. 543 /// \return The random number. 544 /// \todo Since we're switching to C++11, would it be worth using the new C++11 random number generation capabilities? drand()545 double drand() { return rand()/16777216.0; } 546 547 /// Returns a random process number; that is, an integer in [0,`world.size()`). 548 549 /// \return The random process number. random_proc()550 ProcessID random_proc() { return rand()%size(); } 551 552 /// Returns a random process number [0,`world.size()`) that is not the calling process. 553 554 /// It doesn't make any sense to call this with just one process, but just in 555 /// case, this returns -1 in the hope that you won't actually use the result. 556 /// \return The random process number, or -1. random_proc_not_me()557 ProcessID random_proc_not_me() { 558 if (size() == 1) return -1; 559 ProcessID p; 560 do { 561 p = rand()%size(); 562 } while (p == rank()); 563 return p; 564 } 565 566 ~World(); 567 }; // class World 568 569 namespace archive { 570 571 template <typename, typename> 572 struct ArchiveLoadImpl; 573 template <typename, typename> 574 struct ArchiveStoreImpl; 575 576 /// Specialization of \c ArchiveLoadImpl for \c World pointers. 577 578 /// Helps in archiving (reading) \c World objects. 579 /// \tparam Archive The archive type. 580 template <class Archive> 581 struct ArchiveLoadImpl<Archive,World*> { 582 /// Loads a \c World from the specified archive. 583 584 /// \note Aborts the program if a \c World cannot be read from the archive. 585 /// \param[in,out] ar The archive. 586 /// \param[out] wptr Pointer to the \c World. 587 static inline void load(const Archive& ar, World*& wptr) { 588 unsigned long id = 0ul; 589 ar & id; 590 wptr = World::world_from_id(id); 591 MADNESS_ASSERT(wptr); 592 } 593 }; // struct ArchiveLoadImpl<Archive,World*> 594 595 /// Specialization of \c ArchiveStoreImpl for \c World pointers. 596 597 /// Helps in archiving (writing) \c World objects. 598 /// \tparam Archive The archive type. 599 template <class Archive> 600 struct ArchiveStoreImpl<Archive,World*> { 601 /// Writes a \c World to the specified archive. 602 603 /// \param[in,out] ar The archive. 604 /// \param[in] wptr Pointer to the \c World. 605 static inline void store(const Archive& ar, World* const & wptr) { 606 ar & wptr->id(); 607 } 608 }; // struct ArchiveStoreImpl<Archive,World*> 609 } // namespace archive 610 611 612 613 // implementation of templated functions 614 template <typename T> 615 static void error(const char *msg, const T& data) { 616 std::cerr << "MADNESS: fatal error: " << msg << " " << data << std::endl; 617 SafeMPI::COMM_WORLD.Abort(); 618 } 619 } // namespace madness 620 621 /// @} 622 623 #endif // MADNESS_WORLD_WORLD_H__INCLUDED 624