(self, data:ConstType|bytes|list|tuple|UOp|'numpy.ndarray'|pathlib.Path|None,
device:str|tuple|list|None=None, dtype:DTypeLike|None=None)
| 92 | training: ClassVar[bool] = False |
| 93 | |
| 94 | def __init__(self, data:ConstType|bytes|list|tuple|UOp|'numpy.ndarray'|pathlib.Path|None, |
| 95 | device:str|tuple|list|None=None, dtype:DTypeLike|None=None): |
| 96 | if device is None: |
| 97 | if isinstance(data, pathlib.Path): device = f"DISK:{data.resolve()}" # keep it on the disk if device is None |
| 98 | elif isinstance(data, UOp): device = data.device |
| 99 | _dtype:DType|None = to_dtype(dtype) if dtype is not None else None |
| 100 | _device:str|tuple[str, ...] = canonicalize_device(device) |
| 101 | del device, dtype |
| 102 | |
| 103 | # tensors can have gradients if you have called .backward |
| 104 | self.grad:Tensor|None = None |
| 105 | |
| 106 | self.is_param:bool = True |
| 107 | |
| 108 | # create a UOp from the different types of inputs |
| 109 | if isinstance(data, UOp): |
| 110 | assert _dtype is None or _dtype==data.dtype or data.dtype==dtypes.weakint, f"dtype mismatch: {_dtype} vs {data.dtype}" |
| 111 | # 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 |
| 112 | if data.dtype == dtypes.weakint: data = Tensor.from_uop(data, device=_device).uop |
| 113 | elif data is None: |
| 114 | data = UOp.const(_dtype or dtypes.default_float, 0, _device) |
| 115 | elif isinstance(data, get_args(ConstType)): |
| 116 | data = UOp.const(_dtype or dtypes.from_py(data), data, _device) |
| 117 | elif isinstance(data, bytes): data = _frompy(data, _dtype or dtypes.uint8, _device) |
| 118 | elif isinstance(data, (list, tuple)): |
| 119 | if _dtype is None: |
| 120 | if (d := fully_flatten(data)) and all(isinstance(s, bool) for s in d): _dtype = dtypes.bool |
| 121 | else: _dtype = dtypes.default_int if d and all_int(d) else dtypes.default_float # NOTE: this works because all_int([True, False]) is True |
| 122 | if _dtype in [dtypes.bfloat16, *dtypes.fp8s]: data = _frompy(data, dtypes.float32, _device).cast(_dtype) |
| 123 | else: data = _frompy(data, _dtype, _device) |
| 124 | elif is_numpy_ndarray(data): |
| 125 | import numpy as np |
| 126 | assert isinstance(data, np.ndarray), f"expected np.ndarray, got {data}" |
| 127 | if data.shape == (): |
| 128 | data = UOp.const(_dtype or _from_np_dtype(data.dtype), data.item(), _device) |
| 129 | else: |
| 130 | data = _fromnp(data.astype(npdtype) if _dtype is not None and (npdtype:=_to_np_dtype(_dtype)) is not None else data) |
| 131 | elif isinstance(data, pathlib.Path): |
| 132 | _dtype = _dtype or dtypes.uint8 |
| 133 | data = UOp.new_buffer(f"DISK:{data.resolve()}", data.stat().st_size // _dtype.itemsize, _dtype) |
| 134 | |
| 135 | # by this point, it has to be a UOp |
| 136 | if not isinstance(data, UOp): raise RuntimeError(f"can't create Tensor from {data!r} with type {type(data)}") |
| 137 | |
| 138 | # data might be on a different device |
| 139 | self.uop:UOp = data if data.device is None or data.device == _device else data.copy_to_device(_device) |
| 140 | |
| 141 | # add to all_tensors after construction succeeds |
| 142 | all_tensors[weakref.ref(self)] = None |
| 143 | |
| 144 | @suppress_finalizing |
| 145 | def __del__(self): all_tensors.pop(weakref.ref(self), None) |
nothing calls this directly
no test coverage detected