mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-04-29 03:00:14 -04:00
DMARef infra (#10753)
Co-authored-by: wozeparrot <wozeparrot@gmail.com>
This commit is contained in:
@@ -168,6 +168,9 @@ class Buffer:
|
||||
def __repr__(self):
|
||||
return f"<buf real:{self.is_allocated()} device:{self.device} size:{self.size} dtype:{self.dtype}" + \
|
||||
(f" offset:{self.offset}" if self._base is not None else "") + (f" {self.options=}" if self.options is not None else "") + ">"
|
||||
def as_dmaref(self) -> DMARef:
|
||||
assert hasattr(self.allocator, "_as_dmaref"), f"Device {self.device} doesn't support DMA"
|
||||
return self.allocator._as_dmaref(self._buf)
|
||||
def as_buffer(self, allow_zero_copy=False, force_zero_copy=False) -> memoryview:
|
||||
# zero copy with as_buffer (disabled by default due to use after free)
|
||||
if (force_zero_copy or allow_zero_copy) and hasattr(self.allocator, '_as_buffer') and (self.options is None or self.options.image is None):
|
||||
@@ -199,6 +202,19 @@ class Buffer:
|
||||
if self._base is not None: return Buffer(self.device, size, dtype, base=self._base, offset=self.offset+offset)
|
||||
return Buffer(self.device, size, dtype, base=self, offset=offset)
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DMACPURef:
|
||||
addr: int
|
||||
size: int
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class DMAFdRef:
|
||||
fd: int
|
||||
offset: int
|
||||
size: int
|
||||
|
||||
DMARef = DMACPURef|DMAFdRef
|
||||
|
||||
DeviceType = TypeVar('DeviceType', bound='Compiled')
|
||||
|
||||
# TODO: size, dest, src are the same type. can we enforce this?
|
||||
@@ -255,6 +271,7 @@ class _MallocAllocator(LRUAllocator['Compiled']):
|
||||
offset = round_up(ctypes.addressof(buffer), alignment) - ctypes.addressof(buffer)
|
||||
return (ctypes.c_uint8 * size).from_buffer(buffer, offset)
|
||||
def _as_buffer(self, src) -> memoryview: return flat_mv(memoryview(src))
|
||||
def _as_dmaref(self, buf): return DMACPURef(ctypes.addressof(buf), ctypes.sizeof(buf))
|
||||
def _copyin(self, dest, src:memoryview): ctypes.memmove(dest, from_mv(src), len(src))
|
||||
def _copyout(self, dest:memoryview, src): ctypes.memmove(from_mv(dest), src, len(dest))
|
||||
def _offset(self, buf, size:int, offset:int): return from_mv(self._as_buffer(buf)[offset:offset+size])
|
||||
|
||||
@@ -6,7 +6,7 @@ from dataclasses import dataclass
|
||||
from tinygrad.runtime.support.hcq import HCQCompiled, HCQAllocator, HCQBuffer, HWQueue, CLikeArgsState, HCQSignal, HCQProgram, FileIOInterface
|
||||
from tinygrad.runtime.support.hcq import MMIOInterface
|
||||
from tinygrad.uop.ops import sint
|
||||
from tinygrad.device import Compiled, BufferSpec
|
||||
from tinygrad.device import Compiled, DMAFdRef, BufferSpec
|
||||
from tinygrad.helpers import getenv, to_mv, round_up, data64_le, all_same, flatten, DEBUG, AMD_LLVM, PROFILE, ProfileEvent
|
||||
from tinygrad.renderer.cstyle import AMDRenderer
|
||||
from tinygrad.renderer.llvmir import AMDLLVMRenderer
|
||||
@@ -469,6 +469,7 @@ class AMDProgram(HCQProgram):
|
||||
class AMDAllocator(HCQAllocator['AMDDevice']):
|
||||
def __init__(self, dev:AMDDevice):
|
||||
super().__init__(dev, copy_bufs=getattr(dev.iface, 'copy_bufs', None), max_copyout_size=0x1000 if dev.is_usb() else None)
|
||||
if hasattr(dev.iface, "as_dmaref"): self._as_dmaref = dev.iface.as_dmaref
|
||||
|
||||
def _alloc(self, size:int, options:BufferSpec) -> HCQBuffer:
|
||||
return self.dev.iface.alloc(size, host=options.host, uncached=options.uncached, cpu_access=options.cpu_access)
|
||||
@@ -598,6 +599,12 @@ class KFDIface:
|
||||
if mem.va_addr: FileIOInterface.munmap(mem.va_addr, mem.size)
|
||||
kfd.AMDKFD_IOC_FREE_MEMORY_OF_GPU(self.kfd, handle=mem.meta.handle)
|
||||
|
||||
def as_dmaref(self, mem:HCQBuffer) -> DMAFdRef:
|
||||
base = mem._base if mem._base is not None else mem
|
||||
dmaref = DMAFdRef(kfd.AMDKFD_IOC_EXPORT_DMABUF(KFDIface.kfd, handle=base.meta.handle, flags=0).dmabuf_fd, mem.va_addr-base.va_addr, mem.size)
|
||||
weakref.finalize(dmaref, os.close, dmaref.fd)
|
||||
return dmaref
|
||||
|
||||
def map(self, mem):
|
||||
if self.gpu_id in getattr(mem.meta, "mapped_gpu_ids", []): return
|
||||
mem.meta.__setattr__("mapped_gpu_ids", getattr(mem.meta, "mapped_gpu_ids", []) + [self.gpu_id])
|
||||
|
||||
Reference in New Issue
Block a user