#include "inference_engine_common.h"
#include "inference_engine_type.h"
-#include "inference_engine_profiler.h"
+#include "inference_engine_common_profiler.h"
using namespace InferenceEngineInterface::Profiler;
--- /dev/null
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __INFERENCE_ENGINE_PROFILER_H__
+#define __INFERENCE_ENGINE_PROFILER_H__
+
+#include <vector>
+#include <map>
+#include <string>
+#include <time.h>
+
+#include "inference_engine_type.h"
+
+namespace InferenceEngineInterface {
+namespace Profiler {
+
+/**
+ * @brief Enumeration for how-to-dump to profile data.
+ *
+ * @since_tizen 6.0
+ *
+ */
+enum {
+ IE_PROFILER_DUMP_MIN,
+ // Profile data will be printed out on console screen.
+ IE_PROFILER_DUMP_CONSOLE,
+ // Profile data will be stored on a given file.
+ IE_PROFILER_DUMP_FILE,
+ IE_PROFILER_DUMP_MAX
+};
+
+/**
+ * @brief Enumeration for profile types.
+ *
+ * @since_tizen 6.0
+ *
+ */
+enum {
+ IE_PROFILER_MIN,
+ // Measure performance in millisecond.
+ IE_PROFILER_LATENCY,
+ // Measure physical memory usage.
+ IE_PROFILER_MEMORY,
+ IE_PROFILER_MAX
+};
+
+/**
+ * @brief Enumeration for dump format to profile data.
+ *
+ * @since_tizen 6.0
+ *
+ */
+enum {
+ IE_PROFILER_DUMP_FORMAT_MIN,
+ // Store profiling data to a given file in Markdown syntax[1]
+ // [1] https://daringfireball.net/projects/markdown/syntax
+ IE_PROFILER_DUMP_FORMAT_MARKDOWN,
+ IE_PROFILER_DUMP_FORMAT_MAX
+};
+
+/**
+ * @brief A structure of containg inference env.
+ * @details This structure contains inference information which says what env. the inference is being performed on.
+ *
+ * @since_tizen 6.0
+ */
+typedef struct _ProfileEnv {
+ std::string backend_name; /**< backend name such as armnn, tflite, opencv and dldt. */
+ std::string model_name; /**< model name which contains full path of a given model file. */
+ unsigned int target_devices; /**< Hardware type the inference will be performed on. */
+} ProfileEnv;
+
+/**
+ * @brief A structure of containg profiled elased time data.
+ * @details This structure contains profiling data while in inference.
+ *
+ * @since_tizen 6.0
+ */
+typedef struct _ProileData {
+ unsigned int env_idx; /**< An index of v_mProfileEnv vector.*/
+ std::string function_name; /**< A function name targetd to profile. */
+ unsigned int elapsed_time; /**< A latency to how long time a given function is performed. */
+} ProfileData;
+
+/**
+ * @brief A structure of containg profiled memory usage data.
+ * @details This structure contains profiling data while in inference.
+ *
+ * @since_tizen 6.0
+ */
+typedef struct _MemoryData {
+ long rss; /** A number of physical pages consumed by current process. */
+ long gpu_memory; /** A number of physical pages consumed by GPU device. */
+ // TODO.
+} MemoryData;
+
+/**
+ * @brief A class of representing profiler.
+ * @details This class interfaces will be called by InferenceEngineCommon class properly.
+ *
+ * @since_tizen 6.0
+ */
+class InferenceEngineProfiler {
+public:
+ InferenceEngineProfiler();
+ ~InferenceEngineProfiler();
+
+ /**
+ * @brief Set backend name.
+ * @details It will be set in BindBackend callback of InferenceEngineCommon object
+ * to indicate which backend - armnn, opencv, tflite or dldt - inference will be performed by.
+ *
+ * @since_tizen 6.0
+ * @param[in] name A backend name.
+ */
+ void AddBackendName(std::string &name) { mProfileEnv.backend_name = name; }
+
+ /**
+ * @brief Set model name.
+ * @details It will be set in Load callback of InferenceEngineCommon object to indicate which pre-trained model
+ * the inference will be performed on.
+ *
+ * @since_tizen 6.0
+ * @param[in] name A full path to model file.
+ */
+ void AddModelName(std::string &name) { mProfileEnv.model_name = name; }
+
+ /**
+ * @brief Set taget devices the inference runs on.
+ * @details It will be set in SetTargetDevices callback of InferenceEngineCommon object to indicate
+ * which Hardware - CPU or GPU - the inference will be performed on.
+ *
+ * @since_tizen 6.0
+ * @param[in] name A target device type. Please refer to inference_target_type_e enumeration of inference_engine_type.h.
+ */
+ void AddTargetDevices(unsigned int devices) { mProfileEnv.target_devices = devices; }
+
+ /**
+ * @brief Add inference env. information to a vector member, v_mProfileEnv.
+ * @details It will be called in Load callback of InferenceEngineCommon object to add inference env. information
+ * updated already to the vector member, which will be used to get inference env. information
+ * when dumping profile data.
+ *
+ * @since_tizen 6.0
+ */
+ void PushEnv(void) { v_mProfileEnv.push_back(mProfileEnv); mEnvNum++; }
+
+ /**
+ * @brief Start profiling with a given profile type.
+ * @details It will be called at top of a callback function of InferenceEngineCommon object to collect profile data.
+ *
+ * @since_tizen 6.0
+ * @param[in] type Profile type which can be IR_PROFILER_LATENCY or IR_PROFILER_MEMORY for now.
+ */
+ void Start(const unsigned int type);
+
+ /**
+ * @brief Stop profiling to a given profile type.
+ * @details It will be called at bottom of a callback function of InferenceEngineCommon object to collect profile data.
+ *
+ * @since_tizen 6.0
+ * @param[in] type Profile type which can be IR_PROFILER_LATENCY or IR_PROFILER_MEMORY for now.
+ * @param[in] env_idx A index to v_mProfileEnv vector object.
+ * @param[in] func_name A function name to be profiled.
+ */
+ void Stop(const unsigned int type, const char *func_name = "Unknown");
+
+ /**
+ * @brief Dump profiled data to console or a given file.
+ * @details It will be called in deconstructor of InferenceEngineCommon object to dump all of collected profile data.
+ *
+ * @since_tizen 6.0
+ * @param[in] dump_type A dump type which can be IR_PROFILER_DUMP_TEXT or IR_PROFILER_DUMP_FILE for now.
+ */
+ void Dump(const unsigned int dump_type);
+
+ /**
+ * @brief Set user-given dump file name.
+ * @details If a file name is set using this function then profiled data will be stored to the given file.
+ *
+ * @since_tizen 6.0
+ * @param[in] filename A name to user-given dump file.
+ */
+ void SetDumpFilename(const std::string filename) { mDumpFilename = filename; }
+
+private:
+ void PushData(ProfileData &data);
+ struct timespec GetTimeDiff(struct timespec &start, struct timespec &end);
+ unsigned long ConvertMillisec(const struct timespec &time);
+ void GetMemoryUsage(MemoryData &data);
+ void DumpToConsole(void);
+ void DumpToFile(const unsigned int dump_type, std::string filename);
+
+ struct timespec mStartTime, mEndTime;
+ unsigned int mEnvNum;
+ ProfileEnv mProfileEnv;
+ std::vector<ProfileEnv> v_mProfileEnv;
+ std::vector<ProfileData> v_mProfileData;
+ std::map<const char *, const void *> m_mDataTable;
+ std::string mDumpFilename;
+ MemoryData mStartMemoryData;
+ MemoryData mEndMemoryData;
+};
+} /* Profiler */
+} /* InferenceEngineInterface */
+
+#endif /* __INFERENCE_ENGINE_COMMON_H__ */
+++ /dev/null
-/**
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __INFERENCE_ENGINE_PROFILER_H__
-#define __INFERENCE_ENGINE_PROFILER_H__
-
-#include <vector>
-#include <map>
-#include <string>
-#include <time.h>
-
-#include "inference_engine_type.h"
-
-namespace InferenceEngineInterface {
-namespace Profiler {
-
-/**
- * @brief Enumeration for how-to-dump to profile data.
- *
- * @since_tizen 6.0
- *
- */
-enum {
- IE_PROFILER_DUMP_MIN,
- // Profile data will be printed out on console screen.
- IE_PROFILER_DUMP_CONSOLE,
- // Profile data will be stored on a given file.
- IE_PROFILER_DUMP_FILE,
- IE_PROFILER_DUMP_MAX
-};
-
-/**
- * @brief Enumeration for profile types.
- *
- * @since_tizen 6.0
- *
- */
-enum {
- IE_PROFILER_MIN,
- // Measure performance in millisecond.
- IE_PROFILER_LATENCY,
- // Measure physical memory usage.
- IE_PROFILER_MEMORY,
- IE_PROFILER_MAX
-};
-
-/**
- * @brief Enumeration for dump format to profile data.
- *
- * @since_tizen 6.0
- *
- */
-enum {
- IE_PROFILER_DUMP_FORMAT_MIN,
- // Store profiling data to a given file in Markdown syntax[1]
- // [1] https://daringfireball.net/projects/markdown/syntax
- IE_PROFILER_DUMP_FORMAT_MARKDOWN,
- IE_PROFILER_DUMP_FORMAT_MAX
-};
-
-/**
- * @brief A structure of containg inference env.
- * @details This structure contains inference information which says what env. the inference is being performed on.
- *
- * @since_tizen 6.0
- */
-typedef struct _ProfileEnv {
- std::string backend_name; /**< backend name such as armnn, tflite, opencv and dldt. */
- std::string model_name; /**< model name which contains full path of a given model file. */
- unsigned int target_devices; /**< Hardware type the inference will be performed on. */
-} ProfileEnv;
-
-/**
- * @brief A structure of containg profiled elased time data.
- * @details This structure contains profiling data while in inference.
- *
- * @since_tizen 6.0
- */
-typedef struct _ProileData {
- unsigned int env_idx; /**< An index of v_mProfileEnv vector.*/
- std::string function_name; /**< A function name targetd to profile. */
- unsigned int elapsed_time; /**< A latency to how long time a given function is performed. */
-} ProfileData;
-
-/**
- * @brief A structure of containg profiled memory usage data.
- * @details This structure contains profiling data while in inference.
- *
- * @since_tizen 6.0
- */
-typedef struct _MemoryData {
- long rss; /** A number of physical pages consumed by current process. */
- long gpu_memory; /** A number of physical pages consumed by GPU device. */
- // TODO.
-} MemoryData;
-
-/**
- * @brief A class of representing profiler.
- * @details This class interfaces will be called by InferenceEngineCommon class properly.
- *
- * @since_tizen 6.0
- */
-class InferenceEngineProfiler {
-public:
- InferenceEngineProfiler();
- ~InferenceEngineProfiler();
-
- /**
- * @brief Set backend name.
- * @details It will be set in BindBackend callback of InferenceEngineCommon object
- * to indicate which backend - armnn, opencv, tflite or dldt - inference will be performed by.
- *
- * @since_tizen 6.0
- * @param[in] name A backend name.
- */
- void AddBackendName(std::string &name) { mProfileEnv.backend_name = name; }
-
- /**
- * @brief Set model name.
- * @details It will be set in Load callback of InferenceEngineCommon object to indicate which pre-trained model
- * the inference will be performed on.
- *
- * @since_tizen 6.0
- * @param[in] name A full path to model file.
- */
- void AddModelName(std::string &name) { mProfileEnv.model_name = name; }
-
- /**
- * @brief Set taget devices the inference runs on.
- * @details It will be set in SetTargetDevices callback of InferenceEngineCommon object to indicate
- * which Hardware - CPU or GPU - the inference will be performed on.
- *
- * @since_tizen 6.0
- * @param[in] name A target device type. Please refer to inference_target_type_e enumeration of inference_engine_type.h.
- */
- void AddTargetDevices(unsigned int devices) { mProfileEnv.target_devices = devices; }
-
- /**
- * @brief Add inference env. information to a vector member, v_mProfileEnv.
- * @details It will be called in Load callback of InferenceEngineCommon object to add inference env. information
- * updated already to the vector member, which will be used to get inference env. information
- * when dumping profile data.
- *
- * @since_tizen 6.0
- */
- void PushEnv(void) { v_mProfileEnv.push_back(mProfileEnv); mEnvNum++; }
-
- /**
- * @brief Start profiling with a given profile type.
- * @details It will be called at top of a callback function of InferenceEngineCommon object to collect profile data.
- *
- * @since_tizen 6.0
- * @param[in] type Profile type which can be IR_PROFILER_LATENCY or IR_PROFILER_MEMORY for now.
- */
- void Start(const unsigned int type);
-
- /**
- * @brief Stop profiling to a given profile type.
- * @details It will be called at bottom of a callback function of InferenceEngineCommon object to collect profile data.
- *
- * @since_tizen 6.0
- * @param[in] type Profile type which can be IR_PROFILER_LATENCY or IR_PROFILER_MEMORY for now.
- * @param[in] env_idx A index to v_mProfileEnv vector object.
- * @param[in] func_name A function name to be profiled.
- */
- void Stop(const unsigned int type, const char *func_name = "Unknown");
-
- /**
- * @brief Dump profiled data to console or a given file.
- * @details It will be called in deconstructor of InferenceEngineCommon object to dump all of collected profile data.
- *
- * @since_tizen 6.0
- * @param[in] dump_type A dump type which can be IR_PROFILER_DUMP_TEXT or IR_PROFILER_DUMP_FILE for now.
- */
- void Dump(const unsigned int dump_type);
-
- /**
- * @brief Set user-given dump file name.
- * @details If a file name is set using this function then profiled data will be stored to the given file.
- *
- * @since_tizen 6.0
- * @param[in] filename A name to user-given dump file.
- */
- void SetDumpFilename(const std::string filename) { mDumpFilename = filename; }
-
-private:
- void PushData(ProfileData &data);
- struct timespec GetTimeDiff(struct timespec &start, struct timespec &end);
- unsigned long ConvertMillisec(const struct timespec &time);
- void GetMemoryUsage(MemoryData &data);
- void DumpToConsole(void);
- void DumpToFile(const unsigned int dump_type, std::string filename);
-
- struct timespec mStartTime, mEndTime;
- unsigned int mEnvNum;
- ProfileEnv mProfileEnv;
- std::vector<ProfileEnv> v_mProfileEnv;
- std::vector<ProfileData> v_mProfileData;
- std::map<const char *, const void *> m_mDataTable;
- std::string mDumpFilename;
- MemoryData mStartMemoryData;
- MemoryData mEndMemoryData;
-};
-} /* Profiler */
-} /* InferenceEngineInterface */
-
-#endif /* __INFERENCE_ENGINE_COMMON_H__ */
--- /dev/null
+/**
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "inference_engine_error.h"
+#include "inference_engine_common_profiler.h"
+#include <fstream>
+#include <iostream>
+#include <time.h>
+#include <unistd.h>
+
+extern "C" {
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "INFERENCE_ENGINE_PROFILER"
+}
+
+#define NANO_PER_SEC ((__clock_t) 1000000000)
+#define NANO_PER_MILLI ((__clock_t) 1000000)
+#define MILLI_PER_SEC ((__clock_t) 1000)
+
+namespace InferenceEngineInterface {
+namespace Profiler {
+
+// In default, we will use Markdown syntax to print out profile data.
+static const std::string sTitleMarkdown("backend|target devices|model name|Function name|Latency(ms)\n--|--|--|--|--\n");
+
+InferenceEngineProfiler::InferenceEngineProfiler()
+{
+ mStartTime = { 0, };
+ mEndTime = { 0, };
+ mEnvNum = 0;
+
+ // In default. we will store profile data to dump.txt file.
+ // If you want to use other file then use SetDumpFilename function to change the filename.
+ mDumpFilename = "dump.txt";
+
+ mStartMemoryData = {0, };
+ mEndMemoryData = {0, };
+}
+
+InferenceEngineProfiler::~InferenceEngineProfiler()
+{
+ v_mProfileEnv.clear();
+ v_mProfileData.clear();
+ m_mDataTable.clear();
+}
+
+void InferenceEngineProfiler::PushData(ProfileData &data)
+{
+ std::string key = std::to_string(mEnvNum - 1) + data.function_name;
+
+ // In case of multiple 'Run' per one 'Load', update just average value of measured ones instead of adding new one.
+ if (!m_mDataTable.empty()) {
+ std::map<const char *, const void *>::iterator iter;
+ iter = m_mDataTable.find(key.c_str());
+ if (iter != m_mDataTable.end()) {
+ ProfileData *item = (ProfileData *)iter->second;
+ item->elapsed_time = (item->elapsed_time + data.elapsed_time) >> 1;
+ return;
+ }
+ }
+
+ v_mProfileData.push_back(data);
+ m_mDataTable.insert(std::make_pair<const char *, const void *>(key.c_str(), &v_mProfileData.back()));
+}
+
+struct timespec InferenceEngineProfiler::GetTimeDiff(struct timespec &start,
+ struct timespec &end)
+{
+ struct timespec temp;
+
+ if ((end.tv_nsec - start.tv_nsec) < 0) {
+ temp.tv_sec = end.tv_sec - start.tv_sec - 1;
+ temp.tv_nsec = NANO_PER_SEC + end.tv_nsec - start.tv_nsec;
+ }
+ else {
+ temp.tv_sec = end.tv_sec - start.tv_sec;
+ temp.tv_nsec = end.tv_nsec - start.tv_nsec;
+ }
+
+ return temp;
+}
+
+unsigned long InferenceEngineProfiler::ConvertMillisec(const struct timespec &time)
+{
+ mStartTime.tv_nsec = 0;
+ mStartTime.tv_sec = 0;
+ mEndTime.tv_nsec = 0;
+ mEndTime.tv_sec = 0;
+
+ return (unsigned long)(time.tv_sec * MILLI_PER_SEC + time.tv_nsec / NANO_PER_MILLI);
+}
+
+void InferenceEngineProfiler::GetMemoryUsage(MemoryData &data)
+{
+ unsigned long resident_set = 0, rss = 0;
+
+ std::string ignore;
+ std::ifstream ifs("/proc/self/stat", std::ios_base::in);
+ ifs >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
+ >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
+ >> ignore >> ignore >> ignore >> rss;
+
+ resident_set = (rss * getpagesize()) / 1024;
+ data.rss = resident_set;
+
+ // TODO. Collect GPU memory usage specific to board in case of GPU acceleration.
+ //
+ // If current Linux kernel used Linux DMA mapping framework which is a generic solution for GPU memory management
+ // then we can get all memory usage.
+ // On the other hands, GPU driver on some boards may use reserved memory which is hided
+ // from Linux kernel memory subsystem so the memory usage cannot be measured in generic way.
+ // In this case, board specific interface is required.
+}
+
+void InferenceEngineProfiler::Start(const unsigned int type)
+{
+ if (IE_PROFILER_MIN >= type || IE_PROFILER_MAX <= type) {
+ LOGE("Invalid profiler type.");
+ return;
+ }
+
+ switch (type) {
+ case IE_PROFILER_LATENCY:
+ clock_gettime(CLOCK_MONOTONIC, &mStartTime);
+ break;
+ case IE_PROFILER_MEMORY:
+ mStartMemoryData = { 0, };
+ GetMemoryUsage(mStartMemoryData);
+ break;
+ /* TODO */
+ }
+}
+
+void InferenceEngineProfiler::Stop(const unsigned int type, const char *func_name)
+{
+ if (IE_PROFILER_MIN >= type || IE_PROFILER_MAX <= type) {
+ LOGE("Invalid profiler type.");
+ return;
+ }
+
+ ProfileData data = { mEnvNum - 1, func_name, 0 };
+
+ switch (type) {
+ case IE_PROFILER_LATENCY: {
+ clock_gettime(CLOCK_MONOTONIC, &mEndTime);
+ data.elapsed_time = ConvertMillisec(GetTimeDiff(mStartTime, mEndTime));
+ // TODO.
+ PushData(data);
+ break;
+ }
+ case IE_PROFILER_MEMORY:
+ mEndMemoryData = { 0, };
+ GetMemoryUsage(mEndMemoryData);
+ break;
+ /* TODO */
+ }
+}
+
+void InferenceEngineProfiler::DumpToConsole(void)
+{
+ std::cout << sTitleMarkdown;
+
+ std::vector<ProfileData>::iterator iter;
+ for (iter = v_mProfileData.begin(); iter != v_mProfileData.end(); iter++) {
+ ProfileData data = *iter;
+ ProfileEnv env = v_mProfileEnv[data.env_idx];
+ std::cout << env.backend_name << "|" << env.target_devices << "|" << env.model_name << "|";
+ std::cout << data.function_name << "|" << data.elapsed_time << "\n";
+ }
+
+ std::cout << "***" << "\n";
+ std::cout << "Memory Usage(kb) : " << mEndMemoryData.rss - mStartMemoryData.rss << "\n";
+ std::cout << "***" << "\n";
+}
+
+void InferenceEngineProfiler::DumpToFile(const unsigned int dump_type, std::string filename)
+{
+ if (mDumpFilename.empty())
+ mDumpFilename = filename;
+
+ std::ofstream dump_file;
+
+ dump_file.open(mDumpFilename, std::ios::binary | std::ios::app);
+ if (dump_file.is_open()) {
+ dump_file.write(sTitleMarkdown.c_str(), sTitleMarkdown.length());
+
+ std::vector<ProfileData>::iterator iter;
+ for (iter = v_mProfileData.begin(); iter != v_mProfileData.end(); iter++) {
+ ProfileData data = *iter;
+ ProfileEnv env = v_mProfileEnv[data.env_idx];
+ dump_file.write(env.backend_name.c_str(), env.backend_name.length());
+ dump_file.write("|", 1);
+ if (env.target_devices & INFERENCE_TARGET_CPU)
+ dump_file.write("CPU", 3);
+ if (env.target_devices & INFERENCE_TARGET_GPU)
+ dump_file.write("GPU", 3);
+ dump_file.write("|", 1);
+ dump_file.write(env.model_name.c_str(), env.model_name.length());
+ dump_file.write("|", 1);
+ dump_file.write(data.function_name.c_str(), data.function_name.length());
+ dump_file.write("|", 1);
+ std::string sElapsedTime(std::to_string(data.elapsed_time));
+ dump_file.write(sElapsedTime.c_str(), sElapsedTime.length());
+ dump_file.write("\n", 1);
+ }
+
+ dump_file.write("***\n", 4);
+ std::string sMemoryUsage = std::to_string(mEndMemoryData.rss - mStartMemoryData.rss) + "KB Memory used";
+ dump_file.write(sMemoryUsage.c_str(), sMemoryUsage.length());
+ dump_file.write("\n", 1);
+ dump_file.write("***\n", 4);
+ }
+
+ dump_file.close();
+}
+
+void InferenceEngineProfiler::Dump(const unsigned int dump_type)
+{
+ if (IE_PROFILER_DUMP_MIN >= dump_type || IE_PROFILER_DUMP_MAX <= dump_type) {
+ LOGE("Invalid profiler dump type.");
+ return;
+ }
+
+ if (dump_type == IE_PROFILER_DUMP_CONSOLE) {
+ DumpToConsole();
+ } else {
+ DumpToFile(IE_PROFILER_DUMP_FORMAT_MARKDOWN, mDumpFilename);
+ }
+}
+
+} /* Profiler */
+} /* InferenceEngineInterface */
+++ /dev/null
-/**
- * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "inference_engine_error.h"
-#include "inference_engine_profiler.h"
-#include <fstream>
-#include <iostream>
-#include <time.h>
-#include <unistd.h>
-
-extern "C" {
-
-#include <dlog.h>
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-
-#define LOG_TAG "INFERENCE_ENGINE_PROFILER"
-}
-
-#define NANO_PER_SEC ((__clock_t) 1000000000)
-#define NANO_PER_MILLI ((__clock_t) 1000000)
-#define MILLI_PER_SEC ((__clock_t) 1000)
-
-namespace InferenceEngineInterface {
-namespace Profiler {
-
-// In default, we will use Markdown syntax to print out profile data.
-static const std::string sTitleMarkdown("backend|target devices|model name|Function name|Latency(ms)\n--|--|--|--|--\n");
-
-InferenceEngineProfiler::InferenceEngineProfiler()
-{
- mStartTime = { 0, };
- mEndTime = { 0, };
- mEnvNum = 0;
-
- // In default. we will store profile data to dump.txt file.
- // If you want to use other file then use SetDumpFilename function to change the filename.
- mDumpFilename = "dump.txt";
-
- mStartMemoryData = {0, };
- mEndMemoryData = {0, };
-}
-
-InferenceEngineProfiler::~InferenceEngineProfiler()
-{
- v_mProfileEnv.clear();
- v_mProfileData.clear();
- m_mDataTable.clear();
-}
-
-void InferenceEngineProfiler::PushData(ProfileData &data)
-{
- std::string key = std::to_string(mEnvNum - 1) + data.function_name;
-
- // In case of multiple 'Run' per one 'Load', update just average value of measured ones instead of adding new one.
- if (!m_mDataTable.empty()) {
- std::map<const char *, const void *>::iterator iter;
- iter = m_mDataTable.find(key.c_str());
- if (iter != m_mDataTable.end()) {
- ProfileData *item = (ProfileData *)iter->second;
- item->elapsed_time = (item->elapsed_time + data.elapsed_time) >> 1;
- return;
- }
- }
-
- v_mProfileData.push_back(data);
- m_mDataTable.insert(std::make_pair<const char *, const void *>(key.c_str(), &v_mProfileData.back()));
-}
-
-struct timespec InferenceEngineProfiler::GetTimeDiff(struct timespec &start,
- struct timespec &end)
-{
- struct timespec temp;
-
- if ((end.tv_nsec - start.tv_nsec) < 0) {
- temp.tv_sec = end.tv_sec - start.tv_sec - 1;
- temp.tv_nsec = NANO_PER_SEC + end.tv_nsec - start.tv_nsec;
- }
- else {
- temp.tv_sec = end.tv_sec - start.tv_sec;
- temp.tv_nsec = end.tv_nsec - start.tv_nsec;
- }
-
- return temp;
-}
-
-unsigned long InferenceEngineProfiler::ConvertMillisec(const struct timespec &time)
-{
- mStartTime.tv_nsec = 0;
- mStartTime.tv_sec = 0;
- mEndTime.tv_nsec = 0;
- mEndTime.tv_sec = 0;
-
- return (unsigned long)(time.tv_sec * MILLI_PER_SEC + time.tv_nsec / NANO_PER_MILLI);
-}
-
-void InferenceEngineProfiler::GetMemoryUsage(MemoryData &data)
-{
- unsigned long resident_set = 0, rss = 0;
-
- std::string ignore;
- std::ifstream ifs("/proc/self/stat", std::ios_base::in);
- ifs >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
- >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore >> ignore
- >> ignore >> ignore >> ignore >> rss;
-
- resident_set = (rss * getpagesize()) / 1024;
- data.rss = resident_set;
-
- // TODO. Collect GPU memory usage specific to board in case of GPU acceleration.
- //
- // If current Linux kernel used Linux DMA mapping framework which is a generic solution for GPU memory management
- // then we can get all memory usage.
- // On the other hands, GPU driver on some boards may use reserved memory which is hided
- // from Linux kernel memory subsystem so the memory usage cannot be measured in generic way.
- // In this case, board specific interface is required.
-}
-
-void InferenceEngineProfiler::Start(const unsigned int type)
-{
- if (IE_PROFILER_MIN >= type || IE_PROFILER_MAX <= type) {
- LOGE("Invalid profiler type.");
- return;
- }
-
- switch (type) {
- case IE_PROFILER_LATENCY:
- clock_gettime(CLOCK_MONOTONIC, &mStartTime);
- break;
- case IE_PROFILER_MEMORY:
- mStartMemoryData = { 0, };
- GetMemoryUsage(mStartMemoryData);
- break;
- /* TODO */
- }
-}
-
-void InferenceEngineProfiler::Stop(const unsigned int type, const char *func_name)
-{
- if (IE_PROFILER_MIN >= type || IE_PROFILER_MAX <= type) {
- LOGE("Invalid profiler type.");
- return;
- }
-
- ProfileData data = { mEnvNum - 1, func_name, 0 };
-
- switch (type) {
- case IE_PROFILER_LATENCY: {
- clock_gettime(CLOCK_MONOTONIC, &mEndTime);
- data.elapsed_time = ConvertMillisec(GetTimeDiff(mStartTime, mEndTime));
- // TODO.
- PushData(data);
- break;
- }
- case IE_PROFILER_MEMORY:
- mEndMemoryData = { 0, };
- GetMemoryUsage(mEndMemoryData);
- break;
- /* TODO */
- }
-}
-
-void InferenceEngineProfiler::DumpToConsole(void)
-{
- std::cout << sTitleMarkdown;
-
- std::vector<ProfileData>::iterator iter;
- for (iter = v_mProfileData.begin(); iter != v_mProfileData.end(); iter++) {
- ProfileData data = *iter;
- ProfileEnv env = v_mProfileEnv[data.env_idx];
- std::cout << env.backend_name << "|" << env.target_devices << "|" << env.model_name << "|";
- std::cout << data.function_name << "|" << data.elapsed_time << "\n";
- }
-
- std::cout << "***" << "\n";
- std::cout << "Memory Usage(kb) : " << mEndMemoryData.rss - mStartMemoryData.rss << "\n";
- std::cout << "***" << "\n";
-}
-
-void InferenceEngineProfiler::DumpToFile(const unsigned int dump_type, std::string filename)
-{
- if (mDumpFilename.empty())
- mDumpFilename = filename;
-
- std::ofstream dump_file;
-
- dump_file.open(mDumpFilename, std::ios::binary | std::ios::app);
- if (dump_file.is_open()) {
- dump_file.write(sTitleMarkdown.c_str(), sTitleMarkdown.length());
-
- std::vector<ProfileData>::iterator iter;
- for (iter = v_mProfileData.begin(); iter != v_mProfileData.end(); iter++) {
- ProfileData data = *iter;
- ProfileEnv env = v_mProfileEnv[data.env_idx];
- dump_file.write(env.backend_name.c_str(), env.backend_name.length());
- dump_file.write("|", 1);
- if (env.target_devices & INFERENCE_TARGET_CPU)
- dump_file.write("CPU", 3);
- if (env.target_devices & INFERENCE_TARGET_GPU)
- dump_file.write("GPU", 3);
- dump_file.write("|", 1);
- dump_file.write(env.model_name.c_str(), env.model_name.length());
- dump_file.write("|", 1);
- dump_file.write(data.function_name.c_str(), data.function_name.length());
- dump_file.write("|", 1);
- std::string sElapsedTime(std::to_string(data.elapsed_time));
- dump_file.write(sElapsedTime.c_str(), sElapsedTime.length());
- dump_file.write("\n", 1);
- }
-
- dump_file.write("***\n", 4);
- std::string sMemoryUsage = std::to_string(mEndMemoryData.rss - mStartMemoryData.rss) + "KB Memory used";
- dump_file.write(sMemoryUsage.c_str(), sMemoryUsage.length());
- dump_file.write("\n", 1);
- dump_file.write("***\n", 4);
- }
-
- dump_file.close();
-}
-
-void InferenceEngineProfiler::Dump(const unsigned int dump_type)
-{
- if (IE_PROFILER_DUMP_MIN >= dump_type || IE_PROFILER_DUMP_MAX <= dump_type) {
- LOGE("Invalid profiler dump type.");
- return;
- }
-
- if (dump_type == IE_PROFILER_DUMP_CONSOLE) {
- DumpToConsole();
- } else {
- DumpToFile(IE_PROFILER_DUMP_FORMAT_MARKDOWN, mDumpFilename);
- }
-}
-
-} /* Profiler */
-} /* InferenceEngineInterface */