From 97022960ae1fe3d898b758fd67e3dbe14a985fee Mon Sep 17 00:00:00 2001 From: nimlgen <138685161+nimlgen@users.noreply.github.com> Date: Sun, 16 Aug 2026 01:01:36 +0300 Subject: [PATCH] device: fix remap (#17549) --- test/device/test_hcq2.py | 8 ++++++++ tinygrad/device.py | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/test/device/test_hcq2.py b/test/device/test_hcq2.py index 19d72d7bb8..a8ffe60a29 100644 --- a/test/device/test_hcq2.py +++ b/test/device/test_hcq2.py @@ -10,5 +10,13 @@ class TestHCQ2(unittest.TestCase): with patch.object(Device[Device.DEFAULT], "has_copy_queue", False): np.testing.assert_equal(Tensor(np.arange(61, dtype=np.float32)).to(Device.DEFAULT).contiguous().realize().numpy(), np.arange(61)) + def test_overlapping_device_tuples(self): + # an op on a wide device tuple followed by an op on an overlapping smaller tuple used to MMU-fault the smaller one + d4, d2 = tuple(f"{Device.DEFAULT}:{i}" for i in range(4)), tuple(f"{Device.DEFAULT}:{i}" for i in range(2)) + ref = Tensor.arange(16).contiguous().realize() + Tensor(ref.uop.copy_to_device(d4)).realize() + out = Tensor.ones(8).shard(d2, axis=0).contiguous().realize() + np.testing.assert_equal(out.numpy(), np.ones(8)) + if __name__ == "__main__": unittest.main() diff --git a/tinygrad/device.py b/tinygrad/device.py index 6f796e07a6..6176ced789 100644 --- a/tinygrad/device.py +++ b/tinygrad/device.py @@ -103,7 +103,7 @@ class Buffer: def __init__(self, device:str, size:int, dtype:DType, opaque:Any=None, options:BufferSpec|None=None, initial_value:bytes|pickle.PickleBuffer|None=None, uop_refcount=0, base:Buffer|None=None, offset:int=0, preallocate=False): assert isinstance(dtype, DType) - self.device, self.size, self.dtype, self.options, self.offset, self.allocated_views = device, size, dtype, options, offset, 0 + self.device, self.size, self.dtype, self.options, self.offset, self.allocated_views = Device.canonicalize(device), size, dtype, options, offset, 0 self._bufs: dict[str, Any] = {} if base is None: assert offset == 0, "base buffers can't have offset" @@ -116,7 +116,7 @@ class Buffer: if isinstance(initial_value, pickle.PickleBuffer): initial_value.release() else: assert base._base is None, "base can't have a base" - assert device == base.device, "base must have the same device" + assert self.device == base.device, "base must have the same device" self._base = base if preallocate: self.allocate() @property @@ -133,7 +133,7 @@ class Buffer: # check if the underlying buffer is allocated, possibly from the base object def is_allocated(self) -> bool: return self.base.is_allocated() if self._base is not None else self.device in self._bufs def get_buf(self, device: str) -> Any: - if device not in self._bufs: + if (device:=Device.canonicalize(device)) not in self._bufs: allocator = Device[device].allocator if device == self.device: self.ensure_allocated() elif self._base is not None: self._bufs[device] = allocator._offset(self._base.get_buf(device), self.nbytes, self.offset)