Advanced mmap test for IR FE (#18711)

* Advanced `mmap` test for IR FE

* Move memory functions to `CommonTestUtils`

* CppLint + ClangFormat

* Refactor IR FE `mmap` tests

1) Remove `compile_model` stage as not required, so also remove
"CPU" dependency
2) Run test in separate process to make RAM values more stable
3) Update RAM reference as "binsize / 2"

* Skip test on Apple platform

* Remove `getRssFileInKB()` as unused
This commit is contained in:
Vitaliy Urusovskij 2023-08-08 17:56:54 +04:00 committed by GitHub
parent e7565eda3e
commit 4e777b69c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 196 additions and 47 deletions

View File

@ -0,0 +1,121 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "common_test_utils/file_utils.hpp"
#include "frontend_test.hpp"
#include "openvino/opsets/opset1.hpp"
#ifndef __APPLE__ // TODO: add getVmRSSInKB() for Apple platform
class IRFrontendMMapTestsAdvanced : public ::testing::Test, public IRFrontendTestsImpl {
protected:
size_t binsize, REF_RSS;
void SetUp() override {
size_t SIZE_MB = 32;
size_t CONST_SIZE = SIZE_MB * 1024 * 1024 / sizeof(ov::element::f32);
auto parameter = std::make_shared<ov::opset1::Parameter>(ov::element::f32, ov::Shape{CONST_SIZE});
auto constant = std::make_shared<ov::opset1::Constant>(ov::element::f32,
ov::Shape{CONST_SIZE},
std::vector<float>(CONST_SIZE, 0));
auto add = std::make_shared<ov::opset1::Add>(parameter, constant);
auto result = std::make_shared<ov::opset1::Result>(add);
auto model = std::make_shared<ov::Model>(ov::NodeVector{result}, ov::ParameterVector{parameter});
auto filePrefix = ov::test::utils::generateTestFilePrefix();
xmlFileName = filePrefix + "_IrFrontendTestModel.xml";
binFileName = filePrefix + "_IrFrontendTestModel.bin";
ov::serialize(model, xmlFileName);
binsize = ov::test::utils::fileSize(binFileName) / 1024;
// In case of enabled `mmap` RAM should not increase more than 50% of .bin size
// Otherwise RAM should increase on at least 50% of .bin size
REF_RSS = binsize / 2;
}
void TearDown() override {
RemoveTemporalFiles();
}
};
TEST_F(IRFrontendMMapTestsAdvanced, core_enable_mmap_property) {
// Test checks that with enabled `mmap` .bin file
// isn't read into RAM on `read_model` stage.
// Otherwise, with disabled `mmap` .bin file should
// be in RAM
auto test = [&](const bool& is_mmap) {
core.set_property(ov::enable_mmap(is_mmap));
auto rss_init = ov::test::utils::getVmRSSInKB();
auto model = core.read_model(xmlFileName);
auto rss_read = ov::test::utils::getVmRSSInKB();
bool is_weights_read = (rss_read - rss_init) > REF_RSS;
if (is_mmap == is_weights_read) {
std::cerr << "Test failed: mmap is " << (is_mmap ? "enabled" : "disabled") << ", but weights are "
<< (is_weights_read ? "read" : "not read") << " in RAM" << std::endl;
exit(1);
}
std::cerr << "Test passed" << std::endl;
exit(0);
};
for (const auto is_mmap : {true, false})
// Run test in a separate process to not affect RAM values by previous tests
EXPECT_EXIT(test(is_mmap), ::testing::ExitedWithCode(0), "Test passed");
}
TEST_F(IRFrontendMMapTestsAdvanced, fe_read_ir_by_default) {
// Test checks that IR FE `read` IR by default,
// so .bin file should be loaded to RAM
auto test = [&]() {
ov::frontend::InputModel::Ptr input_model;
std::shared_ptr<ov::Model> model;
auto rss_init = ov::test::utils::getVmRSSInKB();
auto FE = manager.load_by_model(xmlFileName);
if (FE)
input_model = FE->load(xmlFileName);
if (input_model)
model = FE->convert(input_model);
auto rss_read = ov::test::utils::getVmRSSInKB();
bool is_weights_read = (rss_read - rss_init) > REF_RSS;
if (!is_weights_read) {
std::cerr << "Test failed: weights are not read; RAM consumption is less than expected" << std::endl;
exit(1);
}
std::cerr << "Test passed" << std::endl;
exit(0);
};
// Run test in a separate process to not affect RAM values by previous tests
ASSERT_EXIT(test(), ::testing::ExitedWithCode(0), "Test passed");
}
TEST_F(IRFrontendMMapTestsAdvanced, core_mmap_ir_by_default) {
// Test checks that Core uses `mmap` by default,
// so .bin file should not be loaded to RAM
auto test = [&]() {
auto rss_init = ov::test::utils::getVmRSSInKB();
auto model = core.read_model(xmlFileName, binFileName);
auto rss_read = ov::test::utils::getVmRSSInKB();
bool is_weights_mapped = (rss_read - rss_init) < REF_RSS;
if (!is_weights_mapped) {
std::cerr << "Test failed: weights are not mapped; RAM consumption is more than expected" << std::endl;
exit(1);
}
std::cerr << "Test passed" << std::endl;
exit(0);
};
// Run test in a separate process to not affect RAM values by previous tests
ASSERT_EXIT(test(), ::testing::ExitedWithCode(0), "Test passed");
}
#endif

