diff --git a/modules/dnn/src/layers/convolution_layer.cpp b/modules/dnn/src/layers/convolution_layer.cpp index a950ea18c2..d0791ecddd 100644 --- a/modules/dnn/src/layers/convolution_layer.cpp +++ b/modules/dnn/src/layers/convolution_layer.cpp @@ -1299,6 +1299,10 @@ public: fastConvImpl = initFastConv(weightsMat, &biasvec[0], ngroups, K, C, kernel_size, strides, dilations, pads_begin, pads_end, conv_dim, preferableTarget == DNN_TARGET_CPU_FP16, canUseWinograd); + // This is legal to release weightsMat here as this is not used anymore for + // OpenCV inference. If network needs to be reinitialized (new shape, new backend) + // a new version of weightsMat is created at .finalize() from original weights + weightsMat.release(); } runFastConv(inputs[0], outputs[0], fastConvImpl, nstripes, activ, reluslope, fusedAdd); @@ -1405,6 +1409,7 @@ public: params.set("input_zeropoint", inputZp); params.set("input_scale", inputScale); + Mat weightsMat = blobs[0].reshape(1, numOutput); Mat weightsQuantized(weightsMat.rows, weightsMat.cols, CV_8S); Mat biasQuantized(1, numOutput, CV_32S); Mat outputMultiplier(1, numOutput, CV_32F); diff --git a/modules/dnn/test/test_common.hpp b/modules/dnn/test/test_common.hpp index 6262a0f7a4..435f481566 100644 --- a/modules/dnn/test/test_common.hpp +++ b/modules/dnn/test/test_common.hpp @@ -232,6 +232,8 @@ public: expectNoFallbacks(net); } + size_t getTopMemoryUsageMB(); + protected: void checkBackend(Mat* inp = 0, Mat* ref = 0) { diff --git a/modules/dnn/test/test_common.impl.hpp b/modules/dnn/test/test_common.impl.hpp index 2a4ee34b02..e78dc6c1e4 100644 --- a/modules/dnn/test/test_common.impl.hpp +++ b/modules/dnn/test/test_common.impl.hpp @@ -15,6 +15,14 @@ #include #include +#ifdef _WIN32 +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#include +#endif // _WIN32 + namespace cv { namespace dnn { CV__DNN_INLINE_NS_BEGIN @@ -502,4 +510,28 @@ void initDNNTests() ); } +size_t DNNTestLayer::getTopMemoryUsageMB() +{ +#ifdef _WIN32 + PROCESS_MEMORY_COUNTERS proc; + GetProcessMemoryInfo(GetCurrentProcess(), &proc, sizeof(proc)); + return proc.PeakWorkingSetSize / pow(1024, 2); // bytes to megabytes +#else + std::ifstream status("/proc/self/status"); + std::string line, title; + while (std::getline(status, line)) + { + std::istringstream iss(line); + iss >> title; + if (title == "VmHWM:") + { + size_t mem; + iss >> mem; + return mem / 1024; + } + } + return 0l; +#endif +} + } // namespace diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index dc8d7dc0a0..859757d17a 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -2298,7 +2298,13 @@ TEST_P(Test_ONNX_nets, ResNet50v1) applyTestTag(CV_TEST_TAG_MEMORY_512MB); // output range: [-67; 75], after Softmax [0, 0.98] + size_t hwm0 = getTopMemoryUsageMB(); testONNXModels("resnet50v1", pb, default_l1, default_lInf, true, target != DNN_TARGET_MYRIAD); + size_t hwm1 = getTopMemoryUsageMB(); + if (backend == DNN_BACKEND_OPENCV && target == DNN_TARGET_CPU) + { + EXPECT_LE(hwm1 - hwm0, 350) << "Top allocated memory"; + } } TEST_P(Test_ONNX_nets, ResNet50_Int8)