HW2: RC4 - [Not tested] The final version
This commit is contained in:
@@ -10,13 +10,9 @@
|
||||
#include "distsort.hpp"
|
||||
|
||||
|
||||
//! Performance timers for each one of the "costly" functions
|
||||
Timing TfullSort, Texchange, Tminmax, TelbowSort;
|
||||
|
||||
|
||||
bool isActive(mpi_id_t node, size_t nodes) {
|
||||
if (!((nodes > 0) &&
|
||||
(nodes <= std::numeric_limits<mpi_id_t>::max()) ))
|
||||
(nodes <= static_cast<size_t>(std::numeric_limits<mpi_id_t>::max())) ))
|
||||
throw std::runtime_error("(isActive) Non-acceptable value of MPI Nodes\n");
|
||||
// ^ Assert that mpi_id_t can hold nodes, and thus we can cast without data loss!
|
||||
|
||||
@@ -24,12 +20,14 @@ bool isActive(mpi_id_t node, size_t nodes) {
|
||||
}
|
||||
|
||||
size_t tagGenerator(size_t depth, size_t step, size_t stage) {
|
||||
auto stage_bits = static_cast<uint32_t>(std::log2(MAX_PIPELINE_SIZE));
|
||||
auto step_bits = static_cast<uint32_t>(std::log2(MAX_MPI_SIZE));
|
||||
auto stage_bits = static_cast<uint32_t>(std::log2(MAX_PIPELINE_SIZE));
|
||||
auto step_bits = static_cast<uint32_t>(std::log2(MAX_MPI_SIZE));
|
||||
uint32_t stat_bit = 1UL;
|
||||
// ^ We use MPI_SIZE room for steps to fit the bubbletonic version
|
||||
|
||||
// [ depth | step | stage+stats ]
|
||||
size_t tag = stage
|
||||
| (step << stage_bits)
|
||||
| (depth << (stage_bits + step_bits));
|
||||
| (step << (stage_bits + stat_bit))
|
||||
| (depth << (stage_bits + step_bits + stat_bit));
|
||||
return tag;
|
||||
}
|
||||
|
||||
+67
-24
@@ -22,7 +22,36 @@ config_t config;
|
||||
MPI_t<> mpi;
|
||||
distBuffer_t Data;
|
||||
Log logger;
|
||||
Timing Ttotal;
|
||||
distStat_t localStat, remoteStat;
|
||||
|
||||
//! Performance timers for each one of the "costly" functions
|
||||
Timing Ttotal;
|
||||
Timing TfullSort;
|
||||
Timing Texchange;
|
||||
Timing Tminmax;
|
||||
Timing TelbowSort;
|
||||
|
||||
//! Init timing objects for extra rounds
|
||||
void measurements_init() {
|
||||
if (config.perf > 1) {
|
||||
Ttotal.init(config.perf);
|
||||
TfullSort.init(config.perf);
|
||||
Texchange.init(config.perf);
|
||||
Tminmax.init(config.perf);
|
||||
TelbowSort.init(config.perf);
|
||||
}
|
||||
}
|
||||
|
||||
//! iterate ot the next round of measurements for all measurement objects
|
||||
void measurements_next() {
|
||||
if (config.perf > 1) {
|
||||
Ttotal.next();
|
||||
TfullSort.next();
|
||||
Texchange.next();
|
||||
Tminmax.next();
|
||||
TelbowSort.next();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* A small command line argument parser
|
||||
@@ -43,6 +72,9 @@ bool get_options(int argc, char* argv[]){
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
else if (arg == "-e" || arg == "--exchange-opt") {
|
||||
config.exchangeOpt = true;
|
||||
}
|
||||
else if (arg == "--pipeline") {
|
||||
if (i+1 < argc) {
|
||||
auto stages = atoi(argv[++i]);
|
||||
@@ -59,7 +91,12 @@ bool get_options(int argc, char* argv[]){
|
||||
config.validation = true;
|
||||
}
|
||||
else if (arg == "--perf") {
|
||||
config.perf = true;
|
||||
if (i+1 < argc) {
|
||||
config.perf = atoi(argv[++i]);
|
||||
}
|
||||
else {
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
else if (arg == "--ndebug") {
|
||||
config.ndebug = true;
|
||||
@@ -68,22 +105,25 @@ bool get_options(int argc, char* argv[]){
|
||||
config.verbose = true;
|
||||
}
|
||||
else if (arg == "-h" || arg == "--help") {
|
||||
std::cout << "distbitonic/distbubbletonic - A distributed bitonic sort\n\n";
|
||||
std::cout << "distbitonic -q <N> [--pipeline N] [--validation] [--ndebug] [-v]\n";
|
||||
std::cout << "distbitonic/distbubbletonic - A distributed sort utility\n\n";
|
||||
std::cout << "distbitonic -q <N> [-e] [-p | --pipeline N] [--validation] [--perf] [--ndebug] [-v]\n";
|
||||
std::cout << "distbitonic -h\n";
|
||||
std::cout << "distbubbletonic -q <N> [--pipeline N] [--validation] [--ndebug] [-v]\n";
|
||||
std::cout << "distbubbletonic -q <N> [-e] [-p | --pipeline N] [--validation] [--perf] [--ndebug] [-v]\n";
|
||||
std::cout << "distbubbletonic -h\n";
|
||||
std::cout << '\n';
|
||||
std::cout << "Options:\n\n";
|
||||
std::cout << " -q | --array-size <N>\n";
|
||||
std::cout << " Selects the array size according to size = 2^N\n\n";
|
||||
std::cout << " --pipeline <N>\n";
|
||||
std::cout << " -e | --exchange-opt\n";
|
||||
std::cout << " Request an MPI data exchange optimization \n\n";
|
||||
std::cout << " -p <N> | --pipeline <N>\n";
|
||||
std::cout << " Request a pipeline of <N> stages for exchange-minmax\n";
|
||||
std::cout << " N must be power of 2 up to " << MAX_PIPELINE_SIZE << "\n\n";
|
||||
std::cout << " --validation\n";
|
||||
std::cout << " Request a full validation at the end, performed by process rank 0\n\n";
|
||||
std::cout << " --perf\n";
|
||||
std::cout << " Request performance timing measurements to stdout.\n\n";
|
||||
std::cout << " --perf <N> \n";
|
||||
std::cout << " Enable performance timing measurements and prints, and repeat\n";
|
||||
std::cout << " the sorting <N> times to average the measurements\n\n";
|
||||
std::cout << " --ndebug\n";
|
||||
std::cout << " Skip debug breakpoint when on debug build.\n\n";
|
||||
std::cout << " -v | --verbose\n";
|
||||
@@ -167,8 +207,8 @@ int main(int argc, char* argv[]) try {
|
||||
" Size: " << mpi.size() <<
|
||||
logger.endl;
|
||||
|
||||
#if defined DEBUG
|
||||
#if defined TESTING
|
||||
#if defined DEBUG
|
||||
#if defined TESTING
|
||||
/*
|
||||
* In case of a debug build we will wait here until sleep_wait
|
||||
* will reset via debugger. In order to do that the user must attach
|
||||
@@ -179,12 +219,12 @@ int main(int argc, char* argv[]) try {
|
||||
* $> gdb <program> <PID2>
|
||||
*/
|
||||
volatile bool sleep_wait = false;
|
||||
#else
|
||||
#else
|
||||
volatile bool sleep_wait = true;
|
||||
#endif
|
||||
#endif
|
||||
while (sleep_wait && !config.ndebug)
|
||||
sleep(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Initialize local data
|
||||
logger << "Initialize local array of " << config.arraySize << " elements" << logger.endl;
|
||||
@@ -201,24 +241,27 @@ int main(int argc, char* argv[]) try {
|
||||
// Run distributed sort
|
||||
if (mpi.rank() == 0)
|
||||
logger << "Starting distributed sorting ... ";
|
||||
Ttotal.start();
|
||||
measurements_init();
|
||||
for (size_t it = 0 ; it < config.perf ; ++it) {
|
||||
Ttotal.start();
|
||||
#if CODE_VERSION == BUBBLETONIC
|
||||
distBubbletonic(Data, mpi.size(), mpi.rank());
|
||||
distBubbletonic(Data, mpi.size(), mpi.rank());
|
||||
#else
|
||||
distBitonic (Data, mpi.size(), mpi.rank());
|
||||
distBitonic(Data, mpi.size(), mpi.rank());
|
||||
#endif
|
||||
Ttotal.stop();
|
||||
Ttotal.stop();
|
||||
measurements_next();
|
||||
}
|
||||
if (mpi.rank() == 0)
|
||||
logger << " Done." << logger.endl;
|
||||
|
||||
|
||||
// Print-outs and validation
|
||||
if (config.perf) {
|
||||
Ttotal.print_duration("Total ", mpi.rank());
|
||||
TfullSort.print_duration("Full-Sort ", mpi.rank());
|
||||
Texchange.print_duration("Exchange ", mpi.rank());
|
||||
Tminmax.print_duration("Min-Max ", mpi.rank());
|
||||
TelbowSort.print_duration("Elbow-Sort", mpi.rank());
|
||||
if (config.perf > 1) {
|
||||
Timing::print_duration(Ttotal.median(), "Total ", mpi.rank());
|
||||
Timing::print_duration(TfullSort.median(), "Full-Sort ", mpi.rank());
|
||||
Timing::print_duration(Texchange.median(), "Exchange ", mpi.rank());
|
||||
Timing::print_duration(Texchange.median(), "Min-Max ", mpi.rank());
|
||||
Timing::print_duration(TelbowSort.median(),"Elbow-Sort", mpi.rank());
|
||||
}
|
||||
if (config.validation) {
|
||||
// If requested, we have the chance to fail!
|
||||
|
||||
Reference in New Issue
Block a user