View File

@ -188,6 +188,10 @@ inline std::ostream& operator<<(std::ostream& os, const std::map<std::string, st
}
std::string generateTestFilePrefix();
size_t getVmSizeInKB();
size_t getVmRSSInKB();
} // namespace utils
} // namespace test
} // namespace ov

View File

@ -8,6 +8,17 @@
#include "openvino/core/except.hpp"
#include "precomp.hpp"
#ifdef _WIN32
# ifndef NOMINMAX
# define NOMINMAX
# endif
# define _WINSOCKAPI_
# include <windows.h>
# include "psapi.h"
#endif
namespace ov {
namespace test {
namespace utils {
@ -34,12 +45,70 @@ std::string generateTestFilePrefix() {
testName += testInfo->name();
testName = std::to_string(std::hash<std::string>()(testName));
std::stringstream ss;
auto ts = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
auto ts = std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::high_resolution_clock::now().time_since_epoch());
ss << testName << "_" << std::this_thread::get_id() << "_" << ts.count();
testName = ss.str();
return testName;
}
#ifdef _WIN32
static PROCESS_MEMORY_COUNTERS getMemoryInfo() {
static PROCESS_MEMORY_COUNTERS pmc;
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, pmc.cb);
return pmc;
}
size_t getVmSizeInKB() {
return getMemoryInfo().PagefileUsage / 1024;
}
size_t getVmRSSInKB() {
return getMemoryInfo().WorkingSetSize / 1024;
}
#else
/// Parses number from provided string
static int parseLine(std::string line) {
std::string res = "";
for (auto c : line)
if (isdigit(c))
res += c;
if (res.empty())
// If number wasn't found return -1
return -1;
return std::stoi(res);
}
size_t getSystemDataByName(char* name) {
FILE* file = fopen("/proc/self/status", "r");
size_t result = 0;
if (file != nullptr) {
char line[128];
while (fgets(line, 128, file) != NULL) {
if (strncmp(line, name, strlen(name)) == 0) {
result = parseLine(line);
break;
}
}
fclose(file);
}
return result;
}
size_t getVmSizeInKB() {
return getSystemDataByName(const_cast<char*>("VmSize:"));
}
size_t getVmRSSInKB() {
return getSystemDataByName(const_cast<char*>("VmRSS:"));
}
#endif
} // namespace utils
} // namespace test
} // namespace ov

View File

@ -9,16 +9,6 @@
#include "openvino/runtime/threading/executor_manager.hpp"
#include "precomp.hpp"
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#define _WINSOCKAPI_
#include <windows.h>
#include "psapi.h"
#endif
#ifdef ENABLE_CONFORMANCE_PGQL
# include "common_test_utils/postgres_link.hpp"
#endif
@ -26,41 +16,6 @@
namespace ov {
namespace test {
inline size_t getVmSizeInKB() {
#ifdef _WIN32
PROCESS_MEMORY_COUNTERS pmc;
pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, pmc.cb);
return pmc.WorkingSetSize;
#else
auto parseLine = [](char *line) {
// This assumes that a digit will be found and the line ends in " Kb".
size_t i = strlen(line);
const char *p = line;
while (*p < '0' || *p > '9')
p++;
line[i - 3] = '\0';
i = (size_t) atoi(p);
return i;
};
FILE *file = fopen("/proc/self/status", "r");
size_t result = 0;
if (file != nullptr) {
char line[128];
while (fgets(line, 128, file) != NULL) {
if (strncmp(line, "VmSize:", 7) == 0) {
result = parseLine(line);
break;
}
}
fclose(file);
}
return result;
#endif
}
TestsCommon::~TestsCommon() {
ov::threading::executor_manager()->clear();
@ -75,7 +30,7 @@ TestsCommon::TestsCommon()
: PGLink(new utils::PostgreSQLLink(this))
#endif
{
auto memsize = getVmSizeInKB();
auto memsize = ov::test::utils::getVmSizeInKB();
if (memsize != 0) {
std::cout << "\nMEM_USAGE=" << memsize << "KB\n";
}