HW2: RC1 - Model version
This commit is contained in:
@@ -44,15 +44,15 @@ using distValue_t = uint32_t;
|
||||
/*!
|
||||
* Session option for each invocation of the executable
|
||||
*/
|
||||
struct session_t {
|
||||
struct config_t {
|
||||
size_t arraySize{DEFAULT_DATA_SIZE}; //!<
|
||||
bool validation{false}; //!< Request a full validation at the end, performed by process rank 0
|
||||
bool ndebug{false}; //!< Skips debug trap on DEBUG builds
|
||||
bool timing{false}; //!< Enable timing measurements and prints
|
||||
bool perf{false}; //!< Enable performance timing measurements and prints
|
||||
bool verbose{false}; //!< Flag to enable verbose output to stdout
|
||||
};
|
||||
|
||||
extern session_t session;
|
||||
extern config_t config;
|
||||
|
||||
|
||||
#endif /* CONFIG_H_ */
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
//#include <parallel/algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#if !defined DEBUG
|
||||
@@ -20,8 +21,8 @@
|
||||
#include <cassert>
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "config.h"
|
||||
|
||||
extern Timing TfullSort, Texchange, Tminmax, TelbowSort;
|
||||
|
||||
/*!
|
||||
* Enumerator for the different versions of the sorting method
|
||||
@@ -159,11 +160,13 @@ bool isActive(mpi_id_t node, size_t nodes);
|
||||
*/
|
||||
template<typename RangeT>
|
||||
void fullSort(RangeT& data, bool ascending) noexcept {
|
||||
// Use introsort from stdlib++ here, unless ...
|
||||
if (ascending)
|
||||
// Use introsort from stdlib++ here, unless ... __gnu_parallel
|
||||
if (ascending) {
|
||||
std::sort(data.begin(), data.end(), std::less<>());
|
||||
else
|
||||
}
|
||||
else {
|
||||
std::sort(data.begin(), data.end(), std::greater<>());
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -270,7 +273,7 @@ void minmax(RangeT& local, const RangeT& remote, bool keepSmall) noexcept {
|
||||
template<typename ShadowedDataT>
|
||||
void distBubbletonic(ShadowedDataT& data, mpi_id_t Processes, mpi_id_t rank) {
|
||||
// Initially sort to create a half part of a bitonic sequence
|
||||
fullSort(data, ascending<SortMode::Bubbletonic>(rank, 0));
|
||||
timeCall(TfullSort, fullSort, data, ascending<SortMode::Bubbletonic>(rank, 0));
|
||||
|
||||
// Sort network (O(N) iterations)
|
||||
for (size_t step = 0; step < static_cast<size_t>(Processes); ++step) {
|
||||
@@ -280,9 +283,9 @@ void distBubbletonic(ShadowedDataT& data, mpi_id_t Processes, mpi_id_t rank) {
|
||||
if ( isActive(rank, Processes) &&
|
||||
isActive(part, Processes) ) {
|
||||
// Exchange with partner, keep nim-or-max and sort - O(N)
|
||||
mpi.exchange(data.getActive(), data.getShadow(), part, step);
|
||||
minmax(data.getActive(), data.getShadow(), ks);
|
||||
elbowSort(data, ascending<SortMode::Bubbletonic>(rank, Processes));
|
||||
timeCall(Texchange, mpi.exchange, data.getActive(), data.getShadow(), part, step);
|
||||
timeCall(Tminmax, minmax, data.getActive(), data.getShadow(), ks);
|
||||
timeCall(TelbowSort, elbowSort, data, ascending<SortMode::Bubbletonic>(rank, Processes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +311,7 @@ void distBubbletonic(ShadowedDataT& data, mpi_id_t Processes, mpi_id_t rank) {
|
||||
template<typename ShadowedDataT>
|
||||
void distBitonic(ShadowedDataT& data, mpi_id_t Processes, mpi_id_t rank) {
|
||||
// Initially sort to create a half part of a bitonic sequence
|
||||
fullSort(data, ascending<SortMode::Bitonic>(rank, 0));
|
||||
timeCall(TfullSort, fullSort, data, ascending<SortMode::Bitonic>(rank, 0));
|
||||
|
||||
// Run through sort network using elbow-sort ( O(LogN * LogN) iterations )
|
||||
auto p = static_cast<uint32_t>(std::log2(Processes));
|
||||
@@ -319,11 +322,11 @@ void distBitonic(ShadowedDataT& data, mpi_id_t Processes, mpi_id_t rank) {
|
||||
auto part = partner<SortMode::Bitonic>(rank, step);
|
||||
auto ks = keepSmall<SortMode::Bitonic>(rank, part, depth);
|
||||
// Exchange with partner, keep nim-or-max
|
||||
mpi.exchange(data.getActive(), data.getShadow(), part, (depth << 8) | step);
|
||||
minmax(data.getActive(), data.getShadow(), ks);
|
||||
timeCall(Texchange, mpi.exchange, data.getActive(), data.getShadow(), part, (depth << 8) | step);
|
||||
timeCall(Tminmax, minmax, data.getActive(), data.getShadow(), ks);
|
||||
}
|
||||
// sort - O(N)
|
||||
elbowSort (data, ascending<SortMode::Bitonic>(rank, depth));
|
||||
timeCall(TelbowSort, elbowSort, data, ascending<SortMode::Bitonic>(rank, depth));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <chrono>
|
||||
#include <unistd.h>
|
||||
#include <mpi.h>
|
||||
//#include <functional>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -286,7 +287,7 @@ struct Log {
|
||||
//! We provide logging via << operator
|
||||
template<typename T>
|
||||
Log &operator<<(T &&t) {
|
||||
if (session.verbose) {
|
||||
if (config.verbose) {
|
||||
if (line_) {
|
||||
std::cout << "[Log]: " << t;
|
||||
line_ = false;
|
||||
@@ -299,7 +300,7 @@ struct Log {
|
||||
// overload for special end line handling
|
||||
Log &operator<<(Endl e) {
|
||||
(void) e;
|
||||
if (session.verbose) {
|
||||
if (config.verbose) {
|
||||
std::cout << '\n';
|
||||
line_ = true;
|
||||
}
|
||||
@@ -317,39 +318,71 @@ extern Log logger;
|
||||
*/
|
||||
struct Timing {
|
||||
using Tpoint = std::chrono::steady_clock::time_point;
|
||||
using Tduration = std::chrono::microseconds;
|
||||
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(); }
|
||||
Tpoint start() noexcept { return mark_ = std::chrono::steady_clock::now(); }
|
||||
|
||||
//! tool to mark the ending point
|
||||
Tpoint stop() noexcept { return stop_ = std::chrono::steady_clock::now(); }
|
||||
Tpoint stop() noexcept {
|
||||
Tpoint now = std::chrono::steady_clock::now();
|
||||
duration_ += dt(now, mark_);
|
||||
return now;
|
||||
}
|
||||
|
||||
auto dt() noexcept {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(stop_ - start_).count();
|
||||
Tduration dt(Tpoint t2, Tpoint t1) noexcept {
|
||||
return std::chrono::duration_cast<Tduration>(t2 - t1);
|
||||
}
|
||||
|
||||
//! 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";
|
||||
}
|
||||
void print_duration(const char *what, mpi_id_t rank) noexcept {
|
||||
if (std::chrono::duration_cast<microseconds>(duration_).count() < 10000)
|
||||
std::cout << "[Timing] (Rank " << rank << ") " << what << ": "
|
||||
<< std::to_string(std::chrono::duration_cast<microseconds>(duration_).count()) << " [usec]\n";
|
||||
else if (std::chrono::duration_cast<milliseconds>(duration_).count() < 10000)
|
||||
std::cout << "[Timing] (Rank " << rank << ") " << what << ": "
|
||||
<< std::to_string(std::chrono::duration_cast<milliseconds>(duration_).count()) << " [msec]\n";
|
||||
else
|
||||
std::cout << "[Timing] (Rank " << rank << ") " << what << ": "
|
||||
<< std::to_string(std::chrono::duration_cast<seconds>(duration_).count()) << " [sec]\n";
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
Tpoint start_;
|
||||
Tpoint stop_;
|
||||
Tpoint mark_{};
|
||||
Tduration duration_{};
|
||||
};
|
||||
|
||||
/*!
|
||||
* Utility high level function to forward a function call to std::invoke and measure
|
||||
* the excecution time
|
||||
*
|
||||
* @tparam Func The function type
|
||||
* @tparam Args The argument
|
||||
* @param func
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
#define timeCall(Tim, Func, ...) \
|
||||
Tim.start(); \
|
||||
Func(__VA_ARGS__); \
|
||||
Tim.stop(); \
|
||||
|
||||
|
||||
//template <typename Ret, typename Func, typename... Args>
|
||||
//auto timeCall_r(Ret& ret, Func&& func, Args&&... args) {
|
||||
// Timing timer;
|
||||
//
|
||||
// timer.start();
|
||||
// ret = std::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
|
||||
// timer.stop();
|
||||
//
|
||||
// return timer.dt();
|
||||
//}
|
||||
|
||||
#endif /* UTILS_HPP_ */
|
||||
|
||||
Reference in New Issue
Block a user