RockyML  0.0.1
A High-Performance Scientific Computing Framework
log.h
1 /*
2  Copyright (C) 2022 Amirabbas Asadi , All Rights Reserved
3  distributed under Apache-2.0 license
4 */
5 #ifndef ROCKY_ZAGROS_LOG_STRATEGY
6 #define ROCKY_ZAGROS_LOG_STRATEGY
7 
8 #include<rocky/zagros/strategies/strategy.h>
9 #include<rocky/zagros/strategies/communication.h>
10 #include<nlohmann/json.hpp>
11 #include<cpr/cpr.h>
12 
13 #include<future>
14 #include<fstream>
15 #include<sstream>
16 
17 namespace rocky{
18 namespace zagros{
19 
24 template<typename T_e, int T_dim>
25 class logging_strategy: public basic_strategy<T_e, T_dim>{};
26 
28  std::string filename;
29  bool log_groups;
30  std::fstream log_output;
31  size_t step;
32  local_log_handler(std::string filename, bool log_groups=false){
33  this->filename = filename;
34  this->step = 0;
35  this->log_groups = log_groups;
36  // openning the log file
37  this->open();
38  // write the headers
39  this->write_header();
40  }
41  void open(){
42  // create a specific filename for this rank
43  int mpi_rank;
44  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
45  std::string process_spc_filename = fmt::format("proc_{}_{}", mpi_rank, filename);
46  // initialize the output file
47  log_output.open(process_spc_filename, std::fstream::out);
48  }
49  std::fstream& stream(){
50  return log_output;
51  }
52  void write_header(){
53  if (this->log_groups)
54  this->stream() << "step,group,best" << std::endl;
55  else
56  this->stream() << "step,best" << std::endl;
57  }
58  virtual void save(){
59  if(this->log_output.is_open())
60  this->log_output.close();
61  }
62  virtual ~local_log_handler(){
63  this->save();
64  }
65 };
66 
71 template<typename T_e, int T_dim>
72 class local_log_best: public logging_strategy<T_e, T_dim>{
73 protected:
74  system<T_e>* problem_;
75  basic_scontainer<T_e, T_dim>* container_;
76  local_log_handler* handler_;
77 
78 public:
80  this->problem_ = problem;
81  this->container_ = container;
82  this->handler_ = handler;
83 
84  }
85  virtual void write_header(){
86  if (this->handler_->log_groups)
87  this->handler_->stream() << "step,group,best" << std::endl;
88  else
89  this->handler_->stream() << "step,best" << std::endl;
90  }
91  virtual void apply(){
92  // find the best solution
93  T_e best = container_->best_min();
94  this->handler_->stream() << fmt::format("{},{}", this->handler_->step, best) << std::endl;
95  this->handler_->step++;
96  };
97 };
98 
100  std::string comet_api_key_;
101  std::string workspace_;
102  std::string project_;
103  std::string metric_name_;
104  std::string experiment_name_;
105  std::string experiment_link_;
106  std::string experiment_key_;
107 
108  comet_log_handler(std::string comet_api_key, std::string workspace, std::string project, std::string metric_name){
109  this->comet_api_key_ = comet_api_key;
110  this->workspace_ = workspace;
111  this->project_ = project;
112  this->metric_name_ = metric_name;
113  // we need to make sure in an MPI app only the root process will create the experiment
114  this->create_experiment();
115  }
116  void create_experiment(){
117  spdlog::info("creating comet experiment...");
118  // encoding experiment data
119  nlohmann::json experiment_data = {{"workspaceName", this->workspace_},
120  {"projectName", this->project_}};
121  // sending a post request for creating the experiment
122  cpr::Response r = cpr::Post(cpr::Url{"https://www.comet.com/api/rest/v2/write/experiment/create"},
123  cpr::Header{{"Authorization", this->comet_api_key_},
124  {"Content-type", "application/json"},
125  {"Accept", "application/json"}},
126  cpr::Body{experiment_data.dump()});
127  // warn the user if connection wasn't successful
128  this->connection_warning(r.status_code);
129  nlohmann::json rdata = nlohmann::json::parse(r.text);
130  // store the exepriment information
131  this->experiment_name_ = rdata["name"];
132  this->experiment_link_ = rdata["link"];
133  // experiment key will be needed for submitting metric values
134  this->experiment_key_ = rdata["experimentKey"];
135  std::string proc_metric_name = get_metric_name();
136  spdlog::info("{} experiment name : {}", proc_metric_name, this->experiment_name_);
137  spdlog::info("{} experiment link : {}", proc_metric_name, this->experiment_link_);
138  spdlog::info("{} experiment key : {}", proc_metric_name, this->experiment_key_);
139  }
140  void broadcast_experiment(){
141  // root process should broadcast the experiment info
142  int mpi_rank;
143  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
144  // a buffer for experiment key
145  char key_buffer[33];
146  if(mpi_rank == 0)
147  sprintf(key_buffer, "%.32s", experiment_key_.c_str());
148  spdlog::info("broadcasting experiment information to all processes...");
149  MPI_Bcast(key_buffer, 32, MPI_CHAR, 0, MPI_COMM_WORLD);
150  if(mpi_rank != 0){
151  experiment_key_ = std::string(key_buffer);
152  spdlog::info("process {} has the key : {}", mpi_rank, experiment_key_);
153  }
154  }
155  std::string get_metric_name(){
156  int mpi_rank;
157  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
158  std::string name = fmt::format("proc_{}_{}", mpi_rank, metric_name_);
159  return name;
160  }
161  void connection_warning(int status_code){
162  if(status_code != 200)
163  spdlog::warn("Error while connecting Comet server! request status code : {}", status_code);
164  }
165 };
166 
171 template<typename T_e, int T_dim>
172 class comet_strategy: public logging_strategy<T_e, T_dim>{};
173 
178 template<typename T_e, int T_dim>
179 class comet_log_best: public comet_strategy<T_e, T_dim>{
180 protected:
181  system<T_e>* problem_;
182  basic_scontainer<T_e, T_dim>* container_;
183  comet_log_handler* handler_;
184 
185 public:
187  this->problem_ = problem;
188  this->container_ = container;
189  this->handler_ = handler;
190  }
191  virtual void apply(){
192  // find the best solution
193  T_e best = container_->best_min();
194  // encode the metric data
195  nlohmann::json metric_data = {{"experimentKey", handler_->experiment_key_},
196  {"metricName", handler_->get_metric_name()},
197  {"metricValue", best}};
198 
199  cpr::Response r = cpr::Post(cpr::Url{"https://www.comet.com/api/rest/v2/write/experiment/metric"},
200  cpr::Header{{"Authorization", this->handler_->comet_api_key_},
201  {"Content-type", "application/json"},
202  {"Accept", "application/json"}},
203  cpr::Body{metric_data.dump()});
204  this->handler_->connection_warning(r.status_code);
205 
206  };
207 };
208 
209 };
210 };
211 #endif
rocky::zagros::comet_log_handler
Definition: log.h:99
rocky::zagros::comet_log_best
A strategy for logging the best solution on Comet server.
Definition: log.h:179
rocky::zagros::local_log_handler
Definition: log.h:27
rocky::zagros::logging_strategy
Interface for logging strategies.
Definition: log.h:25
rocky::zagros::basic_scontainer::best_min
T_e best_min()
find the best solution in the container
Definition: scontainer.h:182
rocky::zagros::basic_scontainer
a data container representing a scontainer
Definition: scontainer.h:31
rocky::zagros::system
Definition: system.h:20
rocky::zagros::basic_strategy
Interface for all strategies.
Definition: strategy.h:31
rocky::zagros::comet_strategy
Interface for Comet logging strategies.
Definition: log.h:172
rocky::zagros::local_log_best
Log the best solution in the container in a csv file.
Definition: log.h:72