forked from tinygrad/tinygrad
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aef4a496b1 | ||
|
|
7383ab9b80 |
@@ -269,7 +269,8 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
# load in weights
|
# load in weights
|
||||||
with WallTimeEvent(BenchEvent.LOAD_WEIGHTS):
|
with WallTimeEvent(BenchEvent.LOAD_WEIGHTS):
|
||||||
load_state_dict(model, torch_load(fetch('https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt', 'sd-v1-4.ckpt'))['state_dict'], verbose=False, strict=False, realize=False)
|
model_bin = fetch('https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt', 'sd-v1-4.ckpt')
|
||||||
|
load_state_dict(model, torch_load(model_bin)['state_dict'], verbose=False, strict=False, realize=False)
|
||||||
|
|
||||||
if args.fp16:
|
if args.fp16:
|
||||||
for k,v in get_state_dict(model).items():
|
for k,v in get_state_dict(model).items():
|
||||||
|
|||||||
@@ -418,5 +418,32 @@ class TestPathTensor(unittest.TestCase):
|
|||||||
Tensor(pathlib.Path(test_file)).tolist()
|
Tensor(pathlib.Path(test_file)).tolist()
|
||||||
os.chmod(test_file, 0o644)
|
os.chmod(test_file, 0o644)
|
||||||
assert Tensor(pathlib.Path(test_file)).tolist(), list(range(10))
|
assert Tensor(pathlib.Path(test_file)).tolist(), list(range(10))
|
||||||
|
|
||||||
|
class TestDiskTensorMovement(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.fn = pathlib.Path(temp("custom_disk_range"))
|
||||||
|
self.fn.unlink(missing_ok=True)
|
||||||
|
Tensor.arange(100, dtype=dtypes.uint8).to(f"disk:{str(self.fn)}").realize()
|
||||||
|
|
||||||
|
def test_simple_read(self):
|
||||||
|
t = Tensor(self.fn)
|
||||||
|
self.assertTrue(Tensor.all(t.to(None) == Tensor.arange(100, dtype=dtypes.uint8)).item())
|
||||||
|
|
||||||
|
def test_slice_read(self):
|
||||||
|
t = Tensor(self.fn)
|
||||||
|
self.assertListEqual(t[16:18].tolist(), [16,17])
|
||||||
|
|
||||||
|
# TODO: fix this! at least assert on it
|
||||||
|
@unittest.expectedFailure
|
||||||
|
def test_slice_read_cat(self):
|
||||||
|
t = Tensor(self.fn)
|
||||||
|
self.assertListEqual(Tensor.cat(t[16:18], t[20:22]).tolist(), [16,17,20,21])
|
||||||
|
|
||||||
|
# TODO: fix this! at least assert on it
|
||||||
|
@unittest.expectedFailure
|
||||||
|
def test_slice_sum(self):
|
||||||
|
t = Tensor(self.fn)
|
||||||
|
self.assertListEqual((t[16:18]+t[20:22]).tolist(), [16+20,17+21])
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
+13
-6
@@ -1,6 +1,6 @@
|
|||||||
import json, pathlib, zipfile, pickle, tarfile, struct, functools, io
|
import json, pathlib, zipfile, pickle, tarfile, struct, functools, io
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from typing import Any, Callable, BinaryIO, Iterable
|
from typing import Any, Callable, BinaryIO, Iterable, cast
|
||||||
from tinygrad.tensor import Tensor
|
from tinygrad.tensor import Tensor
|
||||||
from tinygrad.dtype import dtypes
|
from tinygrad.dtype import dtypes
|
||||||
from tinygrad.helpers import prod, argsort, DEBUG, Timing, CI, unwrap, GlobalCounters, tqdm, round_up, T, strides_for_shape
|
from tinygrad.helpers import prod, argsort, DEBUG, Timing, CI, unwrap, GlobalCounters, tqdm, round_up, T, strides_for_shape
|
||||||
@@ -237,11 +237,18 @@ def torch_load(t:Tensor) -> dict[str, Tensor]:
|
|||||||
|
|
||||||
if passthrough_reset(zipfile.is_zipfile(fobj)): # NOTE: passthrough_reset required to support python < 3.14
|
if passthrough_reset(zipfile.is_zipfile(fobj)): # NOTE: passthrough_reset required to support python < 3.14
|
||||||
myzip = zipfile.ZipFile(fobj, 'r')
|
myzip = zipfile.ZipFile(fobj, 'r')
|
||||||
base_name = myzip.namelist()[0].split('/', 1)[0]
|
base_name = None
|
||||||
for n in myzip.namelist():
|
header_offsets = {}
|
||||||
if n.startswith(f'{base_name}/data/'):
|
for zi in myzip.filelist:
|
||||||
with myzip.open(n) as myfile:
|
if base_name is None: base_name = zi.filename.split('/', 1)[0]
|
||||||
offsets[n.split("/")[-1]] = myfile._orig_compress_start # type: ignore
|
if zi.filename.startswith(f'{base_name}/data/'): header_offsets[zi.filename.split("/")[-1]] = zi.header_offset
|
||||||
|
# sadly there's no way to get the start of the file in the zip without reading the header
|
||||||
|
# at least here we read them in parallel
|
||||||
|
header_contents = [t[v+26:v+30].bitcast(dtypes.uint16).to('CPU') for v in header_offsets.values()]
|
||||||
|
Tensor.realize(*header_contents)
|
||||||
|
for (n,o),c in zip(header_offsets.items(), header_contents):
|
||||||
|
# header_offset + sizeFileHeader + File name length + Extra field length : https://en.wikipedia.org/wiki/ZIP_(file_format)
|
||||||
|
offsets[n] = o+30+sum(cast(list[int], c.tolist()))
|
||||||
with myzip.open(f'{base_name}/data.pkl') as myfile:
|
with myzip.open(f'{base_name}/data.pkl') as myfile:
|
||||||
return TorchPickle(myfile).load()
|
return TorchPickle(myfile).load()
|
||||||
elif passthrough_reset(tarfile.is_tarfile(fobj)): # NOTE: passthrough_reset required to support python < 3.11
|
elif passthrough_reset(tarfile.is_tarfile(fobj)): # NOTE: passthrough_reset required to support python < 3.11
|
||||||
|
|||||||
+3
-2
@@ -256,7 +256,7 @@ class Tensor(MathTrait):
|
|||||||
# create the schedule
|
# create the schedule
|
||||||
schedule, var_vals = create_schedule_with_vars(sink)
|
schedule, var_vals = create_schedule_with_vars(sink)
|
||||||
schedule = memory_planner(schedule)
|
schedule = memory_planner(schedule)
|
||||||
if DEBUG >= 1 and len(schedule) > 1: print(f"scheduled {len(schedule)} kernels in {(time.perf_counter()-st)*1000:.2f} ms")
|
if (DEBUG >= 1 and len(schedule) > 1) or DEBUG >= 3: print(f"scheduled {len(schedule)} kernels in {(time.perf_counter()-st)*1000:.2f} ms")
|
||||||
return schedule, var_vals
|
return schedule, var_vals
|
||||||
|
|
||||||
def schedule(self, *lst:Tensor) -> list[ScheduleItem]:
|
def schedule(self, *lst:Tensor) -> list[ScheduleItem]:
|
||||||
@@ -267,7 +267,8 @@ class Tensor(MathTrait):
|
|||||||
|
|
||||||
def realize(self, *lst:Tensor, do_update_stats=True) -> Tensor:
|
def realize(self, *lst:Tensor, do_update_stats=True) -> Tensor:
|
||||||
"""Triggers the computation needed to create these Tensor(s)."""
|
"""Triggers the computation needed to create these Tensor(s)."""
|
||||||
run_schedule(*self.schedule_with_vars(*lst), do_update_stats=do_update_stats)
|
if len(to_realize:=[x for x in (self,)+lst if not x.uop.is_contiguous()]):
|
||||||
|
run_schedule(*Tensor.schedule_with_vars(*to_realize), do_update_stats=do_update_stats)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def replace(self, x:Tensor, allow_shape_mismatch=False) -> Tensor:
|
def replace(self, x:Tensor, allow_shape_mismatch=False) -> Tensor:
|
||||||
|
|||||||
+9
-5
@@ -389,7 +389,15 @@ class UOp(MathTrait, metaclass=UOpMetaClass):
|
|||||||
assert self.dtype.scalar() is dtypes.index, "Can only call get_valid on index dtype"
|
assert self.dtype.scalar() is dtypes.index, "Can only call get_valid on index dtype"
|
||||||
return self.src[0] if self.op is Ops.WHERE and self.src[2].arg is Invalid else UOp.const(dtypes.bool, self.arg is not Invalid)
|
return self.src[0] if self.op is Ops.WHERE and self.src[2].arg is Invalid else UOp.const(dtypes.bool, self.arg is not Invalid)
|
||||||
def reduce(self, *src:UOp, **kwargs): return UOp(Ops.REDUCE, kwargs.pop('dtype', self.dtype), src=(self,)+src, **kwargs)
|
def reduce(self, *src:UOp, **kwargs): return UOp(Ops.REDUCE, kwargs.pop('dtype', self.dtype), src=(self,)+src, **kwargs)
|
||||||
def contiguous(self, *args, **kwargs): return UOp(Ops.CONTIGUOUS, dtype=self.dtype, src=(self,)+args, **kwargs)
|
|
||||||
|
def is_contiguous(self):
|
||||||
|
# TODO: this is is_realized
|
||||||
|
if self.op is Ops.RESHAPE: return self.src[0].is_contiguous()
|
||||||
|
return self.op is Ops.BUFFER
|
||||||
|
|
||||||
|
def contiguous(self, *args, **kwargs):
|
||||||
|
if self.is_contiguous(): return self
|
||||||
|
return UOp(Ops.CONTIGUOUS, dtype=self.dtype, src=(self,)+args, **kwargs)
|
||||||
def contiguous_backward(self): return self.alu(Ops.CONTIGUOUS_BACKWARD)
|
def contiguous_backward(self): return self.alu(Ops.CONTIGUOUS_BACKWARD)
|
||||||
def bufferize(self, *args, **kwargs): return UOp(Ops.BUFFERIZE, dtype=self.dtype, src=(self,)+args, **kwargs)
|
def bufferize(self, *args, **kwargs): return UOp(Ops.BUFFERIZE, dtype=self.dtype, src=(self,)+args, **kwargs)
|
||||||
def fuse(self): return self.alu(Ops.FUSE)
|
def fuse(self): return self.alu(Ops.FUSE)
|
||||||
@@ -497,10 +505,6 @@ class UOp(MathTrait, metaclass=UOpMetaClass):
|
|||||||
if ret.shape == self.shape and same_shape_noop: return self
|
if ret.shape == self.shape and same_shape_noop: return self
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def is_contiguous(self):
|
|
||||||
if self.op is Ops.RESHAPE: return self.src[0].is_contiguous()
|
|
||||||
return self.op is Ops.BUFFER
|
|
||||||
|
|
||||||
# in these four, if the shape doesn't change we can return self
|
# in these four, if the shape doesn't change we can return self
|
||||||
def forced_reshape(self, arg:tuple[sint, ...]): return self._mop(Ops.RESHAPE, arg, same_shape_noop=False)
|
def forced_reshape(self, arg:tuple[sint, ...]): return self._mop(Ops.RESHAPE, arg, same_shape_noop=False)
|
||||||
def reshape(self, arg:tuple[sint, ...]): return self._mop(Ops.RESHAPE, arg, same_shape_noop=True)
|
def reshape(self, arg:tuple[sint, ...]): return self._mop(Ops.RESHAPE, arg, same_shape_noop=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user