244 lines
8.2 KiB
C++
244 lines
8.2 KiB
C++
/**
|
|
* \file
|
|
* \brief Utilities header
|
|
*
|
|
* \author
|
|
* Christos Choutouridis AEM:8997
|
|
* <cchoutou@ece.auth.gr>
|
|
*/
|
|
#ifndef UTILS_HPP_
|
|
#define UTILS_HPP_
|
|
|
|
#include <vector>
|
|
#include <iostream>
|
|
#include <chrono>
|
|
#include <unistd.h>
|
|
#include <mpi.h>
|
|
|
|
//#include "matrix.hpp"
|
|
#include "config.h"
|
|
|
|
template <typename T> struct MPI_TypeMapper;
|
|
|
|
// Specializations for supported types
|
|
template <> struct MPI_TypeMapper<char> { static MPI_Datatype getType() { return MPI_CHAR; } };
|
|
template <> struct MPI_TypeMapper<unsigned char> { static MPI_Datatype getType() { return MPI_UNSIGNED_CHAR; } };
|
|
template <> struct MPI_TypeMapper<short> { static MPI_Datatype getType() { return MPI_SHORT; } };
|
|
template <> struct MPI_TypeMapper<int> { static MPI_Datatype getType() { return MPI_INT; } };
|
|
template <> struct MPI_TypeMapper<long> { static MPI_Datatype getType() { return MPI_LONG; } };
|
|
template <> struct MPI_TypeMapper<long long> { static MPI_Datatype getType() { return MPI_LONG_LONG; } };
|
|
template <> struct MPI_TypeMapper<unsigned short>{ static MPI_Datatype getType() { return MPI_UNSIGNED_SHORT; } };
|
|
template <> struct MPI_TypeMapper<unsigned long> { static MPI_Datatype getType() { return MPI_UNSIGNED_LONG; } };
|
|
template <> struct MPI_TypeMapper<unsigned long long> { static MPI_Datatype getType() { return MPI_UNSIGNED_LONG_LONG; } };
|
|
|
|
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;
|
|
MPI_Comm_size(MPI_COMM_WORLD, &size_value);
|
|
MPI_Comm_rank(MPI_COMM_WORLD, &rank_value);
|
|
size_ = static_cast<ID_t>(size_value);
|
|
rank_ = static_cast<ID_t>(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();
|
|
}
|
|
|
|
template<typename T>
|
|
void exchange(ID_t partner, const std::vector<T>& send_data, std::vector<T>& recv_data, int tag) {
|
|
using namespace std::string_literals;
|
|
|
|
MPI_Status status;
|
|
MPI_Datatype datatype = MPI_TypeMapper<T>::getType();
|
|
int send_count = static_cast<int>(send_data.size());
|
|
int err = MPI_Sendrecv(
|
|
send_data.data(), send_count, datatype, partner, tag,
|
|
recv_data.data(), send_count, datatype, partner, tag,
|
|
MPI_COMM_WORLD, &status
|
|
);
|
|
if (err != MPI_SUCCESS) {
|
|
char err_msg[MPI_MAX_ERROR_STRING];
|
|
int msg_len;
|
|
MPI_Error_string(err, err_msg, &msg_len);
|
|
throw std::runtime_error("(MPI) MPI_Sendrecv() - " + std::string (err_msg) + '\n');
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
|
|
template <typename Value_t>
|
|
struct ShadowedVec_t {
|
|
// STL requirements
|
|
using value_type = Value_t;
|
|
using iterator = typename std::vector<Value_t>::iterator;
|
|
using const_iterator = typename std::vector<Value_t>::const_iterator;
|
|
using size_type = typename std::vector<Value_t>::size_type;
|
|
|
|
// Dispatch to active vector
|
|
Value_t& operator[](size_type index) { return getActive()[index]; }
|
|
const Value_t& operator[](size_type index) const { return getActive()[index]; }
|
|
|
|
Value_t& at(size_type index) { return getActive().at(index); }
|
|
const Value_t& at(size_type index) const { return getActive().at(index); }
|
|
|
|
void push_back(const Value_t& value) { getActive().push_back(value); }
|
|
void push_back(Value_t&& value) { getActive().push_back(std::move(value)); }
|
|
void pop_back() { getActive().pop_back(); }
|
|
Value_t& front() { return getActive().front(); }
|
|
const Value_t& front() const { return getActive().front(); }
|
|
Value_t& back() { return getActive().back(); }
|
|
const Value_t& back() const { return getActive().back(); }
|
|
|
|
iterator begin() { return getActive().begin(); }
|
|
const_iterator begin() const { return getActive().begin(); }
|
|
iterator end() { return getActive().end(); }
|
|
const_iterator end() const { return getActive().end(); }
|
|
|
|
size_type size() const { return getActive().size(); }
|
|
void resize(size_t new_size) {
|
|
North.resize(new_size);
|
|
South.resize(new_size);
|
|
}
|
|
|
|
void reserve(size_t new_capacity) {
|
|
North.reserve(new_capacity);
|
|
South.reserve(new_capacity);
|
|
}
|
|
[[nodiscard]] size_t capacity() const { return getActive().capacity(); }
|
|
[[nodiscard]] bool empty() const { return getActive().empty(); }
|
|
|
|
void clear() { getActive().clear(); }
|
|
|
|
void swap(std::vector<Value_t>& other) { getActive().swap(other); }
|
|
|
|
// Switching vectors
|
|
void switch_active() { active = (active == north) ? south : north; }
|
|
|
|
// Accessors
|
|
const std::vector<Value_t>& getNorth() const { return North; }
|
|
const std::vector<Value_t>& getSouth() const { return South; }
|
|
std::vector<Value_t>& getActive() {
|
|
return (active == north) ? North : South;
|
|
}
|
|
const std::vector<Value_t>& getActive() const {
|
|
return (active == north) ? North : South;
|
|
}
|
|
std::vector<Value_t>& getShadow() {
|
|
return (active == north) ? South : North;
|
|
}
|
|
const std::vector<Value_t>& getShadow() const {
|
|
return (active == north) ? South : North;
|
|
}
|
|
private:
|
|
enum { north, south } active{north};
|
|
std::vector<Value_t> North{};
|
|
std::vector<Value_t> South{};
|
|
};
|
|
|
|
using distBuffer_t = ShadowedVec_t<distValue_t>;
|
|
|
|
extern distBuffer_t Data;
|
|
|
|
/*!
|
|
* 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_ */
|