mirror of
https://github.com/opencv/opencv.git
synced 2024-11-29 13:47:32 +08:00
Merge pull request #2192 from alalek:buffer_pool
This commit is contained in:
commit
42ac3123ec
26
modules/core/include/opencv2/core/bufferpool.hpp
Normal file
26
modules/core/include/opencv2/core/bufferpool.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||||
|
|
||||||
|
#ifndef __OPENCV_CORE_BUFFER_POOL_HPP__
|
||||||
|
#define __OPENCV_CORE_BUFFER_POOL_HPP__
|
||||||
|
|
||||||
|
namespace cv
|
||||||
|
{
|
||||||
|
|
||||||
|
class BufferPoolController
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
~BufferPoolController() { }
|
||||||
|
public:
|
||||||
|
virtual size_t getReservedSize() const = 0;
|
||||||
|
virtual size_t getMaxReservedSize() const = 0;
|
||||||
|
virtual void setMaxReservedSize(size_t size) = 0;
|
||||||
|
virtual void freeAllReservedBuffers() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __OPENCV_CORE_BUFFER_POOL_HPP__
|
@ -51,6 +51,7 @@
|
|||||||
#include "opencv2/core/matx.hpp"
|
#include "opencv2/core/matx.hpp"
|
||||||
#include "opencv2/core/types.hpp"
|
#include "opencv2/core/types.hpp"
|
||||||
|
|
||||||
|
#include "opencv2/core/bufferpool.hpp"
|
||||||
|
|
||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
@ -299,6 +300,9 @@ public:
|
|||||||
virtual void copy(UMatData* srcdata, UMatData* dstdata, int dims, const size_t sz[],
|
virtual void copy(UMatData* srcdata, UMatData* dstdata, int dims, const size_t sz[],
|
||||||
const size_t srcofs[], const size_t srcstep[],
|
const size_t srcofs[], const size_t srcstep[],
|
||||||
const size_t dstofs[], const size_t dststep[], bool sync) const;
|
const size_t dstofs[], const size_t dststep[], bool sync) const;
|
||||||
|
|
||||||
|
// default implementation returns DummyBufferPoolController
|
||||||
|
virtual BufferPoolController* getBufferPoolController() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -363,7 +367,7 @@ struct CV_EXPORTS UMatData
|
|||||||
int refcount;
|
int refcount;
|
||||||
uchar* data;
|
uchar* data;
|
||||||
uchar* origdata;
|
uchar* origdata;
|
||||||
size_t size;
|
size_t size, capacity;
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
void* handle;
|
void* handle;
|
||||||
|
@ -596,6 +596,9 @@ protected:
|
|||||||
Impl* p;
|
Impl* p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CV_EXPORTS MatAllocator* getOpenCLAllocator();
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
132
modules/core/perf/opencl/perf_bufferpool.cpp
Normal file
132
modules/core/perf/opencl/perf_bufferpool.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||||
|
|
||||||
|
#include "perf_precomp.hpp"
|
||||||
|
#include "opencv2/ts/ocl_perf.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENCL
|
||||||
|
|
||||||
|
namespace cvtest {
|
||||||
|
namespace ocl {
|
||||||
|
|
||||||
|
struct BufferPoolState
|
||||||
|
{
|
||||||
|
BufferPoolController* controller_;
|
||||||
|
size_t oldMaxReservedSize_;
|
||||||
|
|
||||||
|
BufferPoolState(BufferPoolController* c, bool enable)
|
||||||
|
: controller_(c)
|
||||||
|
{
|
||||||
|
if (!cv::ocl::useOpenCL())
|
||||||
|
{
|
||||||
|
throw ::perf::TestBase::PerfSkipTestException();
|
||||||
|
}
|
||||||
|
oldMaxReservedSize_ = c->getMaxReservedSize();
|
||||||
|
if (oldMaxReservedSize_ == (size_t)-1)
|
||||||
|
{
|
||||||
|
throw ::perf::TestBase::PerfSkipTestException();
|
||||||
|
}
|
||||||
|
if (!enable)
|
||||||
|
{
|
||||||
|
c->setMaxReservedSize(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c->freeAllReservedBuffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~BufferPoolState()
|
||||||
|
{
|
||||||
|
controller_->setMaxReservedSize(oldMaxReservedSize_);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef TestBaseWithParam<bool> BufferPoolFixture;
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(BufferPoolFixture, BufferPool_UMatCreation100, Bool())
|
||||||
|
{
|
||||||
|
BufferPoolState s(cv::ocl::getOpenCLAllocator()->getBufferPoolController(), GetParam());
|
||||||
|
|
||||||
|
Size sz(1920, 1080);
|
||||||
|
|
||||||
|
OCL_TEST_CYCLE()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
UMat u(sz, CV_8UC1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING()
|
||||||
|
}
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(BufferPoolFixture, BufferPool_UMatCountNonZero100, Bool())
|
||||||
|
{
|
||||||
|
BufferPoolState s(cv::ocl::getOpenCLAllocator()->getBufferPoolController(), GetParam());
|
||||||
|
|
||||||
|
Size sz(1920, 1080);
|
||||||
|
|
||||||
|
OCL_TEST_CYCLE()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
UMat u(sz, CV_8UC1);
|
||||||
|
countNonZero(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING()
|
||||||
|
}
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(BufferPoolFixture, BufferPool_UMatCanny10, Bool())
|
||||||
|
{
|
||||||
|
BufferPoolState s(cv::ocl::getOpenCLAllocator()->getBufferPoolController(), GetParam());
|
||||||
|
|
||||||
|
Size sz(1920, 1080);
|
||||||
|
|
||||||
|
int aperture = 3;
|
||||||
|
bool useL2 = false;
|
||||||
|
double thresh_low = 100;
|
||||||
|
double thresh_high = 120;
|
||||||
|
|
||||||
|
OCL_TEST_CYCLE()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
UMat src(sz, CV_8UC1);
|
||||||
|
UMat dst;
|
||||||
|
Canny(src, dst, thresh_low, thresh_high, aperture, useL2);
|
||||||
|
dst.getMat(ACCESS_READ); // complete async operations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING()
|
||||||
|
}
|
||||||
|
|
||||||
|
OCL_PERF_TEST_P(BufferPoolFixture, BufferPool_UMatIntegral10, Bool())
|
||||||
|
{
|
||||||
|
BufferPoolState s(cv::ocl::getOpenCLAllocator()->getBufferPoolController(), GetParam());
|
||||||
|
|
||||||
|
Size sz(1920, 1080);
|
||||||
|
|
||||||
|
OCL_TEST_CYCLE()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
UMat src(sz, CV_32FC1);
|
||||||
|
UMat dst;
|
||||||
|
integral(src, dst);
|
||||||
|
dst.getMat(ACCESS_READ); // complete async operations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SANITY_CHECK_NOTHING()
|
||||||
|
}
|
||||||
|
|
||||||
|
} } // namespace cvtest::ocl
|
||||||
|
|
||||||
|
#endif // HAVE_OPENCL
|
28
modules/core/src/bufferpool.impl.hpp
Normal file
28
modules/core/src/bufferpool.impl.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2014, Advanced Micro Devices, Inc., all rights reserved.
|
||||||
|
|
||||||
|
#ifndef __OPENCV_CORE_BUFFER_POOL_IMPL_HPP__
|
||||||
|
#define __OPENCV_CORE_BUFFER_POOL_IMPL_HPP__
|
||||||
|
|
||||||
|
#include "opencv2/core/bufferpool.hpp"
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
|
||||||
|
class DummyBufferPoolController : public BufferPoolController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DummyBufferPoolController() { }
|
||||||
|
virtual ~DummyBufferPoolController() { }
|
||||||
|
|
||||||
|
virtual size_t getReservedSize() const { return (size_t)-1; }
|
||||||
|
virtual size_t getMaxReservedSize() const { return (size_t)-1; }
|
||||||
|
virtual void setMaxReservedSize(size_t size) { (void)size; }
|
||||||
|
virtual void freeAllReservedBuffers() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif // __OPENCV_CORE_BUFFER_POOL_IMPL_HPP__
|
@ -43,6 +43,8 @@
|
|||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
#include "opencl_kernels.hpp"
|
#include "opencl_kernels.hpp"
|
||||||
|
|
||||||
|
#include "bufferpool.impl.hpp"
|
||||||
|
|
||||||
/****************************************************************************************\
|
/****************************************************************************************\
|
||||||
* [scaled] Identity matrix initialization *
|
* [scaled] Identity matrix initialization *
|
||||||
\****************************************************************************************/
|
\****************************************************************************************/
|
||||||
@ -157,6 +159,12 @@ void MatAllocator::copy(UMatData* usrc, UMatData* udst, int dims, const size_t s
|
|||||||
memcpy(ptrs[1], ptrs[0], planesz);
|
memcpy(ptrs[1], ptrs[0], planesz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferPoolController* MatAllocator::getBufferPoolController() const
|
||||||
|
{
|
||||||
|
static DummyBufferPoolController dummy;
|
||||||
|
return &dummy;
|
||||||
|
}
|
||||||
|
|
||||||
class StdMatAllocator : public MatAllocator
|
class StdMatAllocator : public MatAllocator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -40,11 +40,48 @@
|
|||||||
//M*/
|
//M*/
|
||||||
|
|
||||||
#include "precomp.hpp"
|
#include "precomp.hpp"
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <iostream> // std::cerr
|
#include <iostream> // std::cerr
|
||||||
|
|
||||||
|
#include "opencv2/core/bufferpool.hpp"
|
||||||
|
#ifndef LOG_BUFFER_POOL
|
||||||
|
# if 0
|
||||||
|
# define LOG_BUFFER_POOL printf
|
||||||
|
# else
|
||||||
|
# define LOG_BUFFER_POOL(...)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO Move to some common place
|
||||||
|
static size_t getConfigurationParameterForSize(const char* name, size_t defaultValue)
|
||||||
|
{
|
||||||
|
const char* envValue = getenv(name);
|
||||||
|
if (envValue == NULL)
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
cv::String value = envValue;
|
||||||
|
size_t pos = 0;
|
||||||
|
for (; pos < value.size(); pos++)
|
||||||
|
{
|
||||||
|
if (!isdigit(value[pos]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cv::String valueStr = value.substr(0, pos);
|
||||||
|
cv::String suffixStr = value.substr(pos, value.length() - pos);
|
||||||
|
int v = atoi(valueStr.c_str());
|
||||||
|
if (suffixStr.length() == 0)
|
||||||
|
return v;
|
||||||
|
else if (suffixStr == "MB" || suffixStr == "Mb" || suffixStr == "mb")
|
||||||
|
return v * 1024 * 1024;
|
||||||
|
else if (suffixStr == "KB" || suffixStr == "Kb" || suffixStr == "kb")
|
||||||
|
return v * 1024;
|
||||||
|
CV_ErrorNoReturn(cv::Error::StsBadArg, cv::format("Invalid value for %s parameter: %s", name, value.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp"
|
#include "opencv2/core/opencl/runtime/opencl_clamdblas.hpp"
|
||||||
#include "opencv2/core/opencl/runtime/opencl_clamdfft.hpp"
|
#include "opencv2/core/opencl/runtime/opencl_clamdfft.hpp"
|
||||||
|
|
||||||
@ -3234,8 +3271,208 @@ ProgramSource2::hash_t ProgramSource2::hash() const
|
|||||||
|
|
||||||
//////////////////////////////////////////// OpenCLAllocator //////////////////////////////////////////////////
|
//////////////////////////////////////////// OpenCLAllocator //////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class OpenCLBufferPool
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
~OpenCLBufferPool() { }
|
||||||
|
public:
|
||||||
|
virtual cl_mem allocate(size_t size, CV_OUT size_t& capacity) = 0;
|
||||||
|
virtual void release(cl_mem handle, size_t capacity) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class OpenCLBufferPoolImpl : public BufferPoolController, public OpenCLBufferPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct BufferEntry
|
||||||
|
{
|
||||||
|
cl_mem clBuffer_;
|
||||||
|
size_t capacity_;
|
||||||
|
};
|
||||||
|
protected:
|
||||||
|
Mutex mutex_;
|
||||||
|
|
||||||
|
size_t currentReservedSize;
|
||||||
|
size_t maxReservedSize;
|
||||||
|
|
||||||
|
std::list<BufferEntry> reservedEntries_; // LRU order
|
||||||
|
|
||||||
|
// synchronized
|
||||||
|
bool _findAndRemoveEntryFromReservedList(CV_OUT BufferEntry& entry, const size_t size)
|
||||||
|
{
|
||||||
|
if (reservedEntries_.empty())
|
||||||
|
return false;
|
||||||
|
std::list<BufferEntry>::iterator i = reservedEntries_.begin();
|
||||||
|
std::list<BufferEntry>::iterator result_pos = reservedEntries_.end();
|
||||||
|
BufferEntry result = {NULL, 0};
|
||||||
|
size_t minDiff = (size_t)(-1);
|
||||||
|
for (; i != reservedEntries_.end(); ++i)
|
||||||
|
{
|
||||||
|
BufferEntry& e = *i;
|
||||||
|
if (e.capacity_ >= size)
|
||||||
|
{
|
||||||
|
size_t diff = e.capacity_ - size;
|
||||||
|
if (diff < size / 8 && (result_pos == reservedEntries_.end() || diff < minDiff))
|
||||||
|
{
|
||||||
|
minDiff = diff;
|
||||||
|
result_pos = i;
|
||||||
|
result = e;
|
||||||
|
if (diff == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result_pos != reservedEntries_.end())
|
||||||
|
{
|
||||||
|
//CV_DbgAssert(result == *result_pos);
|
||||||
|
reservedEntries_.erase(result_pos);
|
||||||
|
entry = result;
|
||||||
|
currentReservedSize -= entry.capacity_;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// synchronized
|
||||||
|
void _checkSizeOfReservedEntries()
|
||||||
|
{
|
||||||
|
while (currentReservedSize > maxReservedSize)
|
||||||
|
{
|
||||||
|
CV_DbgAssert(!reservedEntries_.empty());
|
||||||
|
const BufferEntry& entry = reservedEntries_.back();
|
||||||
|
CV_DbgAssert(currentReservedSize >= entry.capacity_);
|
||||||
|
currentReservedSize -= entry.capacity_;
|
||||||
|
_releaseBufferEntry(entry);
|
||||||
|
reservedEntries_.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t _allocationGranularity(size_t size)
|
||||||
|
{
|
||||||
|
// heuristic values
|
||||||
|
if (size < 1024)
|
||||||
|
return 16;
|
||||||
|
else if (size < 64*1024)
|
||||||
|
return 64;
|
||||||
|
else if (size < 1024*1024)
|
||||||
|
return 4096;
|
||||||
|
else if (size < 16*1024*1024)
|
||||||
|
return 64*1024;
|
||||||
|
else
|
||||||
|
return 1024*1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _allocateBufferEntry(BufferEntry& entry, size_t size)
|
||||||
|
{
|
||||||
|
CV_DbgAssert(entry.clBuffer_ == NULL);
|
||||||
|
entry.capacity_ = alignSize(size, (int)_allocationGranularity(size));
|
||||||
|
Context2& ctx = Context2::getDefault();
|
||||||
|
cl_int retval = CL_SUCCESS;
|
||||||
|
entry.clBuffer_ = clCreateBuffer((cl_context)ctx.ptr(), CL_MEM_READ_WRITE, entry.capacity_, 0, &retval);
|
||||||
|
CV_Assert(retval == CL_SUCCESS);
|
||||||
|
CV_Assert(entry.clBuffer_ != NULL);
|
||||||
|
LOG_BUFFER_POOL("OpenCL allocate %lld (0x%llx) bytes: %p\n",
|
||||||
|
(long long)entry.capacity_, (long long)entry.capacity_, entry.clBuffer_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _releaseBufferEntry(const BufferEntry& entry)
|
||||||
|
{
|
||||||
|
CV_Assert(entry.capacity_ != 0);
|
||||||
|
CV_Assert(entry.clBuffer_ != NULL);
|
||||||
|
LOG_BUFFER_POOL("OpenCL release buffer: %p, %lld (0x%llx) bytes\n",
|
||||||
|
entry.clBuffer_, (long long)entry.capacity_, (long long)entry.capacity_);
|
||||||
|
clReleaseMemObject(entry.clBuffer_);
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
OpenCLBufferPoolImpl()
|
||||||
|
: currentReservedSize(0), maxReservedSize(0)
|
||||||
|
{
|
||||||
|
// Note: Buffer pool is disabled by default,
|
||||||
|
// because we didn't receive significant performance improvement
|
||||||
|
maxReservedSize = getConfigurationParameterForSize("OPENCV_OPENCL_BUFFERPOOL_LIMIT", 0);
|
||||||
|
}
|
||||||
|
virtual ~OpenCLBufferPoolImpl()
|
||||||
|
{
|
||||||
|
freeAllReservedBuffers();
|
||||||
|
CV_Assert(reservedEntries_.empty());
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
virtual cl_mem allocate(size_t size, CV_OUT size_t& capacity)
|
||||||
|
{
|
||||||
|
BufferEntry entry = {NULL, 0};
|
||||||
|
if (maxReservedSize > 0)
|
||||||
|
{
|
||||||
|
AutoLock locker(mutex_);
|
||||||
|
if (_findAndRemoveEntryFromReservedList(entry, size))
|
||||||
|
{
|
||||||
|
CV_DbgAssert(size <= entry.capacity_);
|
||||||
|
LOG_BUFFER_POOL("Reuse reserved buffer: %p\n", entry.clBuffer_);
|
||||||
|
capacity = entry.capacity_;
|
||||||
|
return entry.clBuffer_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_allocateBufferEntry(entry, size);
|
||||||
|
capacity = entry.capacity_;
|
||||||
|
return entry.clBuffer_;
|
||||||
|
}
|
||||||
|
virtual void release(cl_mem handle, size_t capacity)
|
||||||
|
{
|
||||||
|
BufferEntry entry = {handle, capacity};
|
||||||
|
if (maxReservedSize == 0 || entry.capacity_ > maxReservedSize / 8)
|
||||||
|
{
|
||||||
|
_releaseBufferEntry(entry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AutoLock locker(mutex_);
|
||||||
|
reservedEntries_.push_front(entry);
|
||||||
|
currentReservedSize += entry.capacity_;
|
||||||
|
_checkSizeOfReservedEntries();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual size_t getReservedSize() const { return currentReservedSize; }
|
||||||
|
virtual size_t getMaxReservedSize() const { return maxReservedSize; }
|
||||||
|
virtual void setMaxReservedSize(size_t size)
|
||||||
|
{
|
||||||
|
AutoLock locker(mutex_);
|
||||||
|
size_t oldMaxReservedSize = maxReservedSize;
|
||||||
|
maxReservedSize = size;
|
||||||
|
if (maxReservedSize < oldMaxReservedSize)
|
||||||
|
{
|
||||||
|
std::list<BufferEntry>::iterator i = reservedEntries_.begin();
|
||||||
|
for (; i != reservedEntries_.end();)
|
||||||
|
{
|
||||||
|
const BufferEntry& entry = *i;
|
||||||
|
if (entry.capacity_ > maxReservedSize / 8)
|
||||||
|
{
|
||||||
|
CV_DbgAssert(currentReservedSize >= entry.capacity_);
|
||||||
|
currentReservedSize -= entry.capacity_;
|
||||||
|
_releaseBufferEntry(entry);
|
||||||
|
i = reservedEntries_.erase(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
_checkSizeOfReservedEntries();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void freeAllReservedBuffers()
|
||||||
|
{
|
||||||
|
AutoLock locker(mutex_);
|
||||||
|
std::list<BufferEntry>::const_iterator i = reservedEntries_.begin();
|
||||||
|
for (; i != reservedEntries_.end(); ++i)
|
||||||
|
{
|
||||||
|
const BufferEntry& entry = *i;
|
||||||
|
_releaseBufferEntry(entry);
|
||||||
|
}
|
||||||
|
reservedEntries_.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class OpenCLAllocator : public MatAllocator
|
class OpenCLAllocator : public MatAllocator
|
||||||
{
|
{
|
||||||
|
mutable OpenCLBufferPoolImpl bufferPool;
|
||||||
public:
|
public:
|
||||||
OpenCLAllocator() { matStdAllocator = Mat::getStdAllocator(); }
|
OpenCLAllocator() { matStdAllocator = Mat::getStdAllocator(); }
|
||||||
|
|
||||||
@ -3274,17 +3511,18 @@ public:
|
|||||||
int createFlags = 0, flags0 = 0;
|
int createFlags = 0, flags0 = 0;
|
||||||
getBestFlags(ctx, flags, createFlags, flags0);
|
getBestFlags(ctx, flags, createFlags, flags0);
|
||||||
|
|
||||||
cl_int retval = 0;
|
CV_Assert(createFlags == CL_MEM_READ_WRITE);
|
||||||
void* handle = clCreateBuffer((cl_context)ctx.ptr(),
|
size_t capacity = 0;
|
||||||
createFlags, total, 0, &retval);
|
void* handle = bufferPool.allocate(total, capacity);
|
||||||
if( !handle || retval != CL_SUCCESS )
|
if (!handle)
|
||||||
return defaultAllocate(dims, sizes, type, data, step, flags);
|
return defaultAllocate(dims, sizes, type, data, step, flags);
|
||||||
UMatData* u = new UMatData(this);
|
UMatData* u = new UMatData(this);
|
||||||
u->data = 0;
|
u->data = 0;
|
||||||
u->size = total;
|
u->size = total;
|
||||||
|
u->capacity = capacity;
|
||||||
u->handle = handle;
|
u->handle = handle;
|
||||||
u->flags = flags0;
|
u->flags = flags0;
|
||||||
|
CV_DbgAssert(!u->tempUMat()); // for bufferPool.release() consistency
|
||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3405,8 +3643,9 @@ public:
|
|||||||
fastFree(u->data);
|
fastFree(u->data);
|
||||||
u->data = 0;
|
u->data = 0;
|
||||||
}
|
}
|
||||||
clReleaseMemObject((cl_mem)u->handle);
|
bufferPool.release((cl_mem)u->handle, u->capacity);
|
||||||
u->handle = 0;
|
u->handle = 0;
|
||||||
|
u->capacity = 0;
|
||||||
delete u;
|
delete u;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3713,6 +3952,8 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BufferPoolController* getBufferPoolController() const { return &bufferPool; }
|
||||||
|
|
||||||
MatAllocator* matStdAllocator;
|
MatAllocator* matStdAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -260,11 +260,6 @@ extern TLSData<CoreTLSData> coreTlsData;
|
|||||||
#define CL_RUNTIME_EXPORT
|
#define CL_RUNTIME_EXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ocl
|
|
||||||
{
|
|
||||||
MatAllocator* getOpenCLAllocator();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern bool __termination; // skip some cleanups, because process is terminating
|
extern bool __termination; // skip some cleanups, because process is terminating
|
||||||
// (for example, if ExitProcess() was already called)
|
// (for example, if ExitProcess() was already called)
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ UMatData::UMatData(const MatAllocator* allocator)
|
|||||||
prevAllocator = currAllocator = allocator;
|
prevAllocator = currAllocator = allocator;
|
||||||
urefcount = refcount = 0;
|
urefcount = refcount = 0;
|
||||||
data = origdata = 0;
|
data = origdata = 0;
|
||||||
size = 0;
|
size = 0; capacity = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
handle = 0;
|
handle = 0;
|
||||||
userdata = 0;
|
userdata = 0;
|
||||||
@ -67,7 +67,7 @@ UMatData::~UMatData()
|
|||||||
prevAllocator = currAllocator = 0;
|
prevAllocator = currAllocator = 0;
|
||||||
urefcount = refcount = 0;
|
urefcount = refcount = 0;
|
||||||
data = origdata = 0;
|
data = origdata = 0;
|
||||||
size = 0;
|
size = 0; capacity = 0;
|
||||||
flags = 0;
|
flags = 0;
|
||||||
handle = 0;
|
handle = 0;
|
||||||
userdata = 0;
|
userdata = 0;
|
||||||
|
@ -291,3 +291,31 @@ TEST(UMat, setOpenCL)
|
|||||||
// reset state to the previous one
|
// reset state to the previous one
|
||||||
ocl::setUseOpenCL(useOCL);
|
ocl::setUseOpenCL(useOCL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(UMat, BufferPoolGrowing)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG
|
||||||
|
const int ITERATIONS = 100;
|
||||||
|
#else
|
||||||
|
const int ITERATIONS = 200;
|
||||||
|
#endif
|
||||||
|
const Size sz(1920, 1080);
|
||||||
|
BufferPoolController* c = ocl::getOpenCLAllocator()->getBufferPoolController();
|
||||||
|
if (c)
|
||||||
|
{
|
||||||
|
size_t oldMaxReservedSize = c->getMaxReservedSize();
|
||||||
|
c->freeAllReservedBuffers();
|
||||||
|
c->setMaxReservedSize(sz.area() * 10);
|
||||||
|
for (int i = 0; i < ITERATIONS; i++)
|
||||||
|
{
|
||||||
|
UMat um(Size(sz.width + i, sz.height + i), CV_8UC1);
|
||||||
|
UMat um2(Size(sz.width + 2 * i, sz.height + 2 * i), CV_8UC1);
|
||||||
|
}
|
||||||
|
c->setMaxReservedSize(oldMaxReservedSize);
|
||||||
|
c->freeAllReservedBuffers();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Skipped, no OpenCL" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user