See More

#include #include #include #include #include #ifdef TILEDARRAY_HAS_DEVICE #include #include #include #endif #if TILEDARRAY_HAS_TTG #include #endif #ifdef IntelMKL_FAIR_DISPATCH extern "C" void intel_mkl_use_fair_dispatch(); #endif #include #include #include namespace TiledArray { namespace { #ifdef TILEDARRAY_HAS_DEVICE /// initialize cuda environment inline void device_initialize() { /// initialize deviceEnv deviceEnv::instance(); #if defined(TILEDARRAY_HAS_DEVICE) BLASQueuePool::initialize(); #endif // initialize LibreTT librettInitialize(); } /// finalize cuda environment inline void device_finalize() { DeviceSafeCall(device::deviceSynchronize()); librettFinalize(); #if defined(TILEDARRAY_HAS_DEVICE) BLASQueuePool::finalize(); #endif // although TA::deviceEnv is a singleton, must explicitly delete it so // that the device runtime is not finalized before the deviceEnv dtor is // called deviceEnv::instance().reset(nullptr); } #endif // TILEDARRAY_HAS_DEVICE inline bool& initialized_madworld_accessor() { static bool flag = false; return flag; } inline bool initialized_madworld() { return initialized_madworld_accessor(); } inline bool& initialized_accessor() { static bool flag = false; return flag; } inline bool& finalized_accessor() { static bool flag = false; return flag; } inline bool& quiet_accessor() { static bool quiet = false; return quiet; } } // namespace } // namespace TiledArray bool TiledArray::initialized() { return initialized_accessor(); } bool TiledArray::finalized() { return finalized_accessor(); } bool TiledArray::initialized_to_be_quiet() { return quiet_accessor(); } TiledArray::World& TiledArray::initialize(int& argc, char**& argv, const SafeMPI::Intracomm& comm, bool quiet) { if (initialized_madworld() && finalized()) throw Exception( "TiledArray finalized MADWorld already, cannot re-initialize MADWorld " "again"); if (!initialized()) { if (!madness::initialized()) { initialized_madworld_accessor() = true; } else { // if MADWorld initialized, we must assume that comm is its // default World. if (!madness::World::is_default(comm)) throw Exception( "MADWorld initialized before TiledArray::initialize(argc, argv, " "comm), but not initialized with comm"); } auto& default_world = initialized_madworld() ? madness::initialize(argc, argv, comm, quiet) : *madness::World::find_instance(comm); TiledArray::set_default_world(default_world); #ifdef TILEDARRAY_HAS_DEVICE TiledArray::device_initialize(); #endif #ifdef IntelMKL_FAIR_DISPATCH intel_mkl_use_fair_dispatch(); #endif TiledArray::max_threads = TiledArray::get_num_threads(); TiledArray::set_num_threads(1); madness::print_meminfo_disable(); initialized_accessor() = true; quiet_accessor() = quiet; // if have TTG, initialize it also #if TILEDARRAY_HAS_TTG // MADNESS/PaRSEC creates PaRSEC context that uses MPI_COMM_SELF to avoid // creation of a PaRSEC comm thread to be able to use TTG/PaRSEC need to // tell PaRSEC context to use the full communicator if (madness::ParsecRuntime::context()->nb_nodes != default_world.size()) { auto default_world_comm = default_world.mpi.comm().Get_mpi_comm(); parsec_remote_dep_set_ctx(madness::ParsecRuntime::context(), (intptr_t)default_world_comm); } ttg::initialize(argc, argv, -1, madness::ParsecRuntime::context()); #endif // check if user specified linear algebra backend + params auto* linalg_backend_cstr = std::getenv("TA_LINALG_BACKEND"); if (linalg_backend_cstr) { using namespace std::literals::string_literals; if ("scalapack"s == linalg_backend_cstr) { TiledArray::set_linalg_backend( TiledArray::LinearAlgebraBackend::ScaLAPACK); } else if ("ttg"s == linalg_backend_cstr) { TiledArray::set_linalg_backend(TiledArray::LinearAlgebraBackend::TTG); } else if ("lapack"s == linalg_backend_cstr) { TiledArray::set_linalg_backend( TiledArray::LinearAlgebraBackend::LAPACK); } else TA_EXCEPTION( "TiledArray::initialize: invalid value of environment variable " "TA_LINALG_BACKEND, valid values are \"scalapack\", \"ttg\", and " "\"lapack\""); } const char* linalg_distributed_minsize_cstr = std::getenv("TA_LINALG_DISTRIBUTED_MINSIZE"); if (linalg_distributed_minsize_cstr) { char* end; const auto linalg_distributed_minsize = std::strtoul(linalg_distributed_minsize_cstr, &end, 10); if (errno == ERANGE) TA_EXCEPTION( "TiledArray::initialize: invalid value of environment variable " "TA_LINALG_DISTRIBUTED_MINSIZE"); TiledArray::set_linalg_crossover_to_distributed( linalg_distributed_minsize); } return default_world; } else throw Exception("TiledArray already initialized"); } void TiledArray::finalize() { // finalize in the reverse order of initialize #if TILEDARRAY_HAS_TTG ttg::finalize(); #endif // reset number of threads TiledArray::set_num_threads(TiledArray::max_threads); TiledArray::get_default_world().gop.fence(); // this should ensure no pending // tasks using cuda allocators #ifdef TILEDARRAY_HAS_DEVICE TiledArray::device_finalize(); #endif if (initialized_madworld()) { madness::finalize(); } TiledArray::reset_default_world(); initialized_accessor() = false; finalized_accessor() = true; } TiledArray::detail::Finalizer::~Finalizer() noexcept { static std::mutex mtx; std::scoped_lock lock(mtx); if (TiledArray::initialized()) { TiledArray::finalize(); } } TiledArray::detail::Finalizer TiledArray::scoped_finalizer() { return {}; } void TiledArray::ta_abort() { // if have a custom signal handler for SIGABRT (i.e. we are running under a // debugger) then call abort() struct sigaction sa; auto rc = sigaction(SIGABRT, NULL, &sa); if (rc == 0 && sa.sa_handler != SIG_DFL) { abort(); } else { SafeMPI::COMM_WORLD.Abort(); } } void TiledArray::ta_abort(const std::string& m) { std::cerr << m << std::endl; ta_abort(); } void TiledArray::taskq_wait_busy() { madness::threadpool_wait_policy(madness::WaitPolicy::Busy); } void TiledArray::taskq_wait_yield() { madness::threadpool_wait_policy(madness::WaitPolicy::Yield); } void TiledArray::taskq_wait_usleep(int us) { madness::threadpool_wait_policy(madness::WaitPolicy::Sleep, us); }