PDS/homework_2/include/utils.hpp

151 lines
4.1 KiB
C++

/**
* \file utils.hpp
* \brief Utilities header
*
* \author
* Christos Choutouridis AEM:8997
* <cchoutou@ece.auth.gr>
*/
#ifndef UTILS_HPP_
#define UTILS_HPP_
#include <iostream>
#include <chrono>
#include <unistd.h>
#include <mpi.h>
//#include "matrix.hpp"
#include "config.h"
template<typename TID = int>
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<ID_t>(MPI_Comm_size(MPI_COMM_WORLD, &size_value));
rank_ = static_cast<ID_t>(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<typename T>
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<std::chrono::microseconds>(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<microseconds>(t).count() < 10000)
std::cout << "[Timing]: " << what << ": "
<< std::to_string(std::chrono::duration_cast<microseconds>(t).count()) << " [usec]\n";
else if (std::chrono::duration_cast<milliseconds>(t).count() < 10000)
std::cout << "[Timing]: " << what << ": "
<< std::to_string(std::chrono::duration_cast<milliseconds>(t).count()) << " [msec]\n";
else
std::cout << "[Timing]: " << what << ": "
<< std::to_string(std::chrono::duration_cast<seconds>(t).count()) << " [sec]\n";
}
}
private:
Tpoint start_;
Tpoint stop_;
};
#endif /* UTILS_HPP_ */