mirror of
https://github.com/tinygrad/tinygrad.git
synced 2026-08-30 02:46:06 +00:00
@@ -18,13 +18,16 @@ class TestTensorVariable(unittest.TestCase):
|
||||
self.assertListEqual((vv * t).tolist(), [2, 2, 2])
|
||||
except RuntimeError: pass
|
||||
|
||||
# TODO: a Variable PARAM lowers to int32, so a bound value that doesn't fit int32 truncates or fails to bind
|
||||
@unittest.expectedFailure
|
||||
def test_large_range_variable(self):
|
||||
vv = Variable("b", 0, 2**40).bind(2**35)
|
||||
# TODO: pm_lower_index_dtype lowers ALU PARAM to int32 unconditionally
|
||||
try:
|
||||
self.assertEqual(Tensor(vv).item(), 2**35)
|
||||
except AssertionError:
|
||||
pass
|
||||
self.assertEqual(Tensor(Variable("b", 0, 2**40).bind(2**35)).item(), 2**35)
|
||||
|
||||
def test_variable_defers_like_a_literal(self):
|
||||
vv = Variable("a", 1, 10).bind(2)
|
||||
self.assertEqual(Tensor(vv).dtype, dtypes.weakint)
|
||||
self.assertEqual((Tensor(vv) + Tensor([1], dtype=dtypes.int8)).dtype, dtypes.int8) # takes the concrete side, no widening
|
||||
self.assertEqual(Tensor(vv).item(), 2) # a read commits at default_int
|
||||
|
||||
def test_variable_tensor_dtype_arg(self):
|
||||
vv = Variable("a", 1, 10).bind(2)
|
||||
|
||||
+1
-2
@@ -162,8 +162,7 @@ if (env_default_float := getenv("DEFAULT_FLOAT", "")):
|
||||
DTypeLike = str|DType
|
||||
def to_dtype(dtype:DTypeLike) -> DType: return dtype if isinstance(dtype, DType) else getattr(dtypes, dtype.lower())
|
||||
def strong_dtype(dtype:DType) -> DType:
|
||||
# TODO: weakint
|
||||
return dtypes.default_float if dtype == dtypes.weakfloat else dtype
|
||||
return {dtypes.weakint: dtypes.default_int, dtypes.weakfloat: dtypes.default_float}.get(dtype, dtype)
|
||||
|
||||
# https://jax.readthedocs.io/en/latest/jep/9407-type-promotion.html
|
||||
# we don't support complex type
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from typing import TYPE_CHECKING, Callable, Self
|
||||
from tinygrad.dtype import ConstType, DTypeLike, Invalid, dtypes, to_dtype
|
||||
from tinygrad.dtype import ConstType, DTypeLike, Invalid, dtypes, to_dtype, strong_dtype
|
||||
from tinygrad.helpers import argfix, prod
|
||||
from tinygrad.mixin.dtype import DTypeMixin
|
||||
from tinygrad.mixin.movement import MovementMixin
|
||||
@@ -78,6 +78,8 @@ class CreationMixin(DTypeMixin, MovementMixin):
|
||||
from tinygrad.uop.ops import UOp
|
||||
new_shape = argfix(shape)
|
||||
dt = to_dtype(dtype) if dtype is not None else fill_value.dtype if isinstance(fill_value, UOp) else dtypes.from_py(fill_value)
|
||||
# materializing commits an inferred weak width
|
||||
if dtype is None and buffer: dt = strong_dtype(dt)
|
||||
val = cls.const(dt, fill_value)
|
||||
val = val.reshape((1,)*len(new_shape)).expand(new_shape)
|
||||
if not buffer or val._uop.base.arg is not Invalid or val.dtype == dt: return val.clone(device=device) if buffer else val
|
||||
|
||||
+6
-7
@@ -6,7 +6,7 @@ if TYPE_CHECKING: import numpy
|
||||
from tinygrad.dtype import DType, DTypeLike, dtypes, ConstType, least_upper_dtype, to_dtype, strong_dtype, _from_np_dtype, _to_np_dtype, PyConst
|
||||
from tinygrad.helpers import all_int, getenv, fetch, Metadata, TRACEMETA, TracingKey
|
||||
from tinygrad.helpers import cpu_profile, suppress_finalizing, disable_gc
|
||||
from tinygrad.uop.ops import UOp, Ops, sint, all_metadata, _index_to_concrete_int, Variable, ConstLike
|
||||
from tinygrad.uop.ops import UOp, Ops, sint, all_metadata, Variable, ConstLike
|
||||
from tinygrad.mixin.rand import RandMixin
|
||||
from tinygrad.schedule import create_linear_with_vars
|
||||
from tinygrad.device import Buffer, canonicalize_device
|
||||
@@ -70,16 +70,13 @@ class Tensor(RandMixin):
|
||||
self.is_param:bool = True
|
||||
|
||||
# create a UOp from the different types of inputs
|
||||
if isinstance(data, UOp):
|
||||
# if data is dtype.weakint that means that this is a symbolic int and we need to lower it to something we can make a Tensor out of
|
||||
if data.dtype == dtypes.weakint: data = _index_to_concrete_int(data)
|
||||
elif data is None:
|
||||
if data is None:
|
||||
data = UOp.const(_dtype or dtypes.default_float, 0)
|
||||
elif isinstance(data, get_args(ConstType)):
|
||||
data = UOp.const(_dtype or dtypes.from_py(data), data)
|
||||
elif is_numpy_ndarray(data) and data.shape == ():
|
||||
data = UOp.const(_dtype or _from_np_dtype(data.dtype), data.item())
|
||||
else:
|
||||
elif not isinstance(data, UOp):
|
||||
if _dtype in dtypes.weaks: raise RuntimeError(f"cannot create storage for weak dtype {_dtype}")
|
||||
if isinstance(data, bytes): data = UOp._frompy(data, _dtype or dtypes.uint8, _device)
|
||||
elif isinstance(data, (list, tuple)):
|
||||
@@ -176,7 +173,9 @@ class Tensor(RandMixin):
|
||||
|
||||
def linear_with_vars(self, *lst:Tensor) -> tuple[UOp, dict[str, int]]:
|
||||
"""Creates the LINEAR UOp needed to realize these Tensor(s), with Variables."""
|
||||
if any(t.dtype in dtypes.weaks for t in (self,)+lst): raise RuntimeError("cannot realize a weak dtype; cast to a concrete dtype first")
|
||||
# weakness ends where storage begins
|
||||
if any(t.dtype in dtypes.weaks and t.uop.device is not None for t in (self,)+lst):
|
||||
raise RuntimeError("cannot realize a weak dtype; cast to a concrete dtype first")
|
||||
big_sink, becomes_map = transform_to_call(UOp.sink(*[x.uop for x in (self,)+lst]))
|
||||
_apply_map_to_tensors(becomes_map, name="buffers")
|
||||
return create_linear_with_vars(big_sink)
|
||||
|
||||
@@ -1749,7 +1749,6 @@ pm_lower_index_dtype = PatternMatcher([
|
||||
allow_any_len=True, name="u"),
|
||||
lambda u,buf,gate,idx: u.replace(src=(buf, idx.cast(dtypes.int).valid(gate))+u.src[2:]) if buf.max_numel()-1 <= dtypes.int32.max else None),
|
||||
])
|
||||
def _index_to_concrete_int(u:UOp) -> UOp: return graph_rewrite(u.sink(), pm_lower_index_dtype).src[0]
|
||||
|
||||
_substitute = PatternMatcher([(UPat(tuple(Ops), name="x"), lambda ctx,x: ctx.get(x,None))])
|
||||
_pm_resolve_params = PatternMatcher([(UPat(Ops.PARAM, name="p"), lambda ctx,p: ctx[p.arg.slot])])
|
||||
|
||||
Reference in New Issue
Block a user