diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h index fbe350adb98f815c99452c67a3d02dfbc6806272..f7d1018c9a2c7f25df642c8593b9612ae92dfa98 100644 --- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h +++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/include/hpvm-rt-controller.h @@ -7,6 +7,7 @@ #include <vector> #include <cstring> #include <cstdlib> +#include <random> #include "configuration.h" @@ -124,6 +125,8 @@ class ProfileInfo { void readIterationFrequency(); + unsigned long getIterationFrequency(); + void set_out_file_name(std::string &str); void printToFile(); @@ -177,6 +180,13 @@ class RuntimeController { Slowdowns *slowdowns; float pseudo_rd = 0.0; + std::mt19937 generator; + std::uniform_real_distribution<> distr; + + // Stored frequency and speedup for a running iteration. + // To be changed for a new frequency point + unsigned long g_freq = 0; + double g_speedup = 1.0; /*** Objects used to gather timing and energy information for execution ***/ ProfileInfo *PI; @@ -210,11 +220,21 @@ class RuntimeController { // For testing purposes only - do not use widely unsigned getConfigurationIdx(); + double getCurrentConfigurationSpeedup(); + double getCurrentConfigurationEnergy(); + double getCurrentConfigurationAccuracy(); + double getCurrentConfigurationAccuracyLoss(); + std::vector<float> &getQuantizationRanges(const char *data); NodeConfiguration *getNodeConfiguration(const char *data); // Functions for runtime control + unsigned long getLastFrequency(); + void setLastFrequency(unsigned long); + double getLastSpeedup(); + void setLastSpeedup(double); + void findNextConfiguration(); void findTargetConfiguration(float, enum SEARCH_KIND); void adjustTargetConfiguration(float); @@ -245,6 +265,8 @@ class RuntimeController { void readIterationFrequency(); + unsigned long getIterationFrequency(); + void updateFrequency(); void writeProfileInfo(); diff --git a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp index 813d77c46a51ede56dcc509495308637eb2ce862..9dba9ca15b2c267b505e6a3a72620b37e44c93e1 100644 --- a/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp +++ b/llvm/projects/hpvm-tensor-rt/tensor_runtime/src/hpvm-rt-controller.cpp @@ -1,16 +1,38 @@ + #include "hpvm-rt-controller.h" #include "img_tensor_utils.h" #include "global_data.h" +#include <fstream> //-------- Functionality to read and update frequency on Jetson board -------// -const char* available_freqs[] = {"140250000", "229500000", "318750000", +/*const char* available_freqs[] = {"140250000", "229500000", "318750000", "408000000", "497250000", "586500000", "675750000", "765000000", "854250000", "943500000", "1032750000", "1122000000", "1211250000", "1300500000"}; +*/ + + +const int available_freqs[] = { +140250000, // 0 +229500000, // 1 +318750000, // 2 +408000000, // 3 +497250000, // 4 +586500000, // 5 +675750000, // 6 +765000000, // 7 +854250000, // 8 +943500000, // 9 +1032750000,// 10 +1122000000,// 11 +1211250000,// 12 +1300500000 // 13 +}; + -void updateJetsonGPUFreq(int freq_level) { +/*void updateJetsonGPUFreq(int freq_level) { if (freq_level < 0 || freq_level > 13) { printf("ERROR: Provide freq level between {0, 13} \n\n\n"); @@ -55,6 +77,51 @@ unsigned long int readJetsonGPUFreq() { return cur_freq; } +*/ + + +// Sets frequency +void setFreq(unsigned freq_index) { + + unsigned target_freq = available_freqs[freq_index]; + + const char * const min_freq_file = "/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/min_freq"; + const char * const max_freq_file = "/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/max_freq"; + + std::ofstream min_stream; + std::ofstream max_stream; + + min_stream.open(min_freq_file, std::ofstream::out); + max_stream.open(max_freq_file, std::ofstream::out); + + min_stream << target_freq << std::flush; + max_stream << target_freq << std::flush; + + min_stream.close(); + max_stream.close(); +} + +// Records frequency +unsigned recordFreq() { + + // Current frequency file + const char * const cur_freq_file = "/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/cur_freq"; + std::ifstream cur_stream; + cur_stream.open(cur_freq_file, std::ifstream::in); + + // Get starting frequency + unsigned cur_freq; + cur_stream >> cur_freq; + std::cout << "Starting frequency = " << cur_freq << "\n"; + cur_stream.close(); + + return cur_freq; +} + + + + + //---------------------------------------------------------------------------// /* @@ -137,12 +204,17 @@ void ProfileInfo::end_iteration() { void ProfileInfo::readIterationFrequency() { #ifdef JETSON_EXECUTION - frequency_current_iteration = readJetsonGPUFreq(); + //----- frequency_current_iteration = readJetsonGPUFreq(); + frequency_current_iteration = recordFreq(); #else frequency_current_iteration = 0; #endif //JETSON_EXECUTION } +unsigned long ProfileInfo::getIterationFrequency() { + return frequency_current_iteration; +} + void ProfileInfo::addToCurrentIterationComputeTime(const char *s, double t) { start_iteration(); time_compute_current_iteration += t; @@ -321,6 +393,22 @@ getThreeDCurveConfigurations() { // For testing purposes only - do not use widely unsigned RuntimeController::getConfigurationIdx() { return configurationIdx; } +double RuntimeController::getCurrentConfigurationSpeedup() { + return (double) (*Configurations)[configurationIdx]->speedup; +} + +double RuntimeController::getCurrentConfigurationEnergy() { + return (double) (*Configurations)[configurationIdx]->energy; +} + +double RuntimeController::getCurrentConfigurationAccuracy() { + return (double) (*Configurations)[configurationIdx]->accuracy; +} + +double RuntimeController::getCurrentConfigurationAccuracyLoss() { + return (double) (*Configurations)[configurationIdx]->accuracyLoss; +} + std::vector<float> &RuntimeController::getQuantizationRanges(const char *data) { std::string s(data); // All nodes are expected to have quantization ranges @@ -356,7 +444,16 @@ void RuntimeController::init(const char *Cstr, const char *Qstr) { // Initializations for different runtime control strategies srand(static_cast<unsigned>(time(0))); slowdowns = new Slowdowns(); + + // Pseudo random variable (when we did few experiments) + // or true random numbers for probabilistic control pseudo_rd = 0.0; + std::random_device rd; //Will be used to obtain a seed for the random number engine + generator = std::mt19937 (rd()); //Standard mersenne_twister_engine seeded with rd() + distr = std::uniform_real_distribution<>(0.0, 1.0); + + g_freq = available_freqs[13]; + g_speedup = 1.0; // Initialize utility objects for knob reading perfParamSet = new PerfParamSet(); @@ -419,10 +516,17 @@ void RuntimeController::readIterationFrequency() { PI->readIterationFrequency(); } +unsigned long RuntimeController::getIterationFrequency() { + return (PI ? PI->getIterationFrequency() : 0); +} + void RuntimeController::updateFrequency() { #ifdef JETSON_EXECUTION unsigned freq_idx = FIL->getNextIndex(); - updateJetsonGPUFreq(freq_idx); + //--- updateJetsonGPUFreq(freq_idx); + + setFreq(freq_idx); + #endif //JETSON_EXECUTION } @@ -1076,6 +1180,22 @@ void RuntimeController::printConfigurations( } } +unsigned long RuntimeController::getLastFrequency() { + return g_freq; +} + +void RuntimeController::setLastFrequency(unsigned long f) { + g_freq = f; +} + +double RuntimeController::getLastSpeedup() { + return g_speedup; +} + +void RuntimeController::setLastSpeedup(double s) { + g_speedup = s; +} + void RuntimeController::findNextConfiguration() { configurationIdx = (configurationIdx + 1) % Configurations->size(); DEBUG( @@ -1157,6 +1277,41 @@ void RuntimeController::adjustTargetConfiguration(float goal) { } else { high_pb = low_range / sp_diff; low_pb = high_range / sp_diff; + + //***--- Probability adjustment strategy 1 ---***// + // No big adjustments at edges of probability range +// float adjust_val = 0.0; +// if (low_pb < high_pb) { +// adjust_val = low_pb * 0.2; +// } else { +// adjust_val = high_pb * 0.2; +// } +// low_pb -= adjust_val; +// high_pb += adjust_val; + //***--- ---***// + + //***--- Probability adjustment strategy 2 ---***// + // No big adjustment at high edge of probability range +// float adjust_val = high_pb * 0.2 > 0.1 ? 0.1 : high_pb * 0.2; +// low_pb -= adjust_val; +// high_pb += adjust_val; + //***--- ---***// + + //***--- Probability adjustment strategy 3 ---***// + //Similar to 2, but higher always increases, more significantly +// float adjust_val = low_pb * 0.5 > 0.1 ? 0.1 : low_pb * 0.5; +// low_pb -= adjust_val; +// high_pb += adjust_val; + //***--- ---***// + + //***--- Probability adjustment strategy 4 ---***// + //Similar to 2, but higher always increases, more significantly + // Low end, high end a bit less aggressive than total range + float adjust_val = low_pb * 0.6 > 0.2 ? 0.2 : low_pb * 0.6; + adjust_val = adjust_val > high_pb ? high_pb : adjust_val; + low_pb -= adjust_val; + high_pb += adjust_val; + //***--- ---***// } DEBUG( @@ -1171,8 +1326,9 @@ void RuntimeController::adjustTargetConfiguration(float goal) { // Select a random number from 0 to 1 // We assign the (0..low_pb) to the lower configuration, and the (low_pb..1) // to the upper - // float rd = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) ; - float rd = pseudo_rd; + // float rd = static_cast <float> (rand()) / static_cast <float> (RAND_MAX) ; + //float rd = pseudo_rd; + float rd = distr(generator); if (rd < low_pb) { // If the probability is in the low range configurationIdx = prev_conf_idx; @@ -1293,7 +1449,9 @@ float hpvm_rt_computeAccuracy3(uint32_t *labels, void *result_ptr) { } +//#define llvm_hpvm_invokeRtControl_BASE llvm_hpvm_invokeRtControl #define llvm_hpvm_invokeRtControl_ADJUST_PR llvm_hpvm_invokeRtControl +//#define llvm_hpvm_invokeRtControl_ADJUST llvm_hpvm_invokeRtControl extern "C" void llvm_hpvm_invokeRtControl_BASE( void *result, const char *str, int start, int end) { @@ -1366,8 +1524,18 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST( RC->resume_profiler(); double current_iteration_time = RC->getCurrentIterationComputeTime(); - double baseline_time = RC->getBaselineTime(); - double target_speedup = current_iteration_time / baseline_time; + double target_speedup; + if (RC->getLastFrequency() == RC->getIterationFrequency()) { + target_speedup = RC->getLastSpeedup(); + } else { + double baseline_time = RC->getBaselineTime(); + // Relative to current configuration + target_speedup = current_iteration_time / baseline_time; + // Adjust to baseline + target_speedup *= RC->getCurrentConfigurationSpeedup(); + RC->setLastFrequency(RC->getIterationFrequency()); + RC->setLastSpeedup(target_speedup); + } RC->findTargetConfiguration(target_speedup, SPEEDUP); RC->pause_profiler(); @@ -1409,8 +1577,18 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST_PR( RC->resume_profiler(); double current_iteration_time = RC->getCurrentIterationComputeTime(); - double baseline_time = RC->getBaselineTime(); - double target_speedup = current_iteration_time / baseline_time; + double target_speedup; + if (RC->getLastFrequency() == RC->getIterationFrequency()) { + target_speedup = RC->getLastSpeedup(); + } else { + double baseline_time = RC->getBaselineTime(); + // Relative to current configuration + target_speedup = current_iteration_time / baseline_time; + // Adjust to baseline + target_speedup *= RC->getCurrentConfigurationSpeedup(); + RC->setLastFrequency(RC->getIterationFrequency()); + RC->setLastSpeedup(target_speedup); + } RC->findTargetConfiguration(target_speedup, SPEEDUP); RC->adjustTargetConfiguration(target_speedup); RC->pause_profiler();