SWDEV-483586 - Unblock staging H2D transfers
Although unpinned copies require synchronizations
in HIP, runtime can avoid syncs for H2D copies with
a staging buffer
Change-Id: If2203c6bc0cbd89742823688dc8e89e9acd873b2
[ROCm/clr commit: 29cc678d8d]
Tento commit je obsažen v:
@@ -1065,7 +1065,7 @@ void VirtualGPU::dispatchBarrierPacket(uint16_t packetHeader, bool skipSignal,
|
||||
fence_dirty_ = true;
|
||||
auto cache_state = extractAqlBits(packetHeader, HSA_PACKET_HEADER_SCRELEASE_FENCE_SCOPE,
|
||||
HSA_PACKET_HEADER_WIDTH_SCRELEASE_FENCE_SCOPE);
|
||||
if (!skipSignal) {
|
||||
if (!skipSignal && (signal.handle == 0)) {
|
||||
// Get active signal for current dispatch if profiling is necessary
|
||||
barrier_packet_.completion_signal =
|
||||
Barriers().ActiveSignal(kInitSignalValueOne, timestamp_);
|
||||
@@ -1188,9 +1188,6 @@ void VirtualGPU::dispatchBarrierValuePacket(uint16_t packetHeader, bool resolveD
|
||||
|
||||
// ================================================================================================
|
||||
void VirtualGPU::ResetQueueStates() {
|
||||
// Release all transfer buffers on this command queue
|
||||
releaseXferWrite();
|
||||
|
||||
// Release all memory dependencies
|
||||
memoryDependency().clear();
|
||||
|
||||
@@ -1234,6 +1231,7 @@ VirtualGPU::VirtualGPU(Device& device, bool profiling, bool cooperative,
|
||||
schedulerSignal_({0}),
|
||||
barriers_(*this),
|
||||
kernarg_pool_signal_(KernelArgPoolNumSignal),
|
||||
managed_buffer_(*this, ManagedBuffer::kPoolNumSignals * device.settings().stagedXferSize_),
|
||||
cuMask_(cuMask),
|
||||
priority_(priority),
|
||||
copy_command_type_(0),
|
||||
@@ -1385,9 +1383,77 @@ bool VirtualGPU::create() {
|
||||
LogError("Could not create signal for copy queue!");
|
||||
return false;
|
||||
}
|
||||
// Create managed buffer for staging copies
|
||||
if (!managed_buffer_.Create()) {
|
||||
LogError("Could not create managed buffer for this queue!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
VirtualGPU::ManagedBuffer::~ManagedBuffer() {
|
||||
for (auto& it : pool_signal_) {
|
||||
if (it.handle != 0) {
|
||||
hsa_signal_destroy(it);
|
||||
}
|
||||
}
|
||||
if (pool_base_ != nullptr) {
|
||||
gpu_.dev().hostFree(pool_base_, pool_size_);
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool VirtualGPU::ManagedBuffer::Create() {
|
||||
pool_chunk_end_ = pool_size_ / kPoolNumSignals;
|
||||
active_chunk_ = 0;
|
||||
// Allocate memory for managed buffer
|
||||
pool_base_ = reinterpret_cast<address>(
|
||||
gpu_.dev().hostAlloc(pool_size_, 0, Device::MemorySegment::kNoAtomics));
|
||||
if (pool_base_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
hsa_agent_t agent = gpu_.dev().getBackendDevice();
|
||||
for (auto& it : pool_signal_) {
|
||||
if (HSA_STATUS_SUCCESS != hsa_signal_create(0, 1, &agent, &it)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
address VirtualGPU::ManagedBuffer::Acquire(uint32_t size) {
|
||||
auto alignment = gpu_.dev().info().globalMemCacheLineSize_;
|
||||
address result = nullptr;
|
||||
result = amd::alignUp(pool_base_ + pool_cur_offset_, alignment);
|
||||
const size_t pool_new_usage = (result + size) - pool_base_;
|
||||
if (pool_new_usage <= pool_chunk_end_) {
|
||||
pool_cur_offset_ = pool_new_usage;
|
||||
return result;
|
||||
} else {
|
||||
// Reset the signal for the barrier packet
|
||||
hsa_signal_silent_store_relaxed(pool_signal_[active_chunk_], kInitSignalValueOne);
|
||||
// Currently don't skip wait signal check, because SDMA engine cna be used in staging copy
|
||||
constexpr bool kSkipSignal = false;
|
||||
// Dispatch a barrier packet into the queue
|
||||
gpu_.dispatchBarrierPacket(kBarrierPacketHeader, kSkipSignal, pool_signal_[active_chunk_]);
|
||||
// Get the next chunk
|
||||
active_chunk_ = ++active_chunk_ % kPoolNumSignals;
|
||||
// Make sure the new active chunk is free
|
||||
bool test = WaitForSignal(pool_signal_[active_chunk_], gpu_.ActiveWait());
|
||||
assert(test && "Runtime can't fail a wait for chunk!");
|
||||
// Make sure the current offset matches the new chunk to avoid possible overlaps
|
||||
// between chunks and issues during recycle
|
||||
pool_cur_offset_ = (active_chunk_ == 0) ? 0 : pool_chunk_end_;
|
||||
pool_chunk_end_ = pool_cur_offset_ + pool_size_ / kPoolNumSignals;
|
||||
result = amd::alignUp(pool_base_ + pool_cur_offset_, alignment);
|
||||
pool_cur_offset_ = (result + size) - pool_base_;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool VirtualGPU::initPool(size_t kernarg_pool_size) {
|
||||
kernarg_pool_size_ = kernarg_pool_size;
|
||||
@@ -3562,28 +3628,6 @@ void VirtualGPU::flush(amd::Command* list, bool wait) {
|
||||
releasePinnedMem();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void VirtualGPU::addXferWrite(Memory& memory) {
|
||||
//! @note: ROCr backend doesn't have per resource busy tracking, hence runtime has to wait
|
||||
//! unconditionally, before it can release pinned memory
|
||||
releaseGpuMemoryFence();
|
||||
if (xferWriteBuffers_.size() > 7) {
|
||||
dev().xferWrite().release(*this, *xferWriteBuffers_.front());
|
||||
xferWriteBuffers_.erase(xferWriteBuffers_.begin());
|
||||
}
|
||||
|
||||
// Delay destruction
|
||||
xferWriteBuffers_.push_back(&memory);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void VirtualGPU::releaseXferWrite() {
|
||||
for (auto& memory : xferWriteBuffers_) {
|
||||
dev().xferWrite().release(*this, *memory);
|
||||
}
|
||||
xferWriteBuffers_.resize(0);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void VirtualGPU::addPinnedMem(amd::Memory* mem) {
|
||||
//! @note: ROCr backend doesn't have per resource busy tracking, hence runtime has to wait
|
||||
|
||||
Odkázat v novém úkolu
Zablokovat Uživatele