313 lines
8.2 KiB
C++
313 lines
8.2 KiB
C++
// #include <cstdlib>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <cstring>
|
|
|
|
#include "../../src/core/util/smarthops/TraceReader.hpp"
|
|
#include "BasicAlgorithm.hpp"
|
|
#include "SmartAlgorithm.hpp"
|
|
#include "SimpleAlgorithm.hpp"
|
|
#include "ResultCollector.hpp"
|
|
|
|
#include "../../src/core/util/gzstream/gzstream.h"
|
|
|
|
#include "util/CommandLine.hpp"
|
|
#include "util/Logger.hpp"
|
|
|
|
#define STDOUT_CMD_STRING "-"
|
|
|
|
using namespace fail;
|
|
|
|
typedef enum {
|
|
ALGO_SIMPLE,
|
|
ALGO_SMART,
|
|
} algorithm_e;
|
|
|
|
bool g_use_weights;
|
|
bool g_use_watchpoints;
|
|
bool g_use_checkpoints;
|
|
|
|
unsigned int g_cp_thresh;
|
|
unsigned int g_cost_cp;
|
|
unsigned int g_rollback_thresh;
|
|
|
|
std::ofstream g_cp_ofstream;
|
|
|
|
Logger LOG("hop-calculator", false);
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
// Manually fill the command line option parser
|
|
CommandLine &cmd = CommandLine::Inst();
|
|
|
|
cmd.addOption("", "", Arg::None, "USAGE: compute-hops [options]");
|
|
CommandLine::option_handle HELP = cmd.addOption("h", "help", Arg::None, "-h,--help \tPrint usage and exit");
|
|
|
|
CommandLine::option_handle ALGORITHM =
|
|
cmd.addOption("a", "algorithm", Arg::Required,
|
|
"-a,--algorithm \tHop algorithm (\"simple\"/\"smart\", default: \"none\")");
|
|
|
|
CommandLine::option_handle OUTPUT_MODE =
|
|
cmd.addOption("m", "output-mode", Arg::Required,
|
|
"-m,--output-mode \tOutput mode (\"results\"/\"costs\"/\"statistics\", default: \"results\")");
|
|
|
|
CommandLine::option_handle TRACE_FILE =
|
|
cmd.addOption("i", "input-file", Arg::Required,
|
|
"-i,--input-file \tInput trace file path");
|
|
|
|
CommandLine::option_handle OUTPUT_FILE =
|
|
cmd.addOption("o", "output-file", Arg::Required,
|
|
"-o,--output-file \tOutput file, default: stdout");
|
|
|
|
CommandLine::option_handle OUTPUT_FILE_PROTOBUF =
|
|
cmd.addOption("b", "protobuf-output", Arg::None,
|
|
"-b,--protobuf-output \tOutput file will be created in protobuf (HopChain) format");
|
|
|
|
CommandLine::option_handle USE_COSTS =
|
|
cmd.addOption("c", "use-costs", Arg::None,
|
|
"-c,--use-costs \tUse hop costs for calculations of Smart-Hopping algorithm");
|
|
|
|
CommandLine::option_handle USE_WATCHPOINTS =
|
|
cmd.addOption("w", "use-watchpoints", Arg::None,
|
|
"-w,--use-watchpoints \tUse watchpoints as additional hop candidates");
|
|
|
|
CommandLine::option_handle USE_CHECKPOINTS =
|
|
cmd.addOption("", "use-checkpoints", Arg::None,
|
|
"--use-checkpoints \tUse checkpoints to cap costs in case of long hop chains");
|
|
|
|
CommandLine::option_handle CP_THRESH =
|
|
cmd.addOption("", "cp-costs-threshold", Arg::Required,
|
|
"--cp-costs-threshold \tIf costs of a hop-chain reach this threshold, a checkpoint will be created");
|
|
|
|
CommandLine::option_handle CP_COSTS =
|
|
cmd.addOption("", "cp-costs", Arg::Required,
|
|
"--cp-costs \tThe costs for reloading a checkpoint into the system");
|
|
|
|
CommandLine::option_handle CP_ROLLBACK_THRESH =
|
|
cmd.addOption("", "cp-rollback-threshold", Arg::Required,
|
|
"--cp-rollback-threshold \tMinial number of hops to roll back current solution beyond checkpoint. Must be smaller than ((cp_cost_thresh - cp_costs) / 2)");
|
|
|
|
CommandLine::option_handle CHECKPOINT_OUTPUT_FILE =
|
|
cmd.addOption("", "cp-output", Arg::Required,
|
|
"--cp-output \tCheckpoint output file");
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
cmd.add_args(argv[i]);
|
|
}
|
|
if (!cmd.parse()) {
|
|
std::cerr << "Error parsing arguments." << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
if (cmd[HELP]) {
|
|
cmd.printUsage();
|
|
if (cmd[HELP]) {
|
|
exit(0);
|
|
} else {
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (cmd[USE_CHECKPOINTS]) {
|
|
g_use_checkpoints = true;
|
|
} else {
|
|
g_use_checkpoints = false;
|
|
}
|
|
|
|
if (cmd[USE_WATCHPOINTS]) {
|
|
g_use_watchpoints = true;
|
|
} else {
|
|
g_use_watchpoints = false;
|
|
}
|
|
|
|
if (cmd[USE_COSTS]) {
|
|
g_use_weights = true;
|
|
} else {
|
|
g_use_weights = false;
|
|
}
|
|
|
|
algorithm_e algorithm;
|
|
|
|
if (cmd[ALGORITHM].count() > 0) {
|
|
std::string alg(cmd[ALGORITHM].first()->arg);
|
|
if (alg == "simple") {
|
|
algorithm = ALGO_SIMPLE;
|
|
} else if (alg == "smart") {
|
|
algorithm = ALGO_SMART;
|
|
} else {
|
|
exit(-1);
|
|
}
|
|
} else {
|
|
// default
|
|
algorithm = ALGO_SMART;
|
|
}
|
|
|
|
output_mode_e output_mode;
|
|
|
|
if (cmd[OUTPUT_MODE].count() > 0) {
|
|
std::string outp(cmd[OUTPUT_MODE].first()->arg);
|
|
if (outp == "results") {
|
|
output_mode = OUTPUT_RESULT;
|
|
} else if (outp == "costs") {
|
|
output_mode = OUTPUT_COSTS;
|
|
} else if (outp == "statistics") {
|
|
output_mode = OUTPUT_STATISTICS;
|
|
} else {
|
|
LOG << "Unkown output mode: " << outp << std::endl;
|
|
exit(-1);
|
|
}
|
|
} else {
|
|
// default
|
|
output_mode = OUTPUT_RESULT;
|
|
}
|
|
|
|
fail::TraceReader trace;
|
|
|
|
if (cmd[TRACE_FILE].count() > 0) {
|
|
const char *filename = cmd[TRACE_FILE].first()->arg;
|
|
if (!trace.openTraceFile(filename, 0)) {
|
|
LOG << "Unable to open and parse input trace file " << filename << std::endl;
|
|
return 1;
|
|
}
|
|
} else {
|
|
LOG << "Input trace file path not defined" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
std::ostream *outFile;
|
|
|
|
if (cmd[OUTPUT_FILE].count() > 0) {
|
|
std::string filename(cmd[OUTPUT_FILE].first()->arg);
|
|
|
|
if (filename.compare(STDOUT_CMD_STRING) == 0) {
|
|
outFile = &std::cout;
|
|
} else {
|
|
std::ofstream *of = new std::ofstream(filename.c_str());
|
|
if (!of->is_open()) {
|
|
LOG << "Unable to open output file " << filename << std::endl;
|
|
exit(-1);
|
|
}
|
|
outFile = of;
|
|
}
|
|
} else {
|
|
outFile = &std::cout;
|
|
}
|
|
|
|
if (cmd[OUTPUT_FILE_PROTOBUF] && outFile == &std::cout) {
|
|
LOG << "If protobuf output format is selected, output file must be defined" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
if (cmd[USE_COSTS] && !(algorithm == ALGO_SMART)) {
|
|
LOG << "Using costs for calculations is only possible with Smart-Hopping algorithm" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
if (cmd[CP_THRESH]) {
|
|
if (cmd[CP_THRESH].count() != 1) {
|
|
LOG << "Could not parse cp-costs-threshold" << std::endl;
|
|
exit(-1);
|
|
}
|
|
g_cp_thresh = strtoul(cmd[CP_THRESH].first()->arg, NULL, 0);
|
|
}
|
|
|
|
if (cmd[CP_COSTS]) {
|
|
if (cmd[CP_COSTS].count() != 1) {
|
|
LOG << "Could not parse cp-costs" << std::endl;
|
|
exit(-1);
|
|
}
|
|
g_cost_cp = strtoul(cmd[CP_COSTS].first()->arg, NULL, 0);
|
|
}
|
|
|
|
if (cmd[CP_ROLLBACK_THRESH]) {
|
|
if (cmd[CP_ROLLBACK_THRESH].count()!=1) {
|
|
LOG << "Could not parse cp-rollback-threshold" << std::endl;
|
|
exit(-1);
|
|
}
|
|
// if (strcmp(argv[9],"max")==0) {
|
|
// g_rollback_thresh = (g_cp_thresh - g_cost_cp - 5)/2;
|
|
// }
|
|
g_rollback_thresh = strtoul(cmd[CP_ROLLBACK_THRESH].first()->arg, NULL, 0);
|
|
}
|
|
|
|
if (cmd[USE_CHECKPOINTS] && !(cmd[CHECKPOINT_OUTPUT_FILE].count() > 0)) {
|
|
LOG << "If checkpointing is enabled, --cp-output must be defined" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
if (cmd[CHECKPOINT_OUTPUT_FILE].count() > 0) {
|
|
std::string filename(cmd[CHECKPOINT_OUTPUT_FILE].first()->arg);
|
|
g_cp_ofstream.open(filename.c_str());
|
|
if (!g_cp_ofstream.is_open()) {
|
|
LOG << "Unable to open cp_out_file " << filename << std::endl;
|
|
exit(-1);
|
|
}
|
|
}
|
|
|
|
if (cmd[USE_CHECKPOINTS] && (!cmd[CP_THRESH] ||
|
|
!cmd[CP_COSTS]|| !cmd[CP_ROLLBACK_THRESH])) {
|
|
LOG << "If using checkpointing is enabled, also cp-costs-threshold, "
|
|
"cp-costs and cp-rollback-threshold must be defined" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
if (!cmd[USE_CHECKPOINTS] && (cmd[CP_THRESH].count() ||
|
|
(cmd[CP_COSTS].count() > 0) || (cmd[CP_ROLLBACK_THRESH].count() > 0))) {
|
|
LOG << "If using checkpointing is disabled, cp-costs-threshold, "
|
|
"cp-costs and cp-rollback-threshold must not be defined" << std::endl;
|
|
exit(-1);
|
|
}
|
|
|
|
if (g_use_checkpoints && !(g_cp_thresh > g_cost_cp)) {
|
|
LOG << "cp_cost_thresh needs to be bigger than cp_costs" << std::endl;
|
|
exit(1);
|
|
}
|
|
|
|
if (g_use_checkpoints && !(g_rollback_thresh < ((g_cp_thresh - g_cost_cp) / 2))) {
|
|
LOG << "cp_rollback_hop_thresh needs to be smaller than "
|
|
"((cp_cost_thresh - cp_costs) / 2)" << std::endl;
|
|
exit(1);
|
|
}
|
|
|
|
|
|
ogzstream zipstream;
|
|
|
|
ResultCollector rc(*outFile, output_mode);
|
|
|
|
if (cmd[OUTPUT_FILE_PROTOBUF]) {
|
|
zipstream.open(cmd[OUTPUT_FILE].first()->arg);
|
|
rc.setProtoOStream(new ProtoOStream(&zipstream));
|
|
}
|
|
|
|
BasicAlgorithm *algo;
|
|
|
|
switch (algorithm) {
|
|
case ALGO_SMART:
|
|
algo = new SmartAlgorithm(&rc);
|
|
break;
|
|
case ALGO_SIMPLE:
|
|
algo = new SimpleAlgorithm(&rc);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
rc.startTimer();
|
|
algo->calculateAllHops(trace);
|
|
rc.stopTimer();
|
|
|
|
rc.finish();
|
|
|
|
// ToDo: close output file if not stdout
|
|
if (outFile != &std::cout) {
|
|
((std::ofstream*)outFile)->close();
|
|
delete (std::ofstream*)outFile;
|
|
}
|
|
|
|
if (g_use_checkpoints) {
|
|
g_cp_ofstream.close();
|
|
}
|
|
|
|
return 0;
|
|
}
|