Generic MultiPool template
PiperOrigin-RevId: 488783176
This commit is contained in:
parent
b9fa2e3496
commit
53d015af08
|
@ -618,6 +618,7 @@ cc_library(
|
||||||
cc_library(
|
cc_library(
|
||||||
name = "multi_pool",
|
name = "multi_pool",
|
||||||
hdrs = ["multi_pool.h"],
|
hdrs = ["multi_pool.h"],
|
||||||
|
deps = ["//mediapipe/util:resource_cache"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cc_library(
|
cc_library(
|
||||||
|
|
|
@ -71,12 +71,12 @@ std::string CvPixelBufferPoolWrapper::GetDebugString() const {
|
||||||
void CvPixelBufferPoolWrapper::Flush() { CVPixelBufferPoolFlush(*pool_, 0); }
|
void CvPixelBufferPoolWrapper::Flush() { CVPixelBufferPoolFlush(*pool_, 0); }
|
||||||
|
|
||||||
CFHolder<CVPixelBufferRef> CvPixelBufferPoolWrapper::CreateBufferWithoutPool(
|
CFHolder<CVPixelBufferRef> CvPixelBufferPoolWrapper::CreateBufferWithoutPool(
|
||||||
int width, int height, GpuBufferFormat format) {
|
const internal::GpuBufferSpec& spec) {
|
||||||
OSType cv_format = CVPixelFormatForGpuBufferFormat(format);
|
OSType cv_format = CVPixelFormatForGpuBufferFormat(spec.format);
|
||||||
CHECK_NE(cv_format, -1) << "unsupported pixel format";
|
CHECK_NE(cv_format, -1) << "unsupported pixel format";
|
||||||
CVPixelBufferRef buffer;
|
CVPixelBufferRef buffer;
|
||||||
CVReturn err =
|
CVReturn err = CreateCVPixelBufferWithoutPool(spec.width, spec.height,
|
||||||
CreateCVPixelBufferWithoutPool(width, height, cv_format, &buffer);
|
cv_format, &buffer);
|
||||||
CHECK(!err) << "Error creating pixel buffer: " << err;
|
CHECK(!err) << "Error creating pixel buffer: " << err;
|
||||||
return MakeCFHolderAdopting(buffer);
|
return MakeCFHolderAdopting(buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,11 @@ class CvPixelBufferPoolWrapper {
|
||||||
CvTextureCacheManager* texture_caches);
|
CvTextureCacheManager* texture_caches);
|
||||||
|
|
||||||
static std::shared_ptr<CvPixelBufferPoolWrapper> Create(
|
static std::shared_ptr<CvPixelBufferPoolWrapper> Create(
|
||||||
int width, int height, GpuBufferFormat format,
|
const internal::GpuBufferSpec& spec, const MultiPoolOptions& options,
|
||||||
const MultiPoolOptions& options,
|
|
||||||
CvTextureCacheManager* texture_caches = nullptr) {
|
CvTextureCacheManager* texture_caches = nullptr) {
|
||||||
return std::make_shared<CvPixelBufferPoolWrapper>(
|
return std::make_shared<CvPixelBufferPoolWrapper>(
|
||||||
width, height, format, options.max_inactive_buffer_age, texture_caches);
|
spec.width, spec.height, spec.format, options.max_inactive_buffer_age,
|
||||||
|
texture_caches);
|
||||||
}
|
}
|
||||||
|
|
||||||
CFHolder<CVPixelBufferRef> GetBuffer();
|
CFHolder<CVPixelBufferRef> GetBuffer();
|
||||||
|
@ -53,7 +53,7 @@ class CvPixelBufferPoolWrapper {
|
||||||
void Flush();
|
void Flush();
|
||||||
|
|
||||||
static CFHolder<CVPixelBufferRef> CreateBufferWithoutPool(
|
static CFHolder<CVPixelBufferRef> CreateBufferWithoutPool(
|
||||||
int width, int height, GpuBufferFormat format);
|
const internal::GpuBufferSpec& spec);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CFHolder<CVPixelBufferPoolRef> pool_;
|
CFHolder<CVPixelBufferPoolRef> pool_;
|
||||||
|
|
|
@ -42,9 +42,8 @@ class GlTextureBufferPool
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<GlTextureBufferPool> Create(
|
static std::shared_ptr<GlTextureBufferPool> Create(
|
||||||
int width, int height, GpuBufferFormat format,
|
const internal::GpuBufferSpec& spec, const MultiPoolOptions& options) {
|
||||||
const MultiPoolOptions& options) {
|
return Create(spec.width, spec.height, spec.format, options.keep_count);
|
||||||
return Create(width, height, format, options.keep_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtains a buffers. May either be reused or created anew.
|
// Obtains a buffers. May either be reused or created anew.
|
||||||
|
@ -59,8 +58,8 @@ class GlTextureBufferPool
|
||||||
std::pair<int, int> GetInUseAndAvailableCounts();
|
std::pair<int, int> GetInUseAndAvailableCounts();
|
||||||
|
|
||||||
static GlTextureBufferSharedPtr CreateBufferWithoutPool(
|
static GlTextureBufferSharedPtr CreateBufferWithoutPool(
|
||||||
int width, int height, GpuBufferFormat format) {
|
const internal::GpuBufferSpec& spec) {
|
||||||
return GlTextureBuffer::Create(width, height, format);
|
return GlTextureBuffer::Create(spec.width, spec.height, spec.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -153,6 +153,34 @@ inline GpuBufferFormat GpuBufferFormatForCVPixelFormat(OSType format) {
|
||||||
|
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
struct GpuBufferSpec {
|
||||||
|
GpuBufferSpec(int w, int h, GpuBufferFormat f)
|
||||||
|
: width(w), height(h), format(f) {}
|
||||||
|
|
||||||
|
template <typename H>
|
||||||
|
friend H AbslHashValue(H h, const GpuBufferSpec& spec) {
|
||||||
|
return H::combine(std::move(h), spec.width, spec.height,
|
||||||
|
static_cast<uint32_t>(spec.format));
|
||||||
|
}
|
||||||
|
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
GpuBufferFormat format;
|
||||||
|
};
|
||||||
|
|
||||||
|
// BufferSpec equality operators
|
||||||
|
inline bool operator==(const GpuBufferSpec& lhs, const GpuBufferSpec& rhs) {
|
||||||
|
return lhs.width == rhs.width && lhs.height == rhs.height &&
|
||||||
|
lhs.format == rhs.format;
|
||||||
|
}
|
||||||
|
inline bool operator!=(const GpuBufferSpec& lhs, const GpuBufferSpec& rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
} // namespace mediapipe
|
} // namespace mediapipe
|
||||||
|
|
||||||
#endif // MEDIAPIPE_GPU_GPU_BUFFER_FORMAT_H_
|
#endif // MEDIAPIPE_GPU_GPU_BUFFER_FORMAT_H_
|
||||||
|
|
|
@ -16,51 +16,7 @@
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
#include "absl/memory/memory.h"
|
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
#include "mediapipe/framework/port/logging.h"
|
#include "mediapipe/framework/port/logging.h"
|
||||||
#include "mediapipe/gpu/gpu_shared_data_internal.h"
|
|
||||||
|
|
||||||
namespace mediapipe {
|
namespace mediapipe {} // namespace mediapipe
|
||||||
|
|
||||||
std::shared_ptr<GpuBufferMultiPool::SimplePool>
|
|
||||||
GpuBufferMultiPool::DefaultMakeSimplePool(
|
|
||||||
const GpuBufferMultiPool::BufferSpec& spec,
|
|
||||||
const MultiPoolOptions& options) {
|
|
||||||
return SimplePool::Create(spec.width, spec.height, spec.format, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<GpuBufferMultiPool::SimplePool> GpuBufferMultiPool::RequestPool(
|
|
||||||
const BufferSpec& spec) {
|
|
||||||
std::shared_ptr<SimplePool> pool;
|
|
||||||
std::vector<std::shared_ptr<SimplePool>> evicted;
|
|
||||||
{
|
|
||||||
absl::MutexLock lock(&mutex_);
|
|
||||||
pool =
|
|
||||||
cache_.Lookup(spec, [this](const BufferSpec& spec, int request_count) {
|
|
||||||
return (request_count >= options_.min_requests_before_pool)
|
|
||||||
? create_simple_pool_(spec, options_)
|
|
||||||
: nullptr;
|
|
||||||
});
|
|
||||||
evicted = cache_.Evict(options_.max_pool_count,
|
|
||||||
options_.request_count_scrub_interval);
|
|
||||||
}
|
|
||||||
// Evicted pools, and their buffers, will be released without holding the
|
|
||||||
// lock.
|
|
||||||
return pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
GpuBuffer GpuBufferMultiPool::GetBuffer(int width, int height,
|
|
||||||
GpuBufferFormat format) {
|
|
||||||
BufferSpec key(width, height, format);
|
|
||||||
std::shared_ptr<SimplePool> pool = RequestPool(key);
|
|
||||||
if (pool) {
|
|
||||||
// Note: we release our multipool lock before accessing the simple pool.
|
|
||||||
return GpuBuffer(pool->GetBuffer());
|
|
||||||
} else {
|
|
||||||
return GpuBuffer(
|
|
||||||
SimplePool::CreateBufferWithoutPool(width, height, format));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mediapipe
|
|
||||||
|
|
|
@ -22,15 +22,9 @@
|
||||||
#ifndef MEDIAPIPE_GPU_GPU_BUFFER_MULTI_POOL_H_
|
#ifndef MEDIAPIPE_GPU_GPU_BUFFER_MULTI_POOL_H_
|
||||||
#define MEDIAPIPE_GPU_GPU_BUFFER_MULTI_POOL_H_
|
#define MEDIAPIPE_GPU_GPU_BUFFER_MULTI_POOL_H_
|
||||||
|
|
||||||
#include "absl/hash/hash.h"
|
|
||||||
#include "absl/synchronization/mutex.h"
|
#include "absl/synchronization/mutex.h"
|
||||||
#include "mediapipe/gpu/gpu_buffer.h"
|
#include "mediapipe/gpu/gpu_buffer.h"
|
||||||
#include "mediapipe/gpu/multi_pool.h"
|
#include "mediapipe/gpu/multi_pool.h"
|
||||||
#include "mediapipe/util/resource_cache.h"
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include "mediapipe/gpu/pixel_buffer_pool_util.h"
|
|
||||||
#endif // __APPLE__
|
|
||||||
|
|
||||||
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
#include "mediapipe/gpu/cv_pixel_buffer_pool_wrapper.h"
|
#include "mediapipe/gpu/cv_pixel_buffer_pool_wrapper.h"
|
||||||
|
@ -40,77 +34,24 @@
|
||||||
|
|
||||||
namespace mediapipe {
|
namespace mediapipe {
|
||||||
|
|
||||||
struct GpuSharedData;
|
|
||||||
class CvPixelBufferPoolWrapper;
|
class CvPixelBufferPoolWrapper;
|
||||||
|
|
||||||
class GpuBufferMultiPool {
|
class GpuBufferMultiPool : public MultiPool<
|
||||||
public:
|
|
||||||
GpuBufferMultiPool(MultiPoolOptions options = kDefaultMultiPoolOptions)
|
|
||||||
: options_(options) {}
|
|
||||||
|
|
||||||
// Obtains a buffer. May either be reused or created anew.
|
|
||||||
GpuBuffer GetBuffer(int width, int height,
|
|
||||||
GpuBufferFormat format = GpuBufferFormat::kBGRA32);
|
|
||||||
|
|
||||||
// This class is not intended as part of the public api of this class. It is
|
|
||||||
// public only because it is used as a map key type, and the map
|
|
||||||
// implementation needs access to, e.g., the equality operator.
|
|
||||||
struct BufferSpec {
|
|
||||||
BufferSpec(int w, int h, mediapipe::GpuBufferFormat f)
|
|
||||||
: width(w), height(h), format(f) {}
|
|
||||||
|
|
||||||
template <typename H>
|
|
||||||
friend H AbslHashValue(H h, const BufferSpec& spec) {
|
|
||||||
return H::combine(std::move(h), spec.width, spec.height,
|
|
||||||
static_cast<uint32_t>(spec.format));
|
|
||||||
}
|
|
||||||
|
|
||||||
int width;
|
|
||||||
int height;
|
|
||||||
mediapipe::GpuBufferFormat format;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
using SimplePool = CvPixelBufferPoolWrapper;
|
CvPixelBufferPoolWrapper,
|
||||||
#else
|
#else
|
||||||
using SimplePool = GlTextureBufferPool;
|
GlTextureBufferPool,
|
||||||
#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
|
internal::GpuBufferSpec, GpuBuffer> {
|
||||||
|
public:
|
||||||
|
using MultiPool::MultiPool;
|
||||||
|
|
||||||
using SimplePoolFactory = std::function<std::shared_ptr<SimplePool>(
|
GpuBuffer GetBuffer(int width, int height,
|
||||||
const BufferSpec& spec, const MultiPoolOptions& options)>;
|
GpuBufferFormat format = GpuBufferFormat::kBGRA32) {
|
||||||
|
return Get(internal::GpuBufferSpec(width, height, format));
|
||||||
void SetSimplePoolFactory(SimplePoolFactory create_simple_pool) {
|
|
||||||
create_simple_pool_ = create_simple_pool;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
static std::shared_ptr<SimplePool> DefaultMakeSimplePool(
|
|
||||||
const GpuBufferMultiPool::BufferSpec& spec,
|
|
||||||
const MultiPoolOptions& options);
|
|
||||||
|
|
||||||
// Requests a simple buffer pool for the given spec. This may return nullptr
|
|
||||||
// if we have not yet reached a sufficient number of requests to allocate a
|
|
||||||
// pool, in which case the caller should invoke CreateBufferWithoutPool.
|
|
||||||
std::shared_ptr<SimplePool> RequestPool(const BufferSpec& spec);
|
|
||||||
|
|
||||||
MultiPoolOptions options_;
|
|
||||||
absl::Mutex mutex_;
|
|
||||||
mediapipe::ResourceCache<BufferSpec, std::shared_ptr<SimplePool>> cache_
|
|
||||||
ABSL_GUARDED_BY(mutex_);
|
|
||||||
SimplePoolFactory create_simple_pool_ = DefaultMakeSimplePool;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// BufferSpec equality operators
|
|
||||||
inline bool operator==(const GpuBufferMultiPool::BufferSpec& lhs,
|
|
||||||
const GpuBufferMultiPool::BufferSpec& rhs) {
|
|
||||||
return lhs.width == rhs.width && lhs.height == rhs.height &&
|
|
||||||
lhs.format == rhs.format;
|
|
||||||
}
|
|
||||||
inline bool operator!=(const GpuBufferMultiPool::BufferSpec& lhs,
|
|
||||||
const GpuBufferMultiPool::BufferSpec& rhs) {
|
|
||||||
return !operator==(lhs, rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mediapipe
|
} // namespace mediapipe
|
||||||
|
|
||||||
#endif // MEDIAPIPE_GPU_GPU_BUFFER_MULTI_POOL_H_
|
#endif // MEDIAPIPE_GPU_GPU_BUFFER_MULTI_POOL_H_
|
||||||
|
|
|
@ -80,18 +80,20 @@ GpuResources::StatusOrGpuResources GpuResources::Create(
|
||||||
return gpu_resources;
|
return gpu_resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
GpuResources::GpuResources(std::shared_ptr<GlContext> gl_context) {
|
GpuResources::GpuResources(std::shared_ptr<GlContext> gl_context)
|
||||||
|
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
|
: texture_caches_(std::make_shared<CvTextureCacheManager>()),
|
||||||
|
gpu_buffer_pool_(
|
||||||
|
[tc = texture_caches_](const internal::GpuBufferSpec& spec,
|
||||||
|
const MultiPoolOptions& options) {
|
||||||
|
return CvPixelBufferPoolWrapper::Create(spec, options, tc.get());
|
||||||
|
})
|
||||||
|
#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
|
{
|
||||||
gl_key_context_[SharedContextKey()] = gl_context;
|
gl_key_context_[SharedContextKey()] = gl_context;
|
||||||
named_executors_[kGpuExecutorName] =
|
named_executors_[kGpuExecutorName] =
|
||||||
std::make_shared<GlContextExecutor>(gl_context.get());
|
std::make_shared<GlContextExecutor>(gl_context.get());
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
texture_caches_ = std::make_shared<CvTextureCacheManager>();
|
|
||||||
gpu_buffer_pool().SetSimplePoolFactory(
|
|
||||||
[tc = texture_caches_](const GpuBufferMultiPool::BufferSpec& spec,
|
|
||||||
const MultiPoolOptions& options) {
|
|
||||||
return CvPixelBufferPoolWrapper::Create(spec.width, spec.height,
|
|
||||||
spec.format, options, tc.get());
|
|
||||||
});
|
|
||||||
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
#if MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
texture_caches_->RegisterTextureCache(gl_context->cv_texture_cache());
|
texture_caches_->RegisterTextureCache(gl_context->cv_texture_cache());
|
||||||
#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
|
|
|
@ -87,13 +87,15 @@ class GpuResources {
|
||||||
std::map<std::string, std::string> node_key_;
|
std::map<std::string, std::string> node_key_;
|
||||||
std::map<std::string, std::shared_ptr<GlContext>> gl_key_context_;
|
std::map<std::string, std::shared_ptr<GlContext>> gl_key_context_;
|
||||||
|
|
||||||
|
#ifdef MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
|
std::shared_ptr<CvTextureCacheManager> texture_caches_;
|
||||||
|
#endif // MEDIAPIPE_GPU_BUFFER_USE_CV_PIXEL_BUFFER
|
||||||
|
|
||||||
// The pool must be destructed before the gl_context, but after the
|
// The pool must be destructed before the gl_context, but after the
|
||||||
// ios_gpu_data, so the declaration order is important.
|
// ios_gpu_data, so the declaration order is important.
|
||||||
GpuBufferMultiPool gpu_buffer_pool_;
|
GpuBufferMultiPool gpu_buffer_pool_;
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
std::shared_ptr<CvTextureCacheManager> texture_caches_;
|
|
||||||
|
|
||||||
// Note that this is an Objective-C object.
|
// Note that this is an Objective-C object.
|
||||||
MPPGraphGPUData* ios_gpu_data_;
|
MPPGraphGPUData* ios_gpu_data_;
|
||||||
#endif // defined(__APPLE__)
|
#endif // defined(__APPLE__)
|
||||||
|
|
|
@ -12,16 +12,11 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// This class lets calculators allocate GpuBuffers of various sizes, caching
|
|
||||||
// and reusing them as needed. It does so by automatically creating and using
|
|
||||||
// platform-specific buffer pools for the requested sizes.
|
|
||||||
//
|
|
||||||
// This class is not meant to be used directly by calculators, but is instead
|
|
||||||
// used by GlCalculatorHelper to allocate buffers.
|
|
||||||
|
|
||||||
#ifndef MEDIAPIPE_GPU_MULTI_POOL_H_
|
#ifndef MEDIAPIPE_GPU_MULTI_POOL_H_
|
||||||
#define MEDIAPIPE_GPU_MULTI_POOL_H_
|
#define MEDIAPIPE_GPU_MULTI_POOL_H_
|
||||||
|
|
||||||
|
#include "mediapipe/util/resource_cache.h"
|
||||||
|
|
||||||
namespace mediapipe {
|
namespace mediapipe {
|
||||||
|
|
||||||
struct MultiPoolOptions {
|
struct MultiPoolOptions {
|
||||||
|
@ -42,6 +37,81 @@ struct MultiPoolOptions {
|
||||||
|
|
||||||
static constexpr MultiPoolOptions kDefaultMultiPoolOptions;
|
static constexpr MultiPoolOptions kDefaultMultiPoolOptions;
|
||||||
|
|
||||||
|
// MultiPool is a generic class for vending reusable resources of type Item,
|
||||||
|
// which are assumed to be relatively expensive to create, so that reusing them
|
||||||
|
// is beneficial.
|
||||||
|
// Items are classified by Spec; when an item with a given Spec is requested,
|
||||||
|
// an old Item with the same Spec can be reused, if available; otherwise a new
|
||||||
|
// Item will be created. When user code is done with an Item, it is returned
|
||||||
|
// to the pool for reuse.
|
||||||
|
// In order to manage this, a MultiPool contains a map of Specs to SimplePool;
|
||||||
|
// each SimplePool manages Items with the same Spec, which are thus considered
|
||||||
|
// interchangeable.
|
||||||
|
// Item retention and eviction policies are controlled by options.
|
||||||
|
// A concrete example would be a pool of GlTextureBuffer, grouped by dimensions
|
||||||
|
// and format.
|
||||||
|
template <class SimplePool, class Spec, class Item>
|
||||||
|
class MultiPool {
|
||||||
|
public:
|
||||||
|
using SimplePoolFactory = std::function<std::shared_ptr<SimplePool>(
|
||||||
|
const Spec& spec, const MultiPoolOptions& options)>;
|
||||||
|
|
||||||
|
MultiPool(SimplePoolFactory factory = DefaultMakeSimplePool,
|
||||||
|
MultiPoolOptions options = kDefaultMultiPoolOptions)
|
||||||
|
: create_simple_pool_(factory), options_(options) {}
|
||||||
|
|
||||||
|
// Obtains an item. May either be reused or created anew.
|
||||||
|
Item Get(const Spec& spec);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::shared_ptr<SimplePool> DefaultMakeSimplePool(
|
||||||
|
const Spec& spec, const MultiPoolOptions& options) {
|
||||||
|
return SimplePool::Create(spec, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requests a simple buffer pool for the given spec. This may return nullptr
|
||||||
|
// if we have not yet reached a sufficient number of requests to allocate a
|
||||||
|
// pool, in which case the caller should invoke CreateBufferWithoutPool.
|
||||||
|
std::shared_ptr<SimplePool> RequestPool(const Spec& spec);
|
||||||
|
|
||||||
|
absl::Mutex mutex_;
|
||||||
|
mediapipe::ResourceCache<Spec, std::shared_ptr<SimplePool>> cache_
|
||||||
|
ABSL_GUARDED_BY(mutex_);
|
||||||
|
SimplePoolFactory create_simple_pool_ = DefaultMakeSimplePool;
|
||||||
|
MultiPoolOptions options_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class SimplePool, class Spec, class Item>
|
||||||
|
std::shared_ptr<SimplePool> MultiPool<SimplePool, Spec, Item>::RequestPool(
|
||||||
|
const Spec& spec) {
|
||||||
|
std::shared_ptr<SimplePool> pool;
|
||||||
|
std::vector<std::shared_ptr<SimplePool>> evicted;
|
||||||
|
{
|
||||||
|
absl::MutexLock lock(&mutex_);
|
||||||
|
pool = cache_.Lookup(spec, [this](const Spec& spec, int request_count) {
|
||||||
|
return (request_count >= options_.min_requests_before_pool)
|
||||||
|
? create_simple_pool_(spec, options_)
|
||||||
|
: nullptr;
|
||||||
|
});
|
||||||
|
evicted = cache_.Evict(options_.max_pool_count,
|
||||||
|
options_.request_count_scrub_interval);
|
||||||
|
}
|
||||||
|
// Evicted pools, and their buffers, will be released without holding the
|
||||||
|
// lock.
|
||||||
|
return pool;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SimplePool, class Spec, class Item>
|
||||||
|
Item MultiPool<SimplePool, Spec, Item>::Get(const Spec& spec) {
|
||||||
|
std::shared_ptr<SimplePool> pool = RequestPool(spec);
|
||||||
|
if (pool) {
|
||||||
|
// Note: we release our multipool lock before accessing the simple pool.
|
||||||
|
return Item(pool->GetBuffer());
|
||||||
|
} else {
|
||||||
|
return Item(SimplePool::CreateBufferWithoutPool(spec));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mediapipe
|
} // namespace mediapipe
|
||||||
|
|
||||||
#endif // MEDIAPIPE_GPU_MULTI_POOL_H_
|
#endif // MEDIAPIPE_GPU_MULTI_POOL_H_
|
||||||
|
|
Loading…
Reference in New Issue
Block a user