/** * \file utils.hpp * \brief Utilities header * * \author * Christos Choutouridis AEM:8997 * */ #ifndef UTILS_HPP_ #define UTILS_HPP_ #include #include #include #include //#include "matrix.hpp" #include "config.h" template struct MPI_t { using ID_t = TID; // Export TID type (currently int defined by the standard) void init(int *argc, char ***argv) { // Initialize the MPI environment MPI_Init(argc, argv); // Get the number of processes int size_value, rank_value; size_ = static_cast(MPI_Comm_size(MPI_COMM_WORLD, &size_value)); rank_ = static_cast(MPI_Comm_rank(MPI_COMM_WORLD, &rank_value)); // Get the name of the processor char processor_name[MPI_MAX_PROCESSOR_NAME]; int name_len; MPI_Get_processor_name(processor_name, &name_len); name_ = std::string (processor_name, name_len); } void finalize() { // Finalize the MPI environment. MPI_Finalize(); } bool exchange(ID_t partner, const void *send_data, void *recv_data, int data_count, MPI_Datatype datatype) { bool ret = true; MPI_Status status; MPI_Sendrecv( send_data, data_count, datatype, partner, 0, recv_data, data_count, datatype, partner, 0, MPI_COMM_WORLD, &status ); if (status.MPI_ERROR != MPI_SUCCESS) ret = false; return ret; } // Accessors [[nodiscard]] ID_t rank() const noexcept { return rank_; } [[nodiscard]] ID_t size() const noexcept { return size_; } [[nodiscard]] const std::string& name() const noexcept { return name_; } private: ID_t rank_{}; ID_t size_{}; std::string name_{}; }; extern MPI_t<> mpi; using mpi_id_t = MPI_t<>::ID_t; /*! * A Logger for entire program. */ struct Log { struct Endl { } endl; //!< a tag object to to use it as a new line request. //! We provide logging via << operator template Log &operator<<(T &&t) { if (session.verbose) { if (line_) { std::cout << "[Log]: " << t; line_ = false; } else std::cout << t; } return *this; } // overload for special end line handling Log &operator<<(Endl e) { (void) e; if (session.verbose) { std::cout << '\n'; line_ = true; } return *this; } private: bool line_{true}; }; extern Log logger; /*! * A small timing utility based on chrono. */ struct Timing { using Tpoint = std::chrono::steady_clock::time_point; using microseconds = std::chrono::microseconds; using milliseconds = std::chrono::milliseconds; using seconds = std::chrono::seconds; //! tool to mark the starting point Tpoint start() noexcept { return start_ = std::chrono::steady_clock::now(); } //! tool to mark the ending point Tpoint stop() noexcept { return stop_ = std::chrono::steady_clock::now(); } auto dt() noexcept { return std::chrono::duration_cast(stop_ - start_).count(); } //! tool to print the time interval void print_dt(const char *what) noexcept { if (session.timing) { auto t = stop_ - start_; if (std::chrono::duration_cast(t).count() < 10000) std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast(t).count()) << " [usec]\n"; else if (std::chrono::duration_cast(t).count() < 10000) std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast(t).count()) << " [msec]\n"; else std::cout << "[Timing]: " << what << ": " << std::to_string(std::chrono::duration_cast(t).count()) << " [sec]\n"; } } private: Tpoint start_; Tpoint stop_; }; #endif /* UTILS_HPP_ */