Add pooling for Signal ABI blocks (SharedSignal).

Makes better use of memory and greatly reduces mmap count.

Change-Id: Ib444cd1ccd144986adbcc7cec297a966e2c08bc7


[ROCm/ROCR-Runtime commit: 8323b2e1d7]
Tá an tiomantas seo le fáil i:
Sean Keely
2018-11-08 19:09:24 -06:00
tuismitheoir 9652ba6de2
tiomantas ed18ee7f38
D'athraigh 12 comhad le 191 breiseanna agus 30 scriosta
@@ -68,35 +68,89 @@ class BaseShared {
static std::function<void(void*)> free_;
};
/// @brief Container for object located in GPU visible host memory.
/// Alignment defaults to __alignof(T) but may be increased.
template <typename T, size_t Align = 0> class Shared final : private BaseShared {
/// @brief Default Allocator for Shared. Ensures allocations are whole pages.
template <typename T> class PageAllocator : private BaseShared {
public:
Shared() {
assert(allocate_ != nullptr && free_ != nullptr &&
"Shared object allocator is not set");
static_assert((__alignof(T) <= Align) || (Align == 0),
"Align is less than alignof(T)");
__forceinline static T* alloc() {
T* ret = reinterpret_cast<T*>(allocate_(AlignUp(sizeof(T), 4096), 4096, 0));
if (ret == nullptr) throw std::bad_alloc();
shared_object_ =
reinterpret_cast<T*>(allocate_(sizeof(T), Max(__alignof(T), Align), 0));
if (shared_object_ == nullptr) throw std::bad_alloc();
MAKE_NAMED_SCOPE_GUARD(throwGuard, [&]() { free_(ret); });
MAKE_NAMED_SCOPE_GUARD(throwGuard, [&]() { free_(shared_object_); });
new (shared_object_) T;
new (ret) T;
throwGuard.Dismiss();
return ret;
}
__forceinline static void free(T* ptr) {
if (ptr != nullptr) {
ptr->~T();
free_(ptr);
}
}
};
/// @brief Container for object located in GPU visible host memory.
/// If a custom allocator is not given then data will be placed in dedicated pages.
template <typename T, typename Allocator = PageAllocator<T>>
class Shared final : private BaseShared {
public:
explicit Shared(Allocator* pool = nullptr) : pool_(pool) {
assert(allocate_ != nullptr && free_ != nullptr &&
"Shared object allocator is not set");
if (pool_)
shared_object_ = pool_->alloc();
else
shared_object_ = PageAllocator<T>::alloc();
}
~Shared() {
assert(allocate_ != nullptr && free_ != nullptr && "Shared object allocator is not set");
if (pool_)
pool_->free(shared_object_);
else
PageAllocator<T>::free(shared_object_);
}
Shared(Shared&& rhs) {
this->~Shared();
shared_object_ = rhs.shared_object_;
rhs.shared_object_ = nullptr;
pool_ = rhs.pool_;
rhs.pool_ = nullptr;
}
Shared& operator=(Shared&& rhs) {
this->~Shared();
shared_object_ = rhs.shared_object_;
rhs.shared_object_ = nullptr;
pool_ = rhs.pool_;
rhs.pool_ = nullptr;
return *this;
}
T* shared_object() const { return shared_object_; }
private:
T* shared_object_;
Allocator* pool_;
};
template <typename T> class Shared<T, PageAllocator<T>> final : private BaseShared {
public:
Shared() {
assert(allocate_ != nullptr && free_ != nullptr && "Shared object allocator is not set");
shared_object_ = PageAllocator<T>::alloc();
}
~Shared() {
assert(allocate_ != nullptr && free_ != nullptr &&
"Shared object allocator is not set");
if (shared_object_ != nullptr) {
shared_object_->~T();
free_(shared_object_);
}
PageAllocator<T>::free(shared_object_);
}
Shared(Shared&& rhs) {