// ================================================================== // Author: Jean-Michel Richer // Email: jean-michel.richer@univ-angers.fr // Date: Aug 2020 // Last modified: November 2020 // Purpose: interface and class to facilitate use of MPI // ================================================================== #include "ezmpi.h" using namespace ez::mpi; void Process::find_cpu_name() { char name[MPI::MAX_PROCESSOR_NAME]; int length; memset(name, 0, MPI::MAX_PROCESSOR_NAME); MPI::Get_processor_name(name,length); m_name = name; } void Process::init() { m_max = MPI::COMM_WORLD.Get_size(); m_id = MPI::COMM_WORLD.Get_rank(); find_cpu_name(); m_pid = getpid(); if (m_verbose_flag) { tmp_log << "pid=" << m_pid << ", id=" << m_id << endl; flush(); } } Process::Process(int argc, char *argv[], bool verbose, bool log) { m_remote = 0; m_message_tag = 0; m_verbose_flag = verbose; m_log_flag = log; finalize_already_called = false; MPI::Init(argc, argv); init(); } void Process::logs(ostream& out) { m_verbose_flag = m_log_flag = false; if (m_id == 0) { out.flush(); out << std::endl; out << "====================" << std::endl; out << "=== FINAL RESULT ===" << std::endl; out << "====================" << std::endl; out << "---------------------" << std::endl; out << "CPU " << m_id << " (pid=" << pid() << ")" << std::endl; out << "---------------------" << std::endl; out << log_stream.str(); out.flush(); remote( 1 ); int token = -255; send( token ); } else { remote( m_id - 1 ); int token; recv(token); out << "---------------------" << std::endl; out << "CPU " << m_id << " (pid=" << pid() << ")" << std::endl; out << "---------------------" << std::endl; out << log_stream.str(); out.flush(); if (m_id < m_max - 1) { remote( m_id + 1 ); token = -255; send(token); } } } void Process::finalize() { if (!finalize_already_called) { finalize_already_called = true; MPI::COMM_WORLD.Barrier(); MPI::Finalize(); } } Process::~Process() { if (!finalize_already_called) { finalize_already_called = true; MPI::COMM_WORLD.Barrier(); MPI::Finalize(); } } int Process::pid() { return m_pid; } int Process::id() { return m_id; } int Process::rank() { return m_id; } int Process::max() { return m_max; } string Process::name() { return m_name; } void Process::tag(int tag) { m_message_tag = tag; } void Process::remote(int rmt) { m_remote = rmt; } void Process::synchronize() { MPI::COMM_WORLD.Barrier(); } // -------------------------- // output // -------------------------- const std::string currentDateTime() { time_t now = time(0); struct tm tstruct; char buf[80]; tstruct = *localtime(&now); //strftime(buf, sizeof(buf), "%Y-%m-%d.%X [%s]", &tstruct); strftime(buf, sizeof(buf), "%X", &tstruct); return buf; } void Process::flush() { string str = currentDateTime(); if (m_log_flag) { log_stream << str << " cpu " << m_id << "/" << m_max << ": " << tmp_log.str(); } if (m_verbose_flag) { cerr << str << " cpu " << m_id << "/" << m_max << ": " << tmp_log.str(); } tmp_log.str(""); } void Process::print(char v) { tmp_log << v; } void Process::print(int v) { tmp_log << v; } void Process::print(string v) { tmp_log << v; } void Process::print(float v) { tmp_log << v; } void Process::print(double v) { tmp_log << v; }