cpn: pruning-aware injection points
As we gain some degrees of freedom in choice of the specific injection instruction offset, this can be used to minimize navigational costs. This is a first approach towards pruning-aware injection points. To do so, we need to modify the sql query, which gets the pilots, so we additionally join with the trace table to get begin and end information for equivalence classes, which are feeded into the creation of InjectionPoints. Change-Id: I343b712dfcbed1299121f02eee9ce1b136a7ff15
This commit is contained in:
@ -112,16 +112,17 @@ void DatabaseCampaign::collect_result_thread() {
|
|||||||
bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
||||||
/* Gather all unfinished jobs */
|
/* Gather all unfinished jobs */
|
||||||
int experiment_count;
|
int experiment_count;
|
||||||
std::string sql_select = "SELECT pilot_id, g.fspmethod_id, g.variant_id, p.injection_instr, p.injection_instr_absolute, g.data_address, p.data_width ";
|
std::string sql_select = "SELECT p.id, p.fspmethod_id, p.variant_id, p.injection_instr, p.injection_instr_absolute, p.data_address, p.data_width, t.instr1, t.instr2 ";
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << " FROM fspgroup g"
|
ss << " FROM trace t, fsppilot p"
|
||||||
<< " INNER JOIN fsppilot p ON p.id = g.pilot_id "
|
<< " WHERE p.fspmethod_id = " << fspmethod_id
|
||||||
<< " WHERE p.known_outcome = 0 "
|
<< " AND p.variant_id = " << variant.id
|
||||||
<< " AND g.fspmethod_id = " << fspmethod_id
|
<< " AND (SELECT COUNT(*) FROM " + db_connect.result_table() + " as r WHERE r.pilot_id = p.id)"
|
||||||
<< " AND g.variant_id = " << variant.id
|
|
||||||
<< " AND (SELECT COUNT(*) FROM " + db_connect.result_table() + " as r WHERE r.pilot_id = g.pilot_id)"
|
|
||||||
<< " < " << expected_number_of_results(variant.variant, variant.benchmark)
|
<< " < " << expected_number_of_results(variant.variant, variant.benchmark)
|
||||||
<< " ORDER BY p.injection_instr";
|
<< " AND p.variant_id = t.variant_id"
|
||||||
|
<< " AND p.instr2 = t.instr2"
|
||||||
|
<< " AND p.data_address = t.data_address"
|
||||||
|
<< " ORDER BY t.instr1";
|
||||||
std::string sql_body = ss.str();
|
std::string sql_body = ss.str();
|
||||||
|
|
||||||
/* Get the number of unfinished experiments */
|
/* Get the number of unfinished experiments */
|
||||||
@ -146,6 +147,8 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
|||||||
unsigned injection_instr = atoi(row[3]);
|
unsigned injection_instr = atoi(row[3]);
|
||||||
unsigned data_address = strtoul(row[5], NULL, 10);
|
unsigned data_address = strtoul(row[5], NULL, 10);
|
||||||
unsigned data_width = atoi(row[6]);
|
unsigned data_width = atoi(row[6]);
|
||||||
|
unsigned instr1 = strtoul(row[7], NULL, 10);
|
||||||
|
unsigned instr2 = strtoul(row[8], NULL, 10);
|
||||||
|
|
||||||
|
|
||||||
DatabaseCampaignMessage pilot;
|
DatabaseCampaignMessage pilot;
|
||||||
@ -157,7 +160,7 @@ bool DatabaseCampaign::run_variant(Database::Variant variant) {
|
|||||||
pilot.set_variant(variant.variant);
|
pilot.set_variant(variant.variant);
|
||||||
pilot.set_benchmark(variant.benchmark);
|
pilot.set_benchmark(variant.benchmark);
|
||||||
|
|
||||||
ip.parseFromInjectionInstr(injection_instr);
|
ip.parseFromInjectionInstr(instr1, instr2);
|
||||||
ip.addToCampaignMessage(pilot);
|
ip.addToCampaignMessage(pilot);
|
||||||
|
|
||||||
if (row[4]) {
|
if (row[4]) {
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
#include "util/Logger.hpp"
|
#include "util/Logger.hpp"
|
||||||
#include "config/FailConfig.hpp"
|
#include "config/FailConfig.hpp"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,7 +28,7 @@ public:
|
|||||||
* Used by server.
|
* Used by server.
|
||||||
* @param inj_instr trace instruction offset to be parsed
|
* @param inj_instr trace instruction offset to be parsed
|
||||||
*/
|
*/
|
||||||
virtual void parseFromInjectionInstr(unsigned inj_instr) = 0;
|
virtual void parseFromInjectionInstr(unsigned instr1, unsigned instr2) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses (extracts) generic representation from a DatabaseCampaignMessage.
|
* Parses (extracts) generic representation from a DatabaseCampaignMessage.
|
||||||
@ -62,19 +64,28 @@ class SmartHops;
|
|||||||
class InjectionPointHops : public InjectionPointBase {
|
class InjectionPointHops : public InjectionPointBase {
|
||||||
private:
|
private:
|
||||||
SmartHops *m_sa; // !< Hop calculator which generates the hop chain
|
SmartHops *m_sa; // !< Hop calculator which generates the hop chain
|
||||||
uint32_t m_curr_inst; // !< Instruction for which currently a hop chain is available
|
|
||||||
|
// Boundaries must be signed to ensure, they can be initialized as outside of beginning
|
||||||
|
// of the trace (instr is -1).
|
||||||
|
long m_curr_instr1; // !< Lower end of instructions for which currently a hop chain is available
|
||||||
|
long m_curr_instr2; // !< Upper end of instructions for which currently a hop chain is available
|
||||||
|
|
||||||
bool m_initialized;
|
bool m_initialized;
|
||||||
|
std::vector<InjectionPointMessage> m_results;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
public:
|
public:
|
||||||
InjectionPointHops();
|
InjectionPointHops() : InjectionPointBase(), m_sa(NULL), m_curr_instr1(-1),
|
||||||
|
m_curr_instr2(-1), m_initialized(false) {}
|
||||||
|
|
||||||
virtual ~InjectionPointHops();
|
virtual ~InjectionPointHops();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a hop chain from a injection instruction (trace offset).
|
* Parses a hop chain from a injection instruction (trace offset).
|
||||||
* @param inj_instr trace instruction offset to be parsed
|
* @param instr1 trace instruction offset of beginning of equivalence class
|
||||||
|
* @param instr2 trace instruction offset of ending of equivalence class
|
||||||
*/
|
*/
|
||||||
virtual void parseFromInjectionInstr(unsigned inj_instr);
|
virtual void parseFromInjectionInstr(unsigned instr1, unsigned instr2);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef InjectionPointHops ConcreteInjectionPoint;
|
typedef InjectionPointHops ConcreteInjectionPoint;
|
||||||
@ -94,9 +105,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Parses a trace offset from a injection instruction (trace offset),
|
* Parses a trace offset from a injection instruction (trace offset),
|
||||||
* so it effectively just stores the value in the protobuf message.
|
* so it effectively just stores the value in the protobuf message.
|
||||||
* @param inj_instr trace instruction offset to be parsed
|
* @param instr1 trace instruction offset of beginning of equivalence class
|
||||||
|
* @param instr2 trace instruction offset of ending of equivalence class
|
||||||
*/
|
*/
|
||||||
virtual void parseFromInjectionInstr(unsigned inj_instr);
|
virtual void parseFromInjectionInstr(unsigned instr1, unsigned instr2);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef InjectionPointSteps ConcreteInjectionPoint;
|
typedef InjectionPointSteps ConcreteInjectionPoint;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
#include "InjectionPoint.hpp"
|
#include "InjectionPoint.hpp"
|
||||||
#include "util/smarthops/SmartHops.hpp"
|
#include "util/smarthops/SmartHops.hpp"
|
||||||
|
|
||||||
namespace fail {
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
InjectionPointHops::InjectionPointHops() : InjectionPointBase(), m_sa(NULL), m_curr_inst(0), m_initialized(false) {
|
namespace fail {
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
InjectionPointHops::~InjectionPointHops() {
|
InjectionPointHops::~InjectionPointHops() {
|
||||||
@ -15,7 +15,7 @@ InjectionPointHops::~InjectionPointHops() {
|
|||||||
void InjectionPointHops::init()
|
void InjectionPointHops::init()
|
||||||
{
|
{
|
||||||
m_sa = new SmartHops();
|
m_sa = new SmartHops();
|
||||||
m_curr_inst = 0;
|
|
||||||
char * elfpath = getenv("FAIL_TRACE_PATH");
|
char * elfpath = getenv("FAIL_TRACE_PATH");
|
||||||
if(elfpath == NULL){
|
if(elfpath == NULL){
|
||||||
m_log << "FAIL_TRACE_PATH not set :(" << std::endl;
|
m_log << "FAIL_TRACE_PATH not set :(" << std::endl;
|
||||||
@ -27,27 +27,73 @@ void InjectionPointHops::init()
|
|||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InjectionPointHops::parseFromInjectionInstr(unsigned inj_instr) {
|
/*
|
||||||
|
* if (!it->has_costs()) {
|
||||||
|
m_log << "FATAL ERROR: Costs must be delivered in order to calculate minimum costs" << endl;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void InjectionPointHops::parseFromInjectionInstr(unsigned instr1, unsigned instr2) {
|
||||||
if (!m_initialized) {
|
if (!m_initialized) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already calculated result needed?
|
// clear results older than instr1, as the input needs to be sorted by instr1, these
|
||||||
if (m_curr_inst == inj_instr) {
|
// results won't be needed anymore
|
||||||
return;
|
std::vector<InjectionPointMessage>::iterator it = m_results.begin(), delete_iterator = m_results.end();
|
||||||
}
|
for (; it != m_results.end(); it++) {
|
||||||
|
if (!it->has_target_trace_position()) {
|
||||||
// Non monotonic ascending injection instruction given?
|
m_log << "FATAL ERROR: Target trace offset must be delivered in order to calculate minimum costs" << std::endl;
|
||||||
if (m_curr_inst > inj_instr) {
|
}
|
||||||
m_log << "FATAL ERROR: Got not monotonic ascending values of injection instruction" << std::endl;
|
if (it->target_trace_position() < instr1) {
|
||||||
exit(-1);
|
delete_iterator = it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_sa->calculateFollowingHop(m_ip, inj_instr)) {
|
// Delete as chunk
|
||||||
m_log << "FATAL ERROR: Trace does not contain enough instructions (" << inj_instr << ")" << std::endl;
|
if (delete_iterator != m_results.end()) {
|
||||||
exit(-1);
|
m_results.erase(m_results.begin(), delete_iterator);
|
||||||
|
m_curr_instr1 = instr1;
|
||||||
}
|
}
|
||||||
m_curr_inst = inj_instr;
|
|
||||||
|
// Calculate next needed results
|
||||||
|
while (instr2 > m_curr_instr2) {
|
||||||
|
// if instr1 is bigger than nex instr2, we can skip instructions
|
||||||
|
// And current instr1 will be newly defined
|
||||||
|
unsigned new_curr_instr2;
|
||||||
|
if (instr1 > m_curr_instr2) {
|
||||||
|
m_curr_instr1 = instr1;
|
||||||
|
new_curr_instr2 = instr1;
|
||||||
|
} else {
|
||||||
|
new_curr_instr2 = m_curr_instr2 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
InjectionPointMessage m;
|
||||||
|
if (!m_sa->calculateFollowingHop(m, new_curr_instr2)) {
|
||||||
|
m_log << "FATAL ERROR: Trace does not contain enough instructions (no instruction with offset "
|
||||||
|
<< new_curr_instr2 << ")" << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_results.push_back(m);
|
||||||
|
m_curr_instr2 = new_curr_instr2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose minimum
|
||||||
|
InjectionPointMessage *min_cost_msg;
|
||||||
|
uint32_t min_costs = std::numeric_limits<uint32_t>::max();
|
||||||
|
|
||||||
|
std::vector<InjectionPointMessage>::iterator search, search_end;
|
||||||
|
search = m_results.begin() + (instr1 - m_curr_instr1);
|
||||||
|
search_end = m_results.begin() + (instr2 - m_curr_instr1);
|
||||||
|
|
||||||
|
for(;search != search_end; search++) {
|
||||||
|
if (search->costs() < min_costs) {
|
||||||
|
min_cost_msg = &(*search);
|
||||||
|
min_costs = search->costs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_ip = *min_cost_msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace fail */
|
} /* namespace fail */
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace fail {
|
namespace fail {
|
||||||
|
|
||||||
void InjectionPointSteps::parseFromInjectionInstr(unsigned inj_instr) {
|
void InjectionPointSteps::parseFromInjectionInstr(unsigned instr1, unsigned instr2) {
|
||||||
// compute hops
|
// compute hops
|
||||||
m_ip.set_injection_instr(inj_instr);
|
m_ip.set_injection_instr(instr2);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace fail */
|
} /* namespace fail */
|
||||||
|
|||||||
Reference in New Issue
Block a user