From 809eab37e358ecc583f384791acddbd28b4108c0 Mon Sep 17 00:00:00 2001
From: Maria Kotsifakou <kotsifa2@illinois.edu>
Date: Wed, 13 May 2020 20:11:31 -0500
Subject: [PATCH] Read and change frequency at the end of a batch. List of
 indices (and replication) of frequencies for the board currently hardcoded.

---
 .../include/hpvm-rt-controller.h              |  31 ++++-
 .../tensor_runtime/src/hpvm-rt-controller.cpp | 112 ++++++++++++++++--
 2 files changed, 132 insertions(+), 11 deletions(-)

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 669de46032..fbe350adb9 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
@@ -17,6 +17,7 @@
 #include <sys/stat.h>
 
 #define ACTIVE_PROFILING
+//#define JETSON_EXECUTION
 
 /*
  * Check if a file exists
@@ -24,6 +25,19 @@
  */
 bool fileExists(const std::string& file);
 
+class FrequencyIndexList {
+  private:
+    std::vector<int> idx_list;
+    unsigned rep_factor;
+
+    unsigned count;
+    unsigned idx;
+
+  public:
+    FrequencyIndexList(std::vector<int>, unsigned);
+    unsigned getNextIndex();
+};
+
 class ProfileInfo {
   private:
   // Members
@@ -47,6 +61,9 @@ class ProfileInfo {
   double energy_control_current_iteration; // Control
   double energy_config_current_iteration;  // Apply configuration
 
+  // Frequency of one loop iteration
+  unsigned long frequency_current_iteration;
+
   // Vectors, where compute time and energy information
   // - for each loop iteration (outer vector)
   // - per operation (inner vector)
@@ -68,7 +85,7 @@ class ProfileInfo {
   std::vector< double > config_energy_info;
 
   // Vector, where frequency information at the end of each iteration is stored
-  std::vector< double > frequency_info;
+  std::vector< unsigned long > frequency_info;
 
   bool in_iteration;
 
@@ -82,8 +99,6 @@ class ProfileInfo {
 
   void start_iteration();
 
-  double getIterationEndFrequency();
-
   public:
   void end_iteration();
 
@@ -107,6 +122,8 @@ class ProfileInfo {
 
   double getCurrentIterationComputeEnergy();
 
+  void readIterationFrequency();
+
   void set_out_file_name(std::string &str);
 
   void printToFile();
@@ -166,6 +183,10 @@ class RuntimeController {
   Profiler *profiler;
   Promise *promise;
 
+  // Frequency Index List: used to provide a list of indices, that are used to
+  // update the frequency of the Jetson board
+  FrequencyIndexList *FIL;
+
   //Functions
 
   // Private functions of profiler
@@ -222,6 +243,10 @@ class RuntimeController {
 
   double getCurrentIterationComputeEnergy();
 
+  void readIterationFrequency();
+
+  void updateFrequency();
+
   void writeProfileInfo();
 
   // Exposing functionality of (gpu) profiler
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 70f605f0ad..cc01caaef6 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
@@ -2,6 +2,60 @@
 #include "img_tensor_utils.h"
 #include "global_data.h"
 
+//-------- Functionality to read and update frequency on Jetson board -------//
+const char* available_freqs[] = {"140250000", "229500000", "318750000",
+                                 "408000000", "497250000", "586500000", 
+                                 "675750000", "765000000", "854250000",
+                                 "943500000", "1032750000", "1122000000",
+                                 "1211250000", "1300500000"};
+
+
+void updateJetsonGPUFreq(int freq_level) {
+
+  if (freq_level < 0 || freq_level > 13) {
+    printf("ERROR: Provide freq level between {0, 13}  \n\n\n");
+    abort();
+  }
+
+  const char* freq_val = available_freqs[freq_level]; 
+  printf("freq-val[0] = %s \n", freq_val);
+
+  FILE* max_file =
+    fopen("/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/max_freq", "w+");
+  if (max_file == NULL) {
+    printf("Could not min_freq file \n");
+  }
+  fwrite(freq_val, strlen(freq_val), 1, max_file);
+  fclose(max_file);
+  
+  FILE* min_file =
+    fopen("/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/min_freq", "w+");
+  if (min_file == NULL){
+    printf("Could not min_freq file \n");
+    abort();
+  }
+  fwrite(freq_val, strlen(freq_val), 1, min_file);
+  fclose(min_file);
+}
+
+unsigned long int readJetsonGPUFreq() {
+  FILE* cur_freq_file =
+    fopen("/sys/devices/17000000.gp10b/devfreq/17000000.gp10b/cur_freq", "r");
+  if (cur_freq_file == NULL) {
+    printf("Could not open cur_freq file \n");
+  }
+
+  char buf[50];
+  char* ptr;
+  
+  fread(buf, 50, 1, cur_freq_file);
+  unsigned long cur_freq = strtoul(buf, &ptr, 10);
+  fclose(cur_freq_file);
+  return cur_freq;
+}
+
+//---------------------------------------------------------------------------//
+
 /*
  * Check if a file exists
  * Return true if the file exists, false else
@@ -11,6 +65,18 @@ bool fileExists(const std::string &file) {
   return (stat(file.c_str(), &buf) == 0);
 }
 
+FrequencyIndexList::FrequencyIndexList(std::vector<int> il, unsigned rf) :
+  idx_list(il), rep_factor(rf), count(0), idx(0) {}
+
+unsigned FrequencyIndexList::getNextIndex() {
+  if (count == rep_factor) {
+    count = 0;
+    idx = (idx+1) % idx_list.size();
+  }
+  count++;
+  return idx_list[idx];
+}
+
 // Functions
 void ProfileInfo::resetCurrentIterationTime() {
   time_compute_current_iteration = 0.0;
@@ -59,15 +125,19 @@ void ProfileInfo::end_iteration() {
   control_energy_info.push_back(energy_control_current_iteration);
   config_time_info.push_back(time_config_current_iteration);
   config_energy_info.push_back(energy_config_current_iteration);
-  frequency_info.push_back(getIterationEndFrequency());
+
+  frequency_info.push_back(frequency_current_iteration);
 
   // Note end of iteration
   in_iteration = false;
 }
 
-double ProfileInfo::getIterationEndFrequency() {
-  return 0.0;
-  //TODO: if file exists read it else return 0.0
+void ProfileInfo::readIterationFrequency() {
+#ifdef JETSON_EXECUTION
+  frequency_current_iteration = readJetsonGPUFreq();
+#else
+  frequency_current_iteration = 0;
+#endif //JETSON_EXECUTION
 }
 
 void ProfileInfo::addToCurrentIterationComputeTime(const char *s, double t) {
@@ -188,7 +258,8 @@ ProfileInfo::ProfileInfo()
       time_control_current_iteration(0.0), time_config_current_iteration(0.0),
       energy_compute_current_iteration(0.0),
       energy_control_current_iteration(0.0),
-      energy_config_current_iteration(0.0), in_iteration(false) {}
+      energy_config_current_iteration(0.0),
+      frequency_current_iteration(0), in_iteration(false) {}
 
 Slowdowns::Slowdowns() {
   idx = 0;
@@ -340,6 +411,18 @@ double RuntimeController::getCurrentIterationComputeEnergy() {
   return (PI ? PI->getCurrentIterationComputeEnergy() : 0.0);
 }
 
+void RuntimeController::readIterationFrequency() {
+  if (PI)
+    PI->readIterationFrequency();
+}
+
+void RuntimeController::updateFrequency() {
+#ifdef JETSON_EXECUTION
+  unsigned freq_idx = FIL->getNextIndex();
+  updateJetsonGPUFreq(freq_idx);
+#endif //JETSON_EXECUTION
+}
+
 void RuntimeController::writeProfileInfo() {
   if (PI)
     PI->printToFile();
@@ -392,6 +475,7 @@ std::pair<double, double> RuntimeController::conv_profile(
 // Constructor and descructor
 RuntimeController::RuntimeController() {
   configurationIdx = 0;
+  FIL = new FrequencyIndexList({13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, 5);
 #ifdef ACTIVE_PROFILING
   PI = new ProfileInfo();
   profiler = new Profiler();
@@ -1192,13 +1276,11 @@ float hpvm_rt_computeAccuracy3(uint32_t *labels, void *result_ptr) {
 }
 
 
-#define llvm_hpvm_invokeRtControl_SLOWDOWN_PR llvm_hpvm_invokeRtControl
+#define llvm_hpvm_invokeRtControl_ADJUST_PR llvm_hpvm_invokeRtControl
 
 extern "C" void llvm_hpvm_invokeRtControl_BASE(
     void *result, const char *str, int start, int end) {
 
-  RC->resume_profiler();
-
   uint32_t *labels_cached = hpvm_rt_readLabelsBatch_cached(str, start, end);
   hpvm_rt_computeAccuracy3(labels_cached, result);
 
@@ -1206,7 +1288,9 @@ extern "C" void llvm_hpvm_invokeRtControl_BASE(
   double current_iteration_time = RC->getCurrentIterationComputeTime();
   double current_iteration_energy = RC->getCurrentIterationComputeEnergy();
 
+  RC->resume_profiler();
   RC->pause_profiler();
+
   std::pair<double, double> pinfo = RC->get_time_energy();
   RC->reset_profiler();
   RC->addToCurrentIterationControlTime(pinfo.first);
@@ -1261,6 +1345,7 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST(
 
   // Read stats for iteration that was just completed
   double current_iteration_energy = RC->getCurrentIterationComputeEnergy();
+  RC->readIterationFrequency();
 
   RC->resume_profiler();
   double current_iteration_time = RC->getCurrentIterationComputeTime();
@@ -1269,6 +1354,11 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST(
   RC->findTargetConfiguration(target_speedup, SPEEDUP);
   RC->pause_profiler();
 
+  //*                                                                        *
+  //*Needed for the frequency variation experiment - not part of the control *
+  RC->updateFrequency();
+  //*                                                                        */
+
   std::pair<double, double> pinfo = RC->get_time_energy();
   RC->reset_profiler();
   RC->addToCurrentIterationControlTime(pinfo.first);
@@ -1291,6 +1381,7 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST_PR(
 
   // Read stats for iteration that was just completed
   double current_iteration_energy = RC->getCurrentIterationComputeEnergy();
+  RC->readIterationFrequency();
 
   RC->resume_profiler();
   double current_iteration_time = RC->getCurrentIterationComputeTime();
@@ -1300,6 +1391,11 @@ extern "C" void llvm_hpvm_invokeRtControl_ADJUST_PR(
   RC->adjustTargetConfiguration(target_speedup);
   RC->pause_profiler();
 
+  //*                                                                        *
+  //*Needed for the frequency variation experiment - not part of the control *
+  RC->updateFrequency();
+  //*                                                                        */
+
   std::pair<double, double> pinfo = RC->get_time_energy();
   RC->reset_profiler();
   RC->addToCurrentIterationControlTime(pinfo.first);
-- 
GitLab