Files
StarPilot/tinygrad_repo/test/runtime/test_setitem_schedule.py
2026-10-20 03:55:45 +00:00

127 lines
4.0 KiB
Python

import unittest
from tinygrad import Tensor, Device, dtypes, GlobalCounters
from test.helpers import assert_kernel_count
class TestSetitemInto(unittest.TestCase):
def test_setitem_into_unrealized(self):
GlobalCounters.reset()
t = Tensor.arange(4, dtype=dtypes.int32).reshape(2, 2)
assert_kernel_count(0)
t[1] = 5
assert_kernel_count(0)
t.realize()
assert_kernel_count(0)
self.assertEqual(GlobalCounters.global_mem, 0)
self.assertListEqual(t.tolist(), [[0, 1], [5, 5]])
def test_setitem_into_unrealized_sliced_compute(self):
# base computation contains SHRINK from prior slicing (like QR decomposition pattern)
GlobalCounters.reset()
a = Tensor.arange(8, dtype=dtypes.int32).reshape(2, 4)
w = a[0] + a[1] # unrealized ADD with SHRINK in graph: [4, 6, 8, 10]
assert_kernel_count(0)
w[1] = 99
assert_kernel_count(0)
w.realize()
assert_kernel_count(0)
self.assertEqual(GlobalCounters.global_mem, 0)
self.assertListEqual(w.tolist(), [4, 99, 8, 10])
def test_setitem_into_empty(self):
GlobalCounters.reset()
t = Tensor.empty(4, dtype=dtypes.int32)
t[1] = 5
assert_kernel_count(0)
t.realize()
assert_kernel_count(1)
self.assertEqual(GlobalCounters.global_mem, 4)
t[1].realize()
t.realize()
assert_kernel_count(1)
self.assertEqual(t[1].item(), 5)
def test_setitem_into_empty_alu(self):
GlobalCounters.reset()
t = Tensor.empty(4, dtype=dtypes.int32) + 1
assert_kernel_count(0)
t[1] = 5
assert_kernel_count(0)
t.realize()
assert_kernel_count(1)
self.assertLessEqual(GlobalCounters.global_mem, 32)
t[1].realize()
t.realize()
assert_kernel_count(1)
self.assertEqual(t[1].item(), 5)
def test_setitem_into_tensor(self):
t = Tensor([1, 2, 3, 4], dtype=dtypes.int32).realize()
GlobalCounters.reset()
t[1] = 5
assert_kernel_count(0)
t[1].realize()
assert_kernel_count(1)
self.assertEqual(GlobalCounters.global_mem, 4)
t.realize()
assert_kernel_count(1)
self.assertListEqual(t.tolist(), [1, 5, 3, 4])
def test_setitem_into_tensor_alu(self):
t = Tensor([1, 2, 3, 4], dtype=dtypes.int32).realize() + 1
GlobalCounters.reset()
t[1] = 5
assert_kernel_count(0)
t[1].realize()
assert_kernel_count(1)
self.assertLessEqual(GlobalCounters.global_mem, 32)
t[1].realize()
t.realize()
assert_kernel_count(1)
self.assertListEqual(t.tolist(), [2, 5, 4, 5])
def test_setitem_into_const(self):
GlobalCounters.reset()
t = Tensor.ones(4, dtype=dtypes.int32, buffer=False)
t[1] = 5
assert_kernel_count(0)
t.realize()
assert_kernel_count(0)
self.assertEqual(GlobalCounters.global_mem, 0)
self.assertListEqual(t.tolist(), [1, 5, 1, 1])
def test_setitem_into_const_alu(self):
GlobalCounters.reset()
t = Tensor.ones(4, dtype=dtypes.int32, buffer=False) + 1
t[1] = 5
assert_kernel_count(0)
t.realize()
assert_kernel_count(0)
self.assertEqual(GlobalCounters.global_mem, 0)
self.assertListEqual(t.tolist(), [2, 5, 2, 2])
def test_setitem_into_arange(self):
# NOTE: arange has no real buffer, but assigning to it is fine
GlobalCounters.reset()
other = Tensor.arange(4, dtype=dtypes.int32)
t = Tensor.arange(4, dtype=dtypes.int32)
self.assertIs(other.uop, t.uop)
t[1] = 5
assert_kernel_count(0)
t.realize()
assert_kernel_count(0)
self.assertListEqual(t.tolist(), [0, 5, 2, 3])
@unittest.skipUnless(Device.DEFAULT != "CPU", "source must be on another device")
def test_setitem_slice_assign_from_other_device(self):
# Copy and assign; CL and WEBGPU also need a kernel to materialize the source slice (no buffer views).
a = Tensor.ones(20, device="CPU")
b = Tensor.arange(20).float().clone()
Tensor.realize(a, b)
GlobalCounters.reset()
a[10:12].assign(b[13:15].to(a.device)).realize()
assert_kernel_count(3 if Device.DEFAULT in {"CL", "WEBGPU"} else 2)
self.assertListEqual(a.tolist(), [1.0]*10 + [13.0, 14.0] + [1.0]*8)
if __name__ == '__main__':
unittest.main()