[Gpu] Allocate nothing per host DMA fill or copy
A DMA fill the buffer cache completes on the host allocated a 16 KiB array for every call, even though almost all of them are label-sized, and a host copy allocated a 64 KiB array per call. WriteHostMemory then scanned every registered buffer for each write it made. The fill builds its repeating chunk in a stack buffer sized to the fill, the copy rents its staging buffer from the shared pool, and WriteHostMemory walks only the registered buffers the write actually overlaps, which it can do because the registry is ordered and disjoint.
This commit is contained in:
parent
13d0ade074
commit
4ba0c6945a
|
|
@ -325,8 +325,11 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
|
|||
throw SubmissionScheduler.Fatal($"Could not write the required direct backing: addr=0x{guestAddress:X16} size=0x{data.Length:X16}");
|
||||
}
|
||||
|
||||
// Registered buffers are ordered and disjoint: walk only the ones the write overlaps.
|
||||
var end = guestAddress + (ulong)data.Length;
|
||||
for (var index = 0; index < _registry.RegisteredCount; index++)
|
||||
for (var index = _registry.FindFirstOverlappingIndex(guestAddress);
|
||||
index < _registry.RegisteredCount && _registry.GetRegisteredAddress(index) < end;
|
||||
index++)
|
||||
{
|
||||
var address = _registry.GetRegisteredAddress(index);
|
||||
var bufferIdentifier = _registry.GetRegisteredIdentifier(index);
|
||||
|
|
@ -376,9 +379,10 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
|
|||
images.InvalidateMemory(guestAddress, size);
|
||||
}
|
||||
|
||||
var values = new uint[4096];
|
||||
Array.Fill(values, value);
|
||||
var bytes = MemoryMarshal.AsBytes<uint>(values);
|
||||
// Labels and small clears dominate; fill a stack chunk once and repeat it.
|
||||
Span<uint> values = stackalloc uint[(int)Math.Min(size / sizeof(uint), 1024UL)];
|
||||
values.Fill(value);
|
||||
var bytes = MemoryMarshal.AsBytes(values);
|
||||
for (ulong offset = 0; offset < size;)
|
||||
{
|
||||
var chunk = (int)Math.Min(size - offset, (ulong)bytes.Length);
|
||||
|
|
@ -420,17 +424,24 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
|
|||
images.InvalidateMemory(dstVaddr, size);
|
||||
}
|
||||
|
||||
var bytes = new byte[64 * 1024];
|
||||
for (ulong offset = 0; offset < size;)
|
||||
var bytes = System.Buffers.ArrayPool<byte>.Shared.Rent((int)Math.Min(size, 64UL * 1024));
|
||||
try
|
||||
{
|
||||
var chunk = (int)Math.Min(size - offset, (ulong)bytes.Length);
|
||||
if (!_backing.TryReadBacking(srcVaddr + offset, bytes.AsSpan(0, chunk)))
|
||||
for (ulong offset = 0; offset < size;)
|
||||
{
|
||||
throw SubmissionScheduler.Fatal("The host DMA source has no direct backing.");
|
||||
}
|
||||
var chunk = (int)Math.Min(size - offset, (ulong)bytes.Length);
|
||||
if (!_backing.TryReadBacking(srcVaddr + offset, bytes.AsSpan(0, chunk)))
|
||||
{
|
||||
throw SubmissionScheduler.Fatal("The host DMA source has no direct backing.");
|
||||
}
|
||||
|
||||
WriteHostMemory(dstVaddr + offset, bytes.AsSpan(0, chunk));
|
||||
offset += (ulong)chunk;
|
||||
WriteHostMemory(dstVaddr + offset, bytes.AsSpan(0, chunk));
|
||||
offset += (ulong)chunk;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.Buffers.ArrayPool<byte>.Shared.Return(bytes);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue