summaryrefslogtreecommitdiff
path: root/runtime/libs/benchmark
diff options
context:
space:
mode:
authorChunseok Lee <chunseok.lee@samsung.com>2020-10-28 12:16:55 +0900
committerChunseok Lee <chunseok.lee@samsung.com>2020-10-28 12:16:55 +0900
commitc55f8a6db48cda9d3a78048338b7f18c4cca62b8 (patch)
tree761ee8e171e5203f5c598ad93b2e7e0bc2e31aa2 /runtime/libs/benchmark
parent74476a2d0296bdad70a2f7f90bc7419a8b05bffd (diff)
downloadnnfw-c55f8a6db48cda9d3a78048338b7f18c4cca62b8.tar.gz
nnfw-c55f8a6db48cda9d3a78048338b7f18c4cca62b8.tar.bz2
nnfw-c55f8a6db48cda9d3a78048338b7f18c4cca62b8.zip
Diffstat (limited to 'runtime/libs/benchmark')
-rw-r--r--runtime/libs/benchmark/include/benchmark/MemoryInfo.h40
-rw-r--r--runtime/libs/benchmark/include/benchmark/MemoryPoller.h4
-rw-r--r--runtime/libs/benchmark/include/benchmark/Phases.h5
-rw-r--r--runtime/libs/benchmark/include/benchmark/Result.h2
-rw-r--r--runtime/libs/benchmark/src/MemoryInfo.cpp169
-rw-r--r--runtime/libs/benchmark/src/MemoryPoller.cpp163
-rw-r--r--runtime/libs/benchmark/src/Phases.cpp8
-rw-r--r--runtime/libs/benchmark/src/Result.cpp12
8 files changed, 248 insertions, 155 deletions
diff --git a/runtime/libs/benchmark/include/benchmark/MemoryInfo.h b/runtime/libs/benchmark/include/benchmark/MemoryInfo.h
new file mode 100644
index 000000000..6e8e12ba4
--- /dev/null
+++ b/runtime/libs/benchmark/include/benchmark/MemoryInfo.h
@@ -0,0 +1,40 @@
+/*
+ * 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 __NNFW_BENCHMARK_MEMORY_INFO_H__
+#define __NNFW_BENCHMARK_MEMORY_INFO_H__
+
+#include <cstdint>
+#include <string>
+
+namespace benchmark
+{
+
+bool prepareVmRSS();
+bool prepareVmHWM();
+bool prepareGpuMemory();
+bool preparePssSum();
+
+uint32_t getVmRSS();
+uint32_t getVmHWM();
+uint32_t getGpuMemory(const std::string &process_name);
+uint32_t getPssSum();
+
+std::string getProcessName();
+
+} // namespace benchmark
+
+#endif // __NNFW_BENCHMARK_MEMORY_INFO_H__
diff --git a/runtime/libs/benchmark/include/benchmark/MemoryPoller.h b/runtime/libs/benchmark/include/benchmark/MemoryPoller.h
index 48caa3b3a..47db3fd77 100644
--- a/runtime/libs/benchmark/include/benchmark/MemoryPoller.h
+++ b/runtime/libs/benchmark/include/benchmark/MemoryPoller.h
@@ -57,10 +57,6 @@ public:
private:
void process();
bool prepareMemoryPolling();
- uint32_t getVmRSS();
- uint32_t getVmHWM();
- uint32_t getGpuMemory();
- uint32_t getPssSum();
private:
std::chrono::milliseconds _duration;
diff --git a/runtime/libs/benchmark/include/benchmark/Phases.h b/runtime/libs/benchmark/include/benchmark/Phases.h
index 936a89742..7d642782a 100644
--- a/runtime/libs/benchmark/include/benchmark/Phases.h
+++ b/runtime/libs/benchmark/include/benchmark/Phases.h
@@ -50,6 +50,9 @@ public:
const MemoryPoller &mem_poll() const { return *_mem_poll; }
const Phase &at(const std::string &tag) const { return _phases.at(tag); }
+ uint32_t mem_before_init() const { return _mem_before_init; }
+ uint32_t mem_after_run() const { return _mem_after_run; }
+
private:
void run(const std::string &tag, const PhaseFunc &exec, const PhaseFunc *post, uint32_t loop_num,
bool option_disable);
@@ -58,6 +61,8 @@ private:
const PhaseOption _option;
std::unordered_map<std::string, Phase> _phases;
std::unique_ptr<MemoryPoller> _mem_poll;
+ uint32_t _mem_before_init;
+ uint32_t _mem_after_run;
};
} // namespace benchmark
diff --git a/runtime/libs/benchmark/include/benchmark/Result.h b/runtime/libs/benchmark/include/benchmark/Result.h
index 69084b300..7604aa904 100644
--- a/runtime/libs/benchmark/include/benchmark/Result.h
+++ b/runtime/libs/benchmark/include/benchmark/Result.h
@@ -34,6 +34,8 @@ public:
double time[PhaseEnum::END_OF_PHASE][FigureType::END_OF_FIG_TYPE];
uint32_t memory[PhaseEnum::END_OF_PHASE][MemoryType::END_OF_MEM_TYPE];
bool print_memory = false;
+ uint32_t init_memory = 0;
+ uint32_t peak_memory = 0;
};
// TODO Support not only stdout but also ostream
diff --git a/runtime/libs/benchmark/src/MemoryInfo.cpp b/runtime/libs/benchmark/src/MemoryInfo.cpp
new file mode 100644
index 000000000..20d262961
--- /dev/null
+++ b/runtime/libs/benchmark/src/MemoryInfo.cpp
@@ -0,0 +1,169 @@
+/*
+ * 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 "benchmark/MemoryInfo.h"
+
+#include <vector>
+#include <algorithm>
+#include <fstream>
+#include <sstream>
+#include <cassert>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+namespace
+{
+
+const std::string proc_status_path("/proc/self/status");
+const std::string gpu_memory_path("/sys/kernel/debug/mali0/gpu_memory");
+const std::string proc_smaps_path("/proc/self/smaps");
+
+bool isStrNumber(const std::string &s)
+{
+ return !s.empty() &&
+ std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
+}
+
+std::vector<std::string> splitLine(std::string line, std::string delimiters = " \n\t")
+{
+ std::vector<std::string> words;
+ size_t prev = 0, pos;
+
+ while ((pos = line.find_first_of(delimiters, prev)) != std::string::npos)
+ {
+ if (pos > prev)
+ words.emplace_back(line.substr(prev, pos - prev));
+ prev = pos + 1;
+ }
+
+ if (prev < line.length())
+ words.emplace_back(line.substr(prev, std::string::npos));
+
+ return words;
+}
+
+std::vector<std::string> getValueFromFileStatus(const std::string &file, const std::string &key)
+{
+ std::ifstream ifs(file);
+ assert(ifs.is_open());
+
+ std::string line;
+ std::vector<std::string> val;
+
+ bool found = false;
+ while (std::getline(ifs, line))
+ {
+ if (line.find(key) != std::string::npos)
+ {
+ found = true;
+ break;
+ }
+ }
+ ifs.close();
+
+ if (!found)
+ {
+ // NOTE. the process which uses gpu resources cannot be there yet at the model-load phase.
+ // At that time, just return empty.
+ return val;
+ }
+
+ val = splitLine(line);
+ return val;
+}
+
+// Because of smaps' structure, returns sum value as uint32_t
+uint32_t getSumValueFromFileSmaps(const std::string &file, const std::string &key)
+{
+ std::ifstream ifs(file);
+ assert(ifs.is_open());
+
+ std::string line;
+ uint32_t sum = 0;
+ while (std::getline(ifs, line))
+ {
+ if (line.find(key) != std::string::npos)
+ {
+ // an example by splitLine()
+ // `Pss: 0 kB`
+ // val[0]: "Pss:", val[1]: "0" val[2]: "kB"
+ auto val = splitLine(line);
+ assert(val.size() != 0);
+ // SwapPss could show so that check where Pss is at the beginning
+ if (val[0].find("Pss") != 0)
+ {
+ continue;
+ }
+ sum += std::stoul(val[1]);
+ }
+ }
+
+ return sum;
+}
+
+} // namespace
+
+namespace benchmark
+{
+
+bool prepareVmRSS() { return std::ifstream(proc_status_path).is_open(); }
+
+bool prepareVmHWM() { return std::ifstream(proc_status_path).is_open(); }
+
+bool prepareGpuMemory() { return std::ifstream(gpu_memory_path).is_open(); }
+
+bool preparePssSum() { return std::ifstream(proc_smaps_path).is_open(); }
+
+uint32_t getVmRSS()
+{
+ auto val = getValueFromFileStatus(proc_status_path, "VmRSS");
+ if (val.size() == 0)
+ return 0;
+ assert(isStrNumber(val[1]));
+ return std::stoul(val[1]);
+}
+
+uint32_t getVmHWM()
+{
+ auto val = getValueFromFileStatus(proc_status_path, "VmHWM");
+ if (val.size() == 0)
+ return 0;
+ // key: value
+ assert(isStrNumber(val[1]));
+ return std::stoul(val[1]);
+}
+
+uint32_t getGpuMemory(const std::string &process_name)
+{
+ assert(!process_name.empty());
+ auto val = getValueFromFileStatus(gpu_memory_path, process_name);
+ if (val.size() == 0)
+ return 0;
+ // process_name -> pid -> gpu_mem -> max_gpu_mem
+ assert(isStrNumber(val[2]));
+ return std::stoul(val[2]);
+}
+
+uint32_t getPssSum() { return getSumValueFromFileSmaps(proc_smaps_path, "Pss"); }
+
+std::string getProcessName()
+{
+ auto val = getValueFromFileStatus(proc_status_path, "Name");
+ assert(val.size() >= 2);
+ return val[1];
+}
+
+} // namespace benchmark
diff --git a/runtime/libs/benchmark/src/MemoryPoller.cpp b/runtime/libs/benchmark/src/MemoryPoller.cpp
index 61fdecd46..050b5b163 100644
--- a/runtime/libs/benchmark/src/MemoryPoller.cpp
+++ b/runtime/libs/benchmark/src/MemoryPoller.cpp
@@ -16,106 +16,13 @@
#include "benchmark/MemoryPoller.h"
#include "benchmark/Types.h"
+#include "benchmark/MemoryInfo.h"
#include <vector>
-#include <fstream>
-#include <sstream>
#include <stdexcept>
#include <cassert>
#include <iostream>
-namespace
-{
-
-const std::string proc_status_path("/proc/self/status");
-const std::string gpu_memory_path("/sys/kernel/debug/mali0/gpu_memory");
-const std::string proc_smaps_path("/proc/self/smaps");
-
-bool isStrNumber(const std::string &s)
-{
- return !s.empty() &&
- std::find_if(s.begin(), s.end(), [](char c) { return !std::isdigit(c); }) == s.end();
-}
-
-std::vector<std::string> splitLine(std::string line, std::string delimiters = " \n\t")
-{
- std::vector<std::string> words;
- size_t prev = 0, pos;
-
- while ((pos = line.find_first_of(delimiters, prev)) != std::string::npos)
- {
- if (pos > prev)
- words.emplace_back(line.substr(prev, pos - prev));
- prev = pos + 1;
- }
-
- if (prev < line.length())
- words.emplace_back(line.substr(prev, std::string::npos));
-
- return words;
-}
-
-std::vector<std::string> getValueFromFileStatus(const std::string &file, const std::string &key)
-{
- std::ifstream ifs(file);
- assert(ifs.is_open());
-
- std::string line;
- std::vector<std::string> val;
-
- bool found = false;
- while (std::getline(ifs, line))
- {
- if (line.find(key) != std::string::npos)
- {
- found = true;
- break;
- }
- }
- ifs.close();
-
- if (!found)
- {
- // NOTE. the process which uses gpu resources cannot be there yet at the model-load phase.
- // At that time, just return empty.
- return val;
- }
-
- val = splitLine(line);
- return val;
-}
-
-// Because of smaps' structure, returns sum value as uint32_t
-uint32_t getSumValueFromFileSmaps(const std::string &file, const std::string &key)
-{
- std::ifstream ifs(file);
- assert(ifs.is_open());
-
- std::string line;
- uint32_t sum = 0;
- while (std::getline(ifs, line))
- {
- if (line.find(key) != std::string::npos)
- {
- // an example by splitLine()
- // `Pss: 0 kB`
- // val[0]: "Pss:", val[1]: "0" val[2]: "kB"
- auto val = splitLine(line);
- assert(val.size() != 0);
- // SwapPss could show so that check where Pss is at the beginning
- if (val[0].find("Pss") != 0)
- {
- continue;
- }
- sum += std::stoul(val[1]);
- }
- }
-
- return sum;
-}
-
-} // namespace
-
namespace benchmark
{
@@ -168,7 +75,7 @@ bool MemoryPoller::end(PhaseEnum phase)
mem = getVmRSS();
if (_gpu_poll)
{
- mem += getGpuMemory();
+ mem += getGpuMemory(_process_name);
}
if (mem > _rss_map[phase])
_rss_map[phase] = mem;
@@ -176,7 +83,7 @@ bool MemoryPoller::end(PhaseEnum phase)
mem = getVmHWM();
if (_gpu_poll)
{
- mem += getGpuMemory();
+ mem += getGpuMemory(_process_name);
}
_hwm_map[phase] = mem;
@@ -208,7 +115,7 @@ void MemoryPoller::process()
uint32_t cur_hwm = getVmHWM();
if (_gpu_poll)
{
- auto gpu_mem = getGpuMemory();
+ auto gpu_mem = getGpuMemory(_process_name);
cur_rss += gpu_mem;
cur_hwm += gpu_mem;
}
@@ -236,77 +143,33 @@ void MemoryPoller::process()
bool MemoryPoller::prepareMemoryPolling()
{
// VmRSS
+ if (!prepareVmRSS())
{
- std::ifstream ifs(proc_status_path);
- if (!ifs.is_open())
- {
- std::cerr << "failed to open " << proc_status_path << std::endl;
- return false;
- }
- ifs.close();
+ std::cerr << "failed to prepare parsing vmrss" << std::endl;
+ return false;
}
// (Additionally) GpuMemory
if (_gpu_poll)
{
- std::ifstream ifs(gpu_memory_path);
- if (!ifs.is_open())
+ if (!prepareGpuMemory())
{
- std::cerr << "failed to open " << gpu_memory_path << std::endl;
+ std::cerr << "failed to prepare parsing gpu memory" << std::endl;
return false;
}
- ifs.close();
// Needs process name
- auto val = getValueFromFileStatus(proc_status_path, "Name");
- assert(val.size() != 0);
- _process_name = val[1];
+ _process_name = getProcessName();
}
// PSS
+ if (!preparePssSum())
{
- std::ifstream ifs(proc_smaps_path);
- if (!ifs.is_open())
- {
- std::cerr << "failed to open " << proc_smaps_path << std::endl;
- return false;
- }
- ifs.close();
+ std::cerr << "failed to prepare parsing pss sum" << std::endl;
+ return false;
}
return true;
}
-uint32_t MemoryPoller::getVmRSS()
-{
- auto val = getValueFromFileStatus(proc_status_path, "VmRSS");
- if (val.size() == 0)
- return 0;
- assert(isStrNumber(val[1]));
- return std::stoul(val[1]);
-}
-
-uint32_t MemoryPoller::getVmHWM()
-{
- auto val = getValueFromFileStatus(proc_status_path, "VmHWM");
- if (val.size() == 0)
- return 0;
- // key: value
- assert(isStrNumber(val[1]));
- return std::stoul(val[1]);
-}
-
-uint32_t MemoryPoller::getGpuMemory()
-{
- assert(!_process_name.empty());
- auto val = getValueFromFileStatus(gpu_memory_path, _process_name);
- if (val.size() == 0)
- return 0;
- // process_name -> pid -> gpu_mem -> max_gpu_mem
- assert(isStrNumber(val[2]));
- return std::stoul(val[2]);
-}
-
-uint32_t MemoryPoller::getPssSum() { return getSumValueFromFileSmaps(proc_smaps_path, "Pss"); }
-
} // namespace benchmark
diff --git a/runtime/libs/benchmark/src/Phases.cpp b/runtime/libs/benchmark/src/Phases.cpp
index 9ab67cfd9..897b943d3 100644
--- a/runtime/libs/benchmark/src/Phases.cpp
+++ b/runtime/libs/benchmark/src/Phases.cpp
@@ -17,6 +17,7 @@
#include "benchmark/Phases.h"
#include "benchmark/Types.h"
+#include "benchmark/MemoryInfo.h"
#include <cassert>
#include <chrono>
@@ -46,8 +47,11 @@ void SleepForMicros(uint64_t micros)
namespace benchmark
{
-Phases::Phases(const PhaseOption &option) : _option(option)
+Phases::Phases(const PhaseOption &option) : _option(option), _mem_before_init(0), _mem_after_run(0)
{
+ assert(prepareVmRSS());
+ _mem_before_init = getVmHWM();
+
if (_option.memory)
{
_mem_poll = std::make_unique<MemoryPoller>(std::chrono::milliseconds(option.memory_interval),
@@ -93,6 +97,8 @@ void Phases::run(const std::string &tag, const PhaseFunc &exec, const PhaseFunc
}
}
+ _mem_after_run = getVmHWM();
+
if (p == PhaseEnum::END_OF_PHASE)
{
return;
diff --git a/runtime/libs/benchmark/src/Result.cpp b/runtime/libs/benchmark/src/Result.cpp
index df573da92..e6cafb91c 100644
--- a/runtime/libs/benchmark/src/Result.cpp
+++ b/runtime/libs/benchmark/src/Result.cpp
@@ -141,6 +141,15 @@ void printResultMemory(const uint32_t memory[benchmark::PhaseEnum::END_OF_PHASE]
}
}
+void printUsedPeakMemory(uint32_t init_memory, uint32_t peak_memory)
+{
+ uint32_t used_peak_memory = peak_memory - init_memory;
+ std::cout << "Used Peak Memory : " << used_peak_memory << " kb" << std::endl;
+ std::cout << "- HWM after run : " << peak_memory << " kb" << std::endl;
+ std::cout << "- HWM before init: " << init_memory << " kb" << std::endl;
+ std::cout << "===================================" << std::endl;
+}
+
} // namespace
namespace benchmark
@@ -175,6 +184,8 @@ Result::Result(const Phases &phases)
}
}
}
+ init_memory = phases.mem_before_init();
+ peak_memory = phases.mem_after_run();
}
void printResult(const Result &result)
@@ -185,6 +196,7 @@ void printResult(const Result &result)
return;
printResultMemory(result.memory);
+ printUsedPeakMemory(result.init_memory, result.peak_memory);
}
// TODO There are necessary for a kind of output data file so that it doesn't have to be csv file