[CS/Refactor] Scrape ecore pipe from the train_
authorJihoon Lee <jhoon.it.lee@samsung.com>
Thu, 8 Oct 2020 06:53:07 +0000 (15:53 +0900)
committerJihoon Lee <jhoon.it.lee@samsung.com>
Mon, 12 Oct 2020 01:46:21 +0000 (10:46 +0900)
**Changes proposed in this PR:**
- Ecore Pipe is no longer used to update UI
- Broaden the canvas to make it easier to draw
- s/tries/epoch for training progress
- Minor bug fix that was generating warnings

**Self evaluation:**
1. Build test: [X]Passed [ ]Failed [ ]Skipped
2. Run test: [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: Jihoon Lee <jhoon.it.lee@samsung.com>
Applications/Tizen_native/CustomShortcut/inc/data.h
Applications/Tizen_native/CustomShortcut/inc/view.h
Applications/Tizen_native/CustomShortcut/src/data.c
Applications/Tizen_native/CustomShortcut/src/main.c
Applications/Tizen_native/CustomShortcut/src/view.c

index f1d0d71..6079e27 100644 (file)
@@ -82,11 +82,12 @@ typedef struct appdata {
   pthread_cond_t pipe_cond;  /**< pipe condition to block at a point */
 
   /**< Training related */
-  pthread_t tid_writer;         /**< thread handler to run trainer */
-  pthread_t tid_reader;         /**< thread handler to read train result */
-  int pipe_fd[2];               /**< fd for pipe */
-  Ecore_Pipe *data_output_pipe; /**< pipe to write information to ui */
-  double best_accuracy;         /**< stores best accuracy */
+  pthread_t tid_writer;       /**< thread handler to run trainer */
+  pthread_t tid_reader;       /**< thread handler to read train result */
+  int pipe_fd[2];             /**< fd for pipe */
+  double best_accuracy;       /**< stores best accuracy */
+  unsigned int current_epoch; /**< current epoch */
+  double train_loss;          /**< current loss */
 } appdata_s;
 
 typedef struct train_result {
@@ -173,9 +174,10 @@ void *data_run_model(void *ad);
  * @brief nntrainer update train result from data_run_model
  *
  * @param[in] ad appdata
- * @return not used
+ * @param[in] buf buffer hooked from stdout
+ * @return APP_ERROR_NONE if suceess
  */
-void *data_update_train_result(void *ad);
+int data_update_train_progress(appdata_s *ad, const char *buf);
 
 /**
  * @brief parse result string
@@ -190,7 +192,7 @@ void *data_update_train_result(void *ad);
  * #10/10 - Training Loss: 0.398767 >> [ Accuracy: 75% - Validation Loss :
  0.467543 ]
  */
-int data_parse_result_string(const char *src, train_result_s *train_result);
+int util_parse_result_string(const char *src, train_result_s *train_result);
 
 /**
  * @brief run inference with nnstreamer
index 224ed3c..6f74cf2 100644 (file)
@@ -31,7 +31,7 @@ int view_init(appdata_s *ad);
  * @param[in] ad appdata
  * @param[in] to pop until to is meet, if NULL pops only one time
  */
-void view_pop_naviframe(appdata_s *ad, const Elm_Object_Item *to);
+void view_pop_naviframe(appdata_s *ad, Elm_Object_Item *to);
 
 /**
  * @brief initiate canvas
@@ -57,17 +57,15 @@ void view_set_canvas_clean(appdata_s *ad);
 
 /**
  * @brief callback function to update training result
- * @param[in] data user data
- * @param[in] buffer arrays of null terminated characters
- * @param[in] nbytes max length of the buffer
+ * @param[in] data appdata
+ * @return Not used
  */
-void view_update_result_cb(void *data, void *buffer, unsigned int nbytes);
+void *view_update_train_progress(void *data);
 
 /**
  * @brief update guess from the inference result
  *
  * @param[in] ad appdata
- * @return int APP_ERROR_NONE if success
  */
 void view_update_guess(void *ad);
 
index a5e7ff6..bd3eed6 100644 (file)
@@ -465,37 +465,25 @@ CLEAN_UP:
   return NULL;
 }
 
-void *data_update_train_result(void *data) {
-  appdata_s *ad = (appdata_s *)data;
-
-  // run model in another thread
-  int read_fd = ad->pipe_fd[0];
-  FILE *fp;
-  char buf[255];
-
-  fp = fdopen(read_fd, "r");
-
-  LOG_D("start waiting to get result");
+int data_update_train_progress(appdata_s *ad, const char *buf) {
+  train_result_s result;
 
-  ecore_pipe_thaw(ad->data_output_pipe);
+  if (util_parse_result_string(buf, &result) != 0) {
+    LOG_W("parse failed. current buffer is being ignored");
+    return APP_ERROR_INVALID_PARAMETER;
+  }
 
-  while (fgets(buf, 255, fp) != NULL) {
-    if (ecore_pipe_write(ad->data_output_pipe, buf, 255) == false) {
-      LOG_E("pipe write error");
-      return NULL;
-    };
+  if (result.accuracy > ad->best_accuracy) {
+    ad->best_accuracy = result.accuracy;
   }
 
-  LOG_D("training finished");
-  fclose(fp);
-  close(read_fd);
-  sleep(1);
-  ecore_pipe_freeze(ad->data_output_pipe);
+  ad->current_epoch = result.epoch;
+  ad->train_loss = result.train_loss;
 
-  return NULL;
+  return APP_ERROR_NONE;
 }
 
-int data_parse_result_string(const char *src, train_result_s *train_result) {
+int util_parse_result_string(const char *src, train_result_s *train_result) {
   // clang-format off
   // #10/10 - Training Loss: 0.398767 >> [ Accuracy: 75% - Validation Loss : 0.467543 ]
   // clang-format on
index 12581c3..124f51a 100644 (file)
@@ -63,14 +63,15 @@ static void notify_train_done(void *data) {
 static void *train_(void *data) {
   int status = ML_ERROR_NONE;
   appdata_s *ad = (appdata_s *)data;
+  FILE *fp;
+  char buf[255];
+
   status = pipe(ad->pipe_fd);
   if (status < 0) {
     LOG_E("opening pipe for training failed");
     goto RESTORE_CB;
   }
 
-  ad->best_accuracy = 0.0;
-
   LOG_D("creating thread to run model");
   status = pthread_create(&ad->tid_writer, NULL, data_run_model, (void *)ad);
   if (status < 0) {
@@ -78,18 +79,17 @@ static void *train_(void *data) {
     goto RESTORE_CB;
   }
 
-  status =
-    pthread_create(&ad->tid_reader, NULL, data_update_train_result, (void *)ad);
-  if (status < 0) {
-    LOG_E("creating pthread failed %s", strerror(errno));
-    pthread_cancel(ad->tid_writer);
-    goto RESTORE_CB;
-  }
+  LOG_D("prepare to update the progress");
+  ad->best_accuracy = 0.0;
+  fp = fdopen(ad->pipe_fd[0], "r");
 
-  status = pthread_join(ad->tid_reader, NULL);
-  if (status < 0) {
-    LOG_E("joining reader thread failed %s", strerror(errno));
-    pthread_cancel(ad->tid_reader);
+  while (fgets(buf, 255, fp) != NULL) {
+    status = data_update_train_progress(ad, buf);
+    if (status != APP_ERROR_NONE) {
+      LOG_W("updating training progress failed");
+      continue;
+    }
+    ecore_main_loop_thread_safe_call_sync(view_update_train_progress, data);
   }
 
   status = pthread_join(ad->tid_writer, NULL);
@@ -98,6 +98,8 @@ static void *train_(void *data) {
     pthread_cancel(ad->tid_writer);
   }
 
+  fclose(fp);
+  close(ad->pipe_fd[0]);
 RESTORE_CB:
   ecore_main_loop_thread_safe_call_async(&notify_train_done, data);
   return NULL;
@@ -288,13 +290,6 @@ static bool app_create(void *data) {
 
   pthread_mutex_init(&ad->pipe_lock, NULL);
   pthread_cond_init(&ad->pipe_cond, NULL);
-  ad->data_output_pipe = ecore_pipe_add(view_update_result_cb, (void *)ad);
-  if (ad->data_output_pipe == NULL) {
-    LOG_E("making data out pipe failed");
-    free(data_path);
-    return false;
-  }
-
   util_get_resource_path(EDJ_PATH, ad->edj_path, false);
 
   LOG_D("changing root directory to %s", data_path);
@@ -312,8 +307,6 @@ static bool app_create(void *data) {
                                  eext_naviframe_more_cb, NULL);
 
   presenter_on_routes_request(data, NULL, NULL, "home");
-
-  LOG_D("layout: %x, nf_it: %x", ad->layout, ad->nf_it);
   ad->home = ad->nf_it;
 
   return true;
@@ -339,7 +332,6 @@ static void app_terminate(void *data) { /* Release all resources. */
 
   pthread_mutex_destroy(&ad->pipe_lock);
   pthread_cond_destroy(&ad->pipe_cond);
-  ecore_pipe_del(ad->data_output_pipe);
 }
 
 static void ui_app_lang_changed(app_event_info_h event_info, void *user_data) {
index 044347c..09018d5 100644 (file)
@@ -76,12 +76,10 @@ int view_init(appdata_s *ad) {
   ad->win = win;
   ad->conform = conform;
 
-  ecore_pipe_freeze(ad->data_output_pipe);
-
   return status;
 }
 
-void view_pop_naviframe(appdata_s *ad, const Elm_Object_Item *to) {
+void view_pop_naviframe(appdata_s *ad, Elm_Object_Item *to) {
   if (ad->nf_it == NULL || ad->nf_it == ad->home) {
     LOG_E("naviframe is null or at home, shutdown app instead");
     ui_app_exit();
@@ -97,7 +95,6 @@ void view_pop_naviframe(appdata_s *ad, const Elm_Object_Item *to) {
   ad->nf_it = elm_naviframe_top_item_get(ad->naviframe);
   ad->layout =
     elm_object_item_part_content_get(ad->nf_it, "elm.swallow.content");
-  LOG_D("item popped layout: %x nf_it: %x", ad->layout, ad->nf_it);
 }
 
 /**
@@ -257,8 +254,8 @@ int view_init_canvas(appdata_s *ad) {
     return APP_ERROR_INVALID_PARAMETER;
   }
 
-  evas_object_move(frame, 70, 70);
-  evas_object_resize(frame, 224, 224);
+  evas_object_move(frame, 0, 70);
+  evas_object_resize(frame, 360, 224);
   evas_object_show(frame);
   Evas_Coord width, height, x, y;
 
@@ -337,28 +334,20 @@ int view_init_canvas(appdata_s *ad) {
   return APP_ERROR_NONE;
 }
 
-void view_update_result_cb(void *data, void *buffer, unsigned int nbytes) {
+void *view_update_train_progress(void *data) {
   appdata_s *ad = (appdata_s *)data;
-
   char tmp[255];
 
-  train_result_s result;
-  if (data_parse_result_string(buffer, &result) != 0) {
-    LOG_W("parse failed. current buffer is being ignored");
-    return;
-  }
+  snprintf(tmp, 255, "%.0f%%", ad->best_accuracy);
+  elm_object_part_text_set(ad->layout, "train_progress/accuracy", tmp);
 
-  if (result.accuracy > ad->best_accuracy) {
-    ad->best_accuracy = result.accuracy;
-    snprintf(tmp, 255, "%.0f%%", ad->best_accuracy);
-    elm_object_part_text_set(ad->layout, "train_progress/accuracy", tmp);
-  }
-
-  snprintf(tmp, 255, "%d tries", result.epoch);
+  snprintf(tmp, 255, "%d epoch", ad->current_epoch);
   elm_object_part_text_set(ad->layout, "train_progress/epoch", tmp);
 
-  snprintf(tmp, 255, "Loss: %.2f", result.train_loss);
+  snprintf(tmp, 255, "Loss: %.2f", ad->train_loss);
   elm_object_part_text_set(ad->layout, "train_progress/loss", tmp);
+
+  return NULL;
 }
 
 void view_update_guess(void *data) {