225 regels
7.8 KiB
C++
225 regels
7.8 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 <hdf5.h>
|
|
|
|
#include "matrix.hpp"
|
|
#include "config.h"
|
|
|
|
/*!
|
|
* 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_;
|
|
};
|
|
|
|
|
|
|
|
struct Mtx {
|
|
|
|
template<typename MatrixType, HDF5_type Type>
|
|
static void load(const std::string& filename, const std::string& dataset, MatrixType& matrix) {
|
|
|
|
hid_t file_id{}, dataset_id{}, dataspace_id{};
|
|
herr_t read_st;
|
|
do {
|
|
// Open file
|
|
logger << "Load HDF5 file: " << filename << " Dataset: " << dataset << "...";
|
|
if ((file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT)) < 0)
|
|
break;
|
|
|
|
// Open dataset
|
|
if ((dataset_id = H5Dopen2(file_id, dataset.c_str(), H5P_DEFAULT)) < 0)
|
|
break;
|
|
|
|
// Get dataspace and allocate memory for read buffer
|
|
if ((dataspace_id = H5Dget_space(dataset_id)) < 0)
|
|
break;
|
|
hsize_t dims[2];
|
|
H5Sget_simple_extent_dims(dataspace_id, dims, NULL);
|
|
matrix.resize(dims[0], dims[1]);
|
|
|
|
// Read the dataset
|
|
// ToDo: Come up with a better way to do this
|
|
if constexpr (Type == HDF5_type::DOUBLE) {
|
|
if ((read_st = H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0)
|
|
break;
|
|
}
|
|
else if (Type == HDF5_type::FLOAT) {
|
|
if ((read_st = H5Dread(dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0)
|
|
break;
|
|
}
|
|
else if (Type == HDF5_type::UINT) {
|
|
if ((read_st = H5Dread(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0)
|
|
break;
|
|
}
|
|
else if (Type == HDF5_type::INT) {
|
|
if ((read_st = H5Dread(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) < 0)
|
|
break;
|
|
}
|
|
// Done
|
|
H5Dclose(dataset_id);
|
|
H5Sclose(dataspace_id);
|
|
H5Fclose(file_id);
|
|
logger << " Done" << logger.endl;
|
|
return;
|
|
} while (0);
|
|
|
|
// Error: close everything (if possible) and return false
|
|
H5Dclose(dataset_id);
|
|
H5Sclose(dataspace_id);
|
|
H5Fclose(file_id);
|
|
throw std::runtime_error("Cannot store to " + filename + " dataset:" + dataset + '\n');
|
|
}
|
|
|
|
|
|
template<typename MatrixType, HDF5_type Type>
|
|
static void store(const std::string& filename, const std::string& dataset, MatrixType& matrix) {
|
|
|
|
hid_t file_id{}, dataset_id{}, dataspace_id{};
|
|
herr_t write_st;
|
|
do {
|
|
// Try to open the file in read-write mode
|
|
logger << "Store HDF5 file: " << filename << " Dataset: " << dataset << "...";
|
|
if (access(session.outMtxFile.c_str(), F_OK) == 0){
|
|
if ((file_id = H5Fopen(filename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT)) < 0)
|
|
break;
|
|
}
|
|
else {
|
|
if ((file_id = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
break;
|
|
}
|
|
|
|
// Create the dataspace for the dataset
|
|
hsize_t dims[] = { matrix.rows(), matrix.columns() };
|
|
if ((dataspace_id = H5Screate_simple(2, dims, NULL)) < 0)
|
|
break;
|
|
|
|
// ToDo: Come up with a better way to do this
|
|
if constexpr (Type == HDF5_type::DOUBLE) {
|
|
// Create the dataset with default properties
|
|
if ((dataset_id = H5Dcreate2(
|
|
file_id, dataset.c_str(), H5T_NATIVE_DOUBLE, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
break;
|
|
// Write the data to the dataset
|
|
if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 )
|
|
break;
|
|
}
|
|
else if (Type == HDF5_type::FLOAT) {
|
|
// Create the dataset with default properties
|
|
if ((dataset_id = H5Dcreate2(
|
|
file_id, dataset.c_str(), H5T_NATIVE_FLOAT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
break;
|
|
// Write the data to the dataset
|
|
if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 )
|
|
break;
|
|
}
|
|
else if (Type == HDF5_type::UINT) {
|
|
// Create the dataset with default properties
|
|
if ((dataset_id = H5Dcreate2(
|
|
file_id, dataset.c_str(), H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
break;
|
|
// Write the data to the dataset
|
|
if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 )
|
|
break;
|
|
}
|
|
else if (Type == HDF5_type::INT) {
|
|
// Create the dataset with default properties
|
|
if ((dataset_id = H5Dcreate2(
|
|
file_id, dataset.c_str(), H5T_NATIVE_INT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0)
|
|
break;
|
|
// Write the data to the dataset
|
|
if ((write_st = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, matrix.data())) <0 )
|
|
break;
|
|
}
|
|
// Close the dataset, dataspace, and file
|
|
H5Dclose(dataset_id);
|
|
H5Sclose(dataspace_id);
|
|
H5Fclose(file_id);
|
|
logger << " Done" << logger.endl;
|
|
return;
|
|
} while (0);
|
|
|
|
// Error: close everything (if possible) and return false
|
|
H5Dclose(dataset_id);
|
|
H5Sclose(dataspace_id);
|
|
H5Fclose(file_id);
|
|
throw std::runtime_error("Cannot store " + filename + " with dataset:" + dataset +'\n');
|
|
}
|
|
};
|
|
|
|
|
|
|
|
#endif /* UTILS_HPP_ */
|