1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-30 07:43:03 +04:00

Merge remote-tracking branch 'upstream/3.4' into merge-3.4

This commit is contained in:
Alexander Alekhin
2019-04-13 17:22:38 +00:00
53 changed files with 1421 additions and 139 deletions
@@ -141,13 +141,20 @@ namespace cv
{
CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int unroll_to = 0);
//! Allocate all memory buffers which will not be freed, ease filtering memcheck issues
//! Allocate memory buffers which will not be freed, ease filtering memcheck issues. Uses fastMalloc() call.
CV_EXPORTS void* allocSingletonBuffer(size_t size);
//! Allocate all memory buffers which will not be freed, ease filtering memcheck issues
//! Allocate memory buffers which will not be freed, ease filtering memcheck issues. Uses fastMalloc() call
template <typename T> static inline
T* allocSingleton(size_t count = 1) { return static_cast<T*>(allocSingletonBuffer(sizeof(T) * count)); }
//! Allocate memory buffers which will not be freed, ease filtering memcheck issues. Uses generic malloc() call.
CV_EXPORTS void* allocSingletonNewBuffer(size_t size);
//! Allocate memory buffers which will not be freed, ease filtering memcheck issues. Uses generic malloc() call.
template <typename T> static inline
T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); }
} // namespace
#if 1 // TODO: Remove in OpenCV 4.x
@@ -0,0 +1,29 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_CORE_ALLOCATOR_STATS_HPP
#define OPENCV_CORE_ALLOCATOR_STATS_HPP
#include "../cvdef.h"
namespace cv { namespace utils {
class AllocatorStatisticsInterface
{
protected:
AllocatorStatisticsInterface() {}
virtual ~AllocatorStatisticsInterface() {}
public:
virtual uint64_t getCurrentUsage() const = 0;
virtual uint64_t getTotalUsage() const = 0;
virtual uint64_t getNumberOfAllocations() const = 0;
virtual uint64_t getPeakUsage() const = 0;
/** set peak usage = current usage */
virtual void resetPeakUsage() = 0;
};
}} // namespace
#endif // OPENCV_CORE_ALLOCATOR_STATS_HPP
@@ -0,0 +1,117 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_CORE_ALLOCATOR_STATS_IMPL_HPP
#define OPENCV_CORE_ALLOCATOR_STATS_IMPL_HPP
#include "./allocator_stats.hpp"
#ifdef CV_CXX11
#include <atomic>
#endif
namespace cv { namespace utils {
#ifdef CV__ALLOCATOR_STATS_LOG
namespace {
#endif
class AllocatorStatistics : public AllocatorStatisticsInterface
{
protected:
#ifdef CV_CXX11
std::atomic<long long> curr, total, total_allocs, peak;
#else
volatile long long curr, total, total_allocs, peak; // overflow is possible, CV_XADD operates with 'int' only
#endif
public:
AllocatorStatistics()
#ifndef CV_CXX11
: curr(0), total(0), total_allocs(0), peak(0)
#endif
{}
~AllocatorStatistics() CV_OVERRIDE {}
// AllocatorStatisticsInterface
#ifdef CV_CXX11
uint64_t getCurrentUsage() const CV_OVERRIDE { return (uint64_t)curr.load(); }
uint64_t getTotalUsage() const CV_OVERRIDE { return (uint64_t)total.load(); }
uint64_t getNumberOfAllocations() const CV_OVERRIDE { return (uint64_t)total_allocs.load(); }
uint64_t getPeakUsage() const CV_OVERRIDE { return (uint64_t)peak.load(); }
/** set peak usage = current usage */
void resetPeakUsage() CV_OVERRIDE { peak.store(curr.load()); }
// Controller interface
void onAllocate(size_t sz)
{
#ifdef CV__ALLOCATOR_STATS_LOG
CV__ALLOCATOR_STATS_LOG(cv::format("allocate: %lld (curr=%lld)", (long long int)sz, (long long int)curr.load()));
#endif
long long new_curr = curr.fetch_add((long long)sz) + (long long)sz;
// peak = std::max((uint64_t)peak, new_curr);
auto prev_peak = peak.load();
while (prev_peak < new_curr)
{
if (peak.compare_exchange_weak(prev_peak, new_curr))
break;
}
// end of peak = max(...)
total += (long long)sz;
total_allocs++;
}
void onFree(size_t sz)
{
#ifdef CV__ALLOCATOR_STATS_LOG
CV__ALLOCATOR_STATS_LOG(cv::format("free: %lld (curr=%lld)", (long long int)sz, (long long int)curr.load()));
#endif
curr -= (long long)sz;
}
#else
uint64_t getCurrentUsage() const CV_OVERRIDE { return (uint64_t)curr; }
uint64_t getTotalUsage() const CV_OVERRIDE { return (uint64_t)total; }
uint64_t getNumberOfAllocations() const CV_OVERRIDE { return (uint64_t)total_allocs; }
uint64_t getPeakUsage() const CV_OVERRIDE { return (uint64_t)peak; }
void resetPeakUsage() CV_OVERRIDE { peak = curr; }
// Controller interface
void onAllocate(size_t sz)
{
#ifdef CV__ALLOCATOR_STATS_LOG
CV__ALLOCATOR_STATS_LOG(cv::format("allocate: %lld (curr=%lld)", (long long int)sz, (long long int)curr));
#endif
uint64_t new_curr = (uint64_t)CV_XADD(&curr, (uint64_t)sz) + sz;
peak = std::max((uint64_t)peak, new_curr); // non-thread safe
//CV_XADD(&total, (uint64_t)sz); // overflow with int, non-reliable...
total += sz;
CV_XADD(&total_allocs, (uint64_t)1);
}
void onFree(size_t sz)
{
#ifdef CV__ALLOCATOR_STATS_LOG
CV__ALLOCATOR_STATS_LOG(cv::format("free: %lld (curr=%lld)", (long long int)sz, (long long int)curr));
#endif
CV_XADD(&curr, (uint64_t)-sz);
}
#endif
};
#ifdef CV__ALLOCATOR_STATS_LOG
} // namespace
#endif
}} // namespace
#endif // OPENCV_CORE_ALLOCATOR_STATS_IMPL_HPP
+77 -1
View File
@@ -42,12 +42,29 @@
#include "precomp.hpp"
#include <opencv2/core/utils/logger.defines.hpp>
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#include <opencv2/core/utils/logger.hpp>
#define CV__ALLOCATOR_STATS_LOG(...) CV_LOG_VERBOSE(NULL, 0, "alloc.cpp: " << __VA_ARGS__)
#include "opencv2/core/utils/allocator_stats.impl.hpp"
#undef CV__ALLOCATOR_STATS_LOG
//#define OPENCV_ALLOC_ENABLE_STATISTICS
#define OPENCV_ALLOC_STATISTICS_LIMIT 4096 // don't track buffers less than N bytes
#ifdef HAVE_POSIX_MEMALIGN
#include <stdlib.h>
#elif defined HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
#include <map>
#endif
namespace cv {
static void* OutOfMemoryError(size_t size)
@@ -55,8 +72,21 @@ static void* OutOfMemoryError(size_t size)
CV_Error_(CV_StsNoMem, ("Failed to allocate %llu bytes", (unsigned long long)size));
}
CV_EXPORTS cv::utils::AllocatorStatisticsInterface& getAllocatorStatistics();
void* fastMalloc( size_t size )
static cv::utils::AllocatorStatistics allocator_stats;
cv::utils::AllocatorStatisticsInterface& getAllocatorStatistics()
{
return allocator_stats;
}
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
static inline
void* fastMalloc_(size_t size)
#else
void* fastMalloc(size_t size)
#endif
{
#ifdef HAVE_POSIX_MEMALIGN
void* ptr = NULL;
@@ -80,7 +110,12 @@ void* fastMalloc( size_t size )
#endif
}
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
static inline
void fastFree_(void* ptr)
#else
void fastFree(void* ptr)
#endif
{
#if defined HAVE_POSIX_MEMALIGN || defined HAVE_MEMALIGN
free(ptr);
@@ -95,6 +130,47 @@ void fastFree(void* ptr)
#endif
}
#ifdef OPENCV_ALLOC_ENABLE_STATISTICS
static
Mutex& getAllocationStatisticsMutex()
{
static Mutex* p_alloc_mutex = allocSingletonNew<Mutex>();
CV_Assert(p_alloc_mutex);
return *p_alloc_mutex;
}
static std::map<void*, size_t> allocated_buffers; // guarded by getAllocationStatisticsMutex()
void* fastMalloc(size_t size)
{
void* res = fastMalloc_(size);
if (res && size >= OPENCV_ALLOC_STATISTICS_LIMIT)
{
cv::AutoLock lock(getAllocationStatisticsMutex());
allocated_buffers.insert(std::make_pair(res, size));
allocator_stats.onAllocate(size);
}
return res;
}
void fastFree(void* ptr)
{
{
cv::AutoLock lock(getAllocationStatisticsMutex());
std::map<void*, size_t>::iterator i = allocated_buffers.find(ptr);
if (i != allocated_buffers.end())
{
size_t size = i->second;
allocator_stats.onFree(size);
allocated_buffers.erase(i);
}
}
fastFree_(ptr);
}
#endif // OPENCV_ALLOC_ENABLE_STATISTICS
} // namespace
CV_IMPL void* cvAlloc( size_t size )
+30 -4
View File
@@ -54,6 +54,9 @@
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.defines.hpp>
#undef CV_LOG_STRIP_LEVEL
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
#include <opencv2/core/utils/logger.hpp>
#include "opencv2/core/ocl_genbase.hpp"
@@ -63,6 +66,10 @@
#include "opencv2/core/utils/filesystem.hpp"
#include "opencv2/core/utils/filesystem.private.hpp"
#define CV__ALLOCATOR_STATS_LOG(...) CV_LOG_VERBOSE(NULL, 0, "OpenCL allocator: " << __VA_ARGS__)
#include "opencv2/core/utils/allocator_stats.impl.hpp"
#undef CV__ALLOCATOR_STATS_LOG
#define CV_OPENCL_ALWAYS_SHOW_BUILD_LOG 0
#define CV_OPENCL_SHOW_RUN_KERNELS 0
@@ -132,6 +139,14 @@ namespace cv { namespace ocl {
void release() { if( CV_XADD(&refcount, -1) == 1 && !cv::__termination) delete this; } \
int refcount
static cv::utils::AllocatorStatistics opencl_allocator_stats;
CV_EXPORTS cv::utils::AllocatorStatisticsInterface& getOpenCLAllocatorStatistics();
cv::utils::AllocatorStatisticsInterface& getOpenCLAllocatorStatistics()
{
return opencl_allocator_stats;
}
#ifndef HAVE_OPENCL
#define CV_OPENCL_NO_SUPPORT() CV_Error(cv::Error::OpenCLApiCallError, "OpenCV build without OpenCL support")
namespace {
@@ -4534,15 +4549,17 @@ class OpenCLAllocator CV_FINAL : public MatAllocator
mutable OpenCLSVMBufferPoolImpl bufferPoolSVM;
#endif
public:
enum AllocatorFlags
{
ALLOCATOR_FLAGS_BUFFER_POOL_USED = 1 << 0,
ALLOCATOR_FLAGS_BUFFER_POOL_HOST_PTR_USED = 1 << 1
ALLOCATOR_FLAGS_BUFFER_POOL_HOST_PTR_USED = 1 << 1,
#ifdef HAVE_OPENCL_SVM
,ALLOCATOR_FLAGS_BUFFER_POOL_SVM_USED = 1 << 2
ALLOCATOR_FLAGS_BUFFER_POOL_SVM_USED = 1 << 2,
#endif
ALLOCATOR_FLAGS_EXTERNAL_BUFFER = 1 << 3 // convertFromBuffer()
};
public:
OpenCLAllocator()
: bufferPool(0),
bufferPoolHostPtr(CL_MEM_ALLOC_HOST_PTR)
@@ -4648,6 +4665,7 @@ public:
u->allocatorFlags_ = allocatorFlags;
CV_DbgAssert(!u->tempUMat()); // for bufferPool.release() consistency in deallocate()
u->markHostCopyObsolete(true);
opencl_allocator_stats.onAllocate(u->size);
return u;
}
@@ -4757,6 +4775,7 @@ public:
}
if (!!(accessFlags & ACCESS_WRITE))
u->markHostCopyObsolete(true);
opencl_allocator_stats.onAllocate(u->size);
return true;
}
@@ -4809,6 +4828,13 @@ public:
void deallocate_(UMatData* u) const
{
CV_Assert(u);
CV_Assert(u->handle);
if ((u->allocatorFlags_ & ALLOCATOR_FLAGS_EXTERNAL_BUFFER) == 0)
{
opencl_allocator_stats.onFree(u->size);
}
#ifdef _WIN32
if (cv::__termination) // process is not in consistent state (after ExitProcess call) and terminating
return; // avoid any OpenCL calls
@@ -5790,7 +5816,7 @@ void convertFromBuffer(void* cl_mem_buffer, size_t step, int rows, int cols, int
// attach clBuffer to UMatData
dst.u = new UMatData(getOpenCLAllocator());
dst.u->data = 0;
dst.u->allocatorFlags_ = 0; // not allocated from any OpenCV buffer pool
dst.u->allocatorFlags_ = OpenCLAllocator::ALLOCATOR_FLAGS_EXTERNAL_BUFFER; // not allocated from any OpenCV buffer pool
dst.u->flags = static_cast<UMatData::MemoryFlag>(0);
dst.u->handle = cl_mem_buffer;
dst.u->origdata = 0;
+2
View File
@@ -71,6 +71,8 @@ static bool param_dumpErrors = utils::getConfigurationParameterBool("OPENCV_DUMP
);
void* allocSingletonBuffer(size_t size) { return fastMalloc(size); }
void* allocSingletonNewBuffer(size_t size) { return malloc(size); }
} // namespace cv