remove core.tensor, raw_tensor,TensorWrapper
avoid create tensor with zero-stride numpy ndarray
GitOrigin-RevId: 4fe5c4c5ba
release-1.2
@@ -9,5 +9,4 @@ | |||||
import os | import os | ||||
import sys | import sys | ||||
from .tensor import Tensor | |||||
from .tensor.megbrain_graph import Graph | from .tensor.megbrain_graph import Graph |
@@ -27,8 +27,6 @@ from ..ops.builtin import ( | |||||
from ..ops.special import Const | from ..ops.special import Const | ||||
from ..tensor.core import apply | from ..tensor.core import apply | ||||
from ..tensor.function import Function | from ..tensor.function import Function | ||||
from ..tensor.tensor import Tensor | |||||
from ..tensor.tensor_wrapper import TensorWrapper | |||||
@functools.singledispatch | @functools.singledispatch | ||||
@@ -21,7 +21,6 @@ from ..ops.builtin import Elemwise, OpDef, RemoteSend | |||||
from ..ops.special import Const | from ..ops.special import Const | ||||
from ..tensor.core import TensorBase, TensorWrapperBase, apply | from ..tensor.core import TensorBase, TensorWrapperBase, apply | ||||
from ..tensor.function import Function | from ..tensor.function import Function | ||||
from ..tensor.tensor import Tensor, get_context | |||||
from . import builtin_op_utils | from . import builtin_op_utils | ||||
""" Some notes: | """ Some notes: | ||||
@@ -65,238 +64,6 @@ def get_tensor(x): | |||||
return get_tensor(x) | return get_tensor(x) | ||||
class Grad: | |||||
def __init__(self, name=None): | |||||
if name is None: | |||||
global _grad_count | |||||
self._name = "grad_" + str(_grad_count) | |||||
_grad_count += 1 | |||||
else: | |||||
self._name = name | |||||
assert self._name not in _grad_manager_dict, "grad manager name duplicated" | |||||
_grad_manager_dict[self._name] = self | |||||
# list of all x in partial(y) / partial(x) | |||||
self.xs = [] | |||||
# constains weak reference of all OpNode during forward | |||||
# OpNode contains inputs, outputs and its backward | |||||
# ops forms the computational graph | |||||
self.ops = [] | |||||
# save remote_send output for backward | |||||
self.remote_send_cache = [] | |||||
self._attached_tensors = weakref.WeakSet() | |||||
self._enabled = True | |||||
@property | |||||
def name(self): | |||||
return self._name | |||||
def wrt(self, *args: Tensor, callback=None): | |||||
""" Indicates the loss is a function of the input tensors (usually the net trainable parameters), | |||||
i.e., d (loss) / d (Tensor) != 0 | |||||
callback is used to perform additional operations after gradient is obtained in backward. | |||||
e.g., copy the grad to a particular place | |||||
A VariableNode will be created and saved in the tensor/s _extra_data slot. | |||||
""" | |||||
for x in map(get_tensor, args): | |||||
v = self._new_variable(x, callback=callback) | |||||
assert self not in x._extra_data | |||||
x._extra_data[self] = Tracer(v) | |||||
self.xs.append(v) | |||||
return self | |||||
def _new_variable(self, owner, opnode=None, callback=None): | |||||
self._attached_tensors.add(owner) | |||||
return VariableNode(self, owner, opnode=opnode, callback=callback) | |||||
def _new_opnode(self, inputs, outputs): | |||||
inputs = tuple(inputs) | |||||
for i in inputs: | |||||
assert i is None or isinstance(i, VariableNode) | |||||
o = OpNode() | |||||
o.inputs = inputs | |||||
o.outputs = [] | |||||
tracers = [] | |||||
for i in outputs: | |||||
assert isinstance(i, Tensor) | |||||
v = self._new_variable(i, o) | |||||
o.outputs.append(weakref.ref(v)) | |||||
tracers.append(Tracer(v)) | |||||
self.ops.append(weakref.ref(o)) | |||||
return o, tracers | |||||
def copy(self): | |||||
raise NotImplementedError | |||||
def __enter__(self): | |||||
return self | |||||
def _exit(self): | |||||
"""clear all resources""" | |||||
self._enabled = False | |||||
for o in self.ops: | |||||
o = o() | |||||
if o: | |||||
o.clear() | |||||
for i in self._attached_tensors: | |||||
i._extra_data.pop(self, None) | |||||
self.remote_send_cache = [] | |||||
def __exit__(self, *_): | |||||
self._exit() | |||||
def __call__(self, ys, dys): | |||||
""" Defines Grad(). | |||||
:param ys: outputs of forward operators, e.g., the loss tensor | |||||
:type ys: list of Tensor or TensorWrapperBase | |||||
:param dys: delta of outputs, physically equivalent to sensitivity of outputs to the loss, | |||||
e.g., one for the loss itself | |||||
:type dys: list of Tensor or TensorWrapperBase | |||||
""" | |||||
assert self._enabled | |||||
self._enabled = False | |||||
def check_wrapper(): | |||||
if isinstance(dys, TensorWrapperBase): | |||||
return type(dys) | |||||
if isinstance(dys, TensorBase): | |||||
return | |||||
assert isinstance(dys, (tuple, list)) | |||||
for i in dys: | |||||
if isinstance(i, TensorWrapperBase): | |||||
return type(i) | |||||
# use Tensor as defualt wrapper | |||||
return mge.Tensor | |||||
Wrapper = check_wrapper() | |||||
def aslist(x): | |||||
if isinstance(x, (Tensor, TensorWrapperBase)): | |||||
x = [x] | |||||
else: | |||||
x = list(x) | |||||
x = [i.__wrapped__ if isinstance(i, TensorWrapperBase) else i for i in x] | |||||
for i in x: | |||||
assert isinstance(i, Tensor) | |||||
return x | |||||
ys = aslist(ys) | |||||
dys = aslist(dys) | |||||
assert len(ys) == len(dys) | |||||
ids = [i for i, y in enumerate(ys) if self in y._extra_data.keys()] | |||||
ys = [y for i, y in enumerate(ys) if i in ids] | |||||
dys = [dy for i, dy in enumerate(dys) if i in ids] | |||||
# ys is changed to a list of VariableNode which contains more information | |||||
# such as OpNode, callback, etc. | |||||
ys = [i._extra_data[self].node for i in ys] | |||||
# NOTE: callback is called only if grad is not None | |||||
# the OpNode sequence in backward | |||||
op_seq = [] | |||||
# VariableNode -> (i, j), where i is time stamp in backward, j means jth input | |||||
last_written_to = {} | |||||
def schedule(): | |||||
reached = set(ys) | |||||
# i is the time stamp in backward | |||||
i = 0 | |||||
for o in self.ops[::-1]: | |||||
o = o() | |||||
if o is None: | |||||
continue | |||||
if not o.has_grad_fn(o, reached): | |||||
continue | |||||
op_seq.append(o) | |||||
for j, v in enumerate(o.inputs): | |||||
reached.add(v) | |||||
last_written_to[v] = i, j | |||||
i += 1 | |||||
schedule() | |||||
# VariableNode -> Tensor | |||||
cache = {} | |||||
def initialize(): | |||||
for y, dy in zip(ys, dys): | |||||
cache[y] = dy | |||||
if y not in last_written_to and y.callback: | |||||
y.callback(y.owner(), dy) | |||||
initialize() | |||||
# NOTE: None is used to mark a node has been consumed | |||||
for seqno, opnode in enumerate(op_seq): | |||||
input_nodes = opnode.inputs | |||||
output_nodes = [i() for i in opnode.outputs] | |||||
backward = opnode.backward | |||||
backward_allow_noinput = opnode.backward_allow_noinput | |||||
opnode.clear() | |||||
output_grads = [] | |||||
for i in output_nodes: | |||||
if i is not None: | |||||
if i in cache: | |||||
assert cache[i] is not None | |||||
output_grads.append(cache[i]) | |||||
else: | |||||
output_grads.append(None) | |||||
# read by backward, mark consumed | |||||
cache[i] = None | |||||
else: | |||||
output_grads.append(None) | |||||
if ( | |||||
any([grad is not None for grad in output_grads]) | |||||
or backward_allow_noinput | |||||
): | |||||
input_grads = backward(*output_grads) | |||||
else: | |||||
input_grads = [None] * len(input_nodes) | |||||
assert len(input_nodes) == len(input_grads) | |||||
for i, (v, g) in enumerate(zip(input_nodes, input_grads)): | |||||
if v is None: | |||||
continue | |||||
if v in cache: | |||||
assert cache[v] | |||||
if g is not None: | |||||
cache[v] = add(cache[v], g) | |||||
elif g is not None: | |||||
cache[v] = g | |||||
if last_written_to[v] == (seqno, i): | |||||
if v.callback: | |||||
v.callback( | |||||
v.owner(), Wrapper(cache[v]) if Wrapper else cache[v] | |||||
) | |||||
if v.opnode is None: | |||||
# won't read by backward, mark consumed | |||||
cache[v] = None | |||||
for v in cache.values(): | |||||
assert v is None | |||||
self._exit() | |||||
def __del__(self): | |||||
self._exit() | |||||
class clearable: | class clearable: | ||||
__cleared = False | __cleared = False | ||||
@@ -10,11 +10,6 @@ import warnings | |||||
from typing import Union | from typing import Union | ||||
from ..._imperative_rt import OpDef, ops | from ..._imperative_rt import OpDef, ops | ||||
from ...tensor.core import OpBase, TensorBase, TensorWrapperBase, apply | |||||
# register OpDef as a "virtual subclass" of OpBase, so any of registered | |||||
# apply(OpBase, ...) rules could work well on OpDef | |||||
OpBase.register(OpDef) | |||||
__all__ = ["OpDef"] | __all__ = ["OpDef"] | ||||
@@ -6,4 +6,3 @@ | |||||
# Unless required by applicable law or agreed to in writing, | # Unless required by applicable law or agreed to in writing, | ||||
# software distributed under the License is distributed on an | # software distributed under the License is distributed on an | ||||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
from .tensor_wrapper import TensorWrapper as Tensor |
@@ -13,17 +13,9 @@ import sys | |||||
import typing | import typing | ||||
from abc import ABC | from abc import ABC | ||||
from .._imperative_rt.core2 import apply as apply2 | |||||
from .multipledispatch import Dispatcher | from .multipledispatch import Dispatcher | ||||
def apply_op(op, *args): | |||||
Wrapper = type(args[0]) | |||||
args = [arg._tensor for arg in args] | |||||
results = apply2(op, *args) | |||||
return tuple(map(Wrapper, results)) | |||||
class OpBase(ABC): | class OpBase(ABC): | ||||
def __call__(self, *args): | def __call__(self, *args): | ||||
return apply(self, *args) | return apply(self, *args) | ||||
@@ -7,9 +7,6 @@ | |||||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
from ..ops.builtin import OpDef | from ..ops.builtin import OpDef | ||||
from .core import TensorBase, TensorWrapperBase, apply | from .core import TensorBase, TensorWrapperBase, apply | ||||
from .raw_tensor import RawTensor | |||||
from .tensor import Tensor, push_context | |||||
from .tensor_wrapper import TensorWrapper | |||||
class Function: | class Function: | ||||
@@ -155,13 +152,3 @@ def _(op: Function, *args: TensorWrapperBase): | |||||
t._extra_data[k] = i | t._extra_data[k] = i | ||||
return tuple(map(Wrapper, outputs)) | return tuple(map(Wrapper, outputs)) | ||||
@apply.register() | |||||
def _(op: Function, *args: Tensor): | |||||
raise NotImplementedError | |||||
@apply.register() | |||||
def _(op: Function, *args: RawTensor): | |||||
raise NotImplementedError |
@@ -1,117 +0,0 @@ | |||||
# -*- coding: utf-8 -*- | |||||
# MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||||
# | |||||
# Copyright (c) 2014-2020 Megvii Inc. All rights reserved. | |||||
# | |||||
# Unless required by applicable law or agreed to in writing, | |||||
# software distributed under the License is distributed on an | |||||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
import contextlib | |||||
import copy | |||||
from .core import Dispatcher, OpBase, TensorBase, apply | |||||
class Tensor(TensorBase): | |||||
def __init__(self, data: TensorBase): | |||||
self._data = data | |||||
# _extra_data is set up in Grad.wrt | |||||
self._extra_data = {} | |||||
self._user_data = {} | |||||
def __getattr__(self, name): | |||||
if name in self._user_data: | |||||
return self._user_data[name] | |||||
raise AttributeError(name) | |||||
def reset(self, other): | |||||
assert isinstance(other, __class__) | |||||
self.__dict__.clear() | |||||
self._data = other.data | |||||
self._extra_data = other._extra_data.copy() | |||||
self._user_data = other._user_data.copy() | |||||
def copy(self): | |||||
other = object.__new__(type(self)) | |||||
other.reset(self) | |||||
return other | |||||
# tensor interface | |||||
@property | |||||
def shape(self): | |||||
return self._data.shape | |||||
@property | |||||
def dtype(self): | |||||
return self._data.dtype | |||||
@property | |||||
def device(self): | |||||
return self._data.device | |||||
def numpy(self): | |||||
return self._data.numpy() | |||||
def _drop(self): | |||||
self._data._drop() | |||||
def _swap_in(self): | |||||
self._data._swap_in() | |||||
def _swap_out(self): | |||||
self._data._swap_out() | |||||
class ApplyContext: | |||||
__slots__ = ("inputs", "outputs", "key") | |||||
def __init__(self): | |||||
self.inputs = None | |||||
self.outputs = None | |||||
self.key = None | |||||
_context = None | |||||
@contextlib.contextmanager | |||||
def push_context(): | |||||
global _context | |||||
backup = _context | |||||
try: | |||||
_context = ApplyContext() | |||||
yield _context | |||||
finally: | |||||
_context = backup | |||||
def get_context(): | |||||
return _context | |||||
@apply.register() | |||||
def tensor_apply(op: OpBase, *args: Tensor): | |||||
data = tuple(i._data for i in args) | |||||
# type(Tensor._data) is RawTensor | |||||
# dispached to apply.add@RawTensor.py if passed Tensor args | |||||
outputs = apply(op, *data) | |||||
ret = tuple(map(Tensor, outputs)) | |||||
with push_context() as ctx: | |||||
ctx.inputs = args | |||||
ctx.outputs = ret | |||||
for k in set().union(*(i._extra_data for i in args)): | |||||
ctx.key = k | |||||
data = tuple( | |||||
i._extra_data.get(k) if isinstance(i, Tensor) else i for i in args | |||||
) | |||||
# data are instances of Tracer | |||||
# dispatched to apply.add@grad.py | |||||
outputs = apply(op, *data) | |||||
if outputs is not None: | |||||
assert len(outputs) == len(ret) | |||||
for t, i in zip(ret, outputs): | |||||
t._extra_data[k] = i | |||||
return ret |
@@ -19,7 +19,6 @@ from ..ops import builtin | |||||
from ..ops.builtin import Elemwise, GetVarShape | from ..ops.builtin import Elemwise, GetVarShape | ||||
from ..ops.special import Const | from ..ops.special import Const | ||||
from . import utils | from . import utils | ||||
from .core import OpBase, TensorBase, TensorWrapperBase | |||||
from .indexing import getitem as _getitem | from .indexing import getitem as _getitem | ||||
from .indexing import setitem as _setitem | from .indexing import setitem as _setitem | ||||
from .utils import isscalar | from .utils import isscalar | ||||
@@ -439,98 +438,3 @@ class ArrayMethodMixin(abc.ABC): | |||||
min = _reduce("MIN") | min = _reduce("MIN") | ||||
max = _reduce("MAX") | max = _reduce("MAX") | ||||
mean = _reduce("MEAN") | mean = _reduce("MEAN") | ||||
class GenericTensorWrapper(ArrayMethodMixin, TensorWrapperBase): | |||||
def __init__(self, data): | |||||
self.__wrapped__ = data | |||||
def _reset(self, other): | |||||
if not isinstance(other, __class__): | |||||
raise TypeError(type(other)) | |||||
self.__wrapped__ = other.__wrapped__ | |||||
return self | |||||
@property | |||||
def dtype(self): | |||||
return self.__wrapped__.dtype | |||||
@property | |||||
def shape(self): | |||||
shape = self.__wrapped__.shape | |||||
if shape == () or not use_symbolic_shape(): | |||||
return shape | |||||
return apply(GetVarShape(), self)[0] | |||||
@property | |||||
def device(self): | |||||
return self.__wrapped__.device | |||||
def numpy(self): | |||||
return self.__wrapped__.numpy() | |||||
def _drop(self): | |||||
self.__wrapped__._drop() | |||||
def _swap_in(self): | |||||
self.__wrapped__._swap_in() | |||||
def _swap_out(self): | |||||
self.__wrapped__._swap_out() | |||||
class TensorWrapper(ArrayMethodMixin, TensorBase): | |||||
def __init__(self, data, dtype=None, device=None, isscalar=False): | |||||
self._isscalar = isscalar | |||||
if isinstance(data, Tensor): | |||||
self._tensor = data | |||||
else: | |||||
if device is None: | |||||
device = CompNode._get_default_device() | |||||
self._tensor = Tensor(data, dtype, device) | |||||
def _reset(self, other): | |||||
if not isinstance(other, __class__): | |||||
raise TypeError(type(other)) | |||||
self._tensor = other._tensor | |||||
return self | |||||
@property | |||||
def dtype(self): | |||||
return self._tensor.dtype | |||||
@property | |||||
def shape(self): | |||||
if self._isscalar: | |||||
return () | |||||
shape = self._tensor.shape | |||||
if shape == () or not use_symbolic_shape(): | |||||
return shape | |||||
return apply(GetVarShape(), self)[0] | |||||
@property | |||||
def device(self): | |||||
return self._tensor.device | |||||
def numpy(self): | |||||
if self._isscalar: | |||||
return self._tensor.numpy().squeeze() | |||||
return self._tensor.numpy() | |||||
def _drop(self): | |||||
self._tensor._drop() | |||||
def _swap_in(self): | |||||
self._tensor._swap_in() | |||||
def _swap_out(self): | |||||
self._tensor._swap_out() | |||||
def __repr__(self): | |||||
piece = "Tensor(" | |||||
with np.printoptions(precision=4, suppress=True): | |||||
piece += "{}".format(str(self.numpy())) | |||||
if self.dtype != np.float32: | |||||
piece += ", dtype={}".format(np.dtype(self.dtype).name) | |||||
piece += ", device={}".format(self.device) + ")" | |||||
return piece |
@@ -18,9 +18,8 @@ from ..core.autodiff.grad import ( | |||||
tracer_apply, | tracer_apply, | ||||
) | ) | ||||
from ..core.ops.builtin import CollectiveComm, Copy, RemoteRecv, RemoteSend | from ..core.ops.builtin import CollectiveComm, Copy, RemoteRecv, RemoteSend | ||||
from ..core.tensor.tensor import Tensor, tensor_apply | |||||
from ..device import get_default_device | from ..device import get_default_device | ||||
from ..tensor import tensor | |||||
from ..tensor import Tensor | |||||
from .group import WORLD, Group, get_backend, get_client, get_mm_server_addr, get_rank | from .group import WORLD, Group, get_backend, get_client, get_mm_server_addr, get_rank | ||||
__all__ = [ | __all__ = [ | ||||
@@ -16,7 +16,6 @@ from ..core._imperative_rt.core2 import apply | |||||
from ..core.ops import builtin | from ..core.ops import builtin | ||||
from ..core.ops.special import Const | from ..core.ops.special import Const | ||||
from ..core.tensor import utils | from ..core.tensor import utils | ||||
from ..core.tensor.core import TensorBase, TensorWrapperBase | |||||
from ..tensor import Tensor | from ..tensor import Tensor | ||||
from .elemwise import clip, exp, log, log1p | from .elemwise import clip, exp, log, log1p | ||||
from .tensor import reshape, squeeze | from .tensor import reshape, squeeze | ||||
@@ -703,7 +702,7 @@ def topk( | |||||
mode = "VALUE_IDX_SORTED" | mode = "VALUE_IDX_SORTED" | ||||
op = builtin.TopK(mode=mode) | op = builtin.TopK(mode=mode) | ||||
if not isinstance(k, (TensorBase, TensorWrapperBase)): | |||||
if not isinstance(k, Tensor): | |||||
(k,) = Const(k, dtype="int32", device=inp.device)(inp) | (k,) = Const(k, dtype="int32", device=inp.device)(inp) | ||||
if len(inp.shape) == 1: | if len(inp.shape) == 1: | ||||
@@ -14,7 +14,7 @@ from typing import Iterable, List, Optional, Sequence, Tuple, Union | |||||
import numpy as np | import numpy as np | ||||
from ..core._imperative_rt import CompNode | from ..core._imperative_rt import CompNode | ||||
from ..core._imperative_rt.core2 import Tensor, apply | |||||
from ..core._imperative_rt.core2 import apply | |||||
from ..core._wrap import device as as_device | from ..core._wrap import device as as_device | ||||
from ..core.ops import builtin | from ..core.ops import builtin | ||||
from ..core.ops.special import Const | from ..core.ops.special import Const | ||||
@@ -19,6 +19,7 @@ import weakref | |||||
import numpy as np | import numpy as np | ||||
from ..core._imperative_rt import GraphProfiler | from ..core._imperative_rt import GraphProfiler | ||||
from ..core._imperative_rt.core2 import Tensor | |||||
from ..core._imperative_rt.ops import ( | from ..core._imperative_rt.ops import ( | ||||
CollectiveComm, | CollectiveComm, | ||||
GaussianRNG, | GaussianRNG, | ||||
@@ -32,7 +33,6 @@ from ..core.ops.special import Const | |||||
from ..core.tensor import megbrain_graph as G | from ..core.tensor import megbrain_graph as G | ||||
from ..core.tensor.core import OpBase, TensorBase, TensorWrapperBase, apply | from ..core.tensor.core import OpBase, TensorBase, TensorWrapperBase, apply | ||||
from ..core.tensor.raw_tensor import OpDef, RawTensor, as_raw_tensor | from ..core.tensor.raw_tensor import OpDef, RawTensor, as_raw_tensor | ||||
from ..core.tensor.tensor import Tensor | |||||
from .sublinear_memory_config import SublinearMemoryConfig | from .sublinear_memory_config import SublinearMemoryConfig | ||||
@@ -10,7 +10,6 @@ from typing import Iterable, Union | |||||
import numpy as np | import numpy as np | ||||
from ..core.tensor.tensor import Tensor | |||||
from ..tensor import Parameter, tensor | from ..tensor import Parameter, tensor | ||||
from .optimizer import Optimizer | from .optimizer import Optimizer | ||||
@@ -10,7 +10,6 @@ from typing import Iterable, Union | |||||
import numpy as np | import numpy as np | ||||
from ..core.tensor.tensor import Tensor | |||||
from ..tensor import Parameter, tensor | from ..tensor import Parameter, tensor | ||||
from .optimizer import Optimizer | from .optimizer import Optimizer | ||||
@@ -8,7 +8,6 @@ | |||||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
from typing import Iterable, Tuple, Union | from typing import Iterable, Tuple, Union | ||||
from ..core.tensor.tensor import Tensor | |||||
from ..tensor import Parameter, tensor | from ..tensor import Parameter, tensor | ||||
from .optimizer import Optimizer | from .optimizer import Optimizer | ||||
@@ -8,7 +8,6 @@ | |||||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
from typing import Iterable, Union | from typing import Iterable, Union | ||||
from ..core.tensor.tensor import Tensor | |||||
from ..tensor import Parameter, tensor | from ..tensor import Parameter, tensor | ||||
from .optimizer import Optimizer | from .optimizer import Optimizer | ||||
@@ -16,8 +16,8 @@ from .core._imperative_rt import CompNode | |||||
from .core._imperative_rt.core2 import Tensor as _Tensor | from .core._imperative_rt.core2 import Tensor as _Tensor | ||||
from .core._imperative_rt.core2 import apply | from .core._imperative_rt.core2 import apply | ||||
from .core._trace_option import use_symbolic_shape | from .core._trace_option import use_symbolic_shape | ||||
from .core._wrap import device as as_device | |||||
from .core.ops.builtin import Copy, GetVarShape | from .core.ops.builtin import Copy, GetVarShape | ||||
from .core.tensor.raw_tensor import as_device | |||||
from .core.tensor.tensor_wrapper import ArrayMethodMixin | from .core.tensor.tensor_wrapper import ArrayMethodMixin | ||||
from .device import _valid_device, get_default_device | from .device import _valid_device, get_default_device | ||||
from .utils.deprecation import deprecated | from .utils.deprecation import deprecated | ||||
@@ -43,6 +43,10 @@ class Tensor(_Tensor, ArrayMethodMixin): | |||||
if isinstance(data, _Tensor): | if isinstance(data, _Tensor): | ||||
obj = _Tensor.__new__(cls, data) | obj = _Tensor.__new__(cls, data) | ||||
else: | else: | ||||
if isinstance(data, np.ndarray): | |||||
if 0 in data.strides: | |||||
data = data.squeeze().reshape(data.shape) | |||||
obj = _Tensor.__new__(cls, data, dtype, cn) | obj = _Tensor.__new__(cls, data, dtype, cn) | ||||
return obj | return obj | ||||
@@ -13,7 +13,7 @@ import numpy | |||||
from ..core import _imperative_rt | from ..core import _imperative_rt | ||||
from ..core._imperative_rt import OperatorNode, VarNode | from ..core._imperative_rt import OperatorNode, VarNode | ||||
from ..core.tensor import megbrain_graph as G | from ..core.tensor import megbrain_graph as G | ||||
from ..core.tensor.raw_tensor import as_raw_tensor | |||||
from ..tensor import Tensor | |||||
__all__ = [ | __all__ = [ | ||||
"get_dep_vars", | "get_dep_vars", | ||||
@@ -309,7 +309,7 @@ def load_and_inference(file, inp_data_list: List[numpy.ndarray]) -> List[numpy.n | |||||
cg = new_out_list[0].graph | cg = new_out_list[0].graph | ||||
func = cg.compile(new_out_list) | func = cg.compile(new_out_list) | ||||
for node, value in zip(inp_node_list, inp_data_list): | for node, value in zip(inp_node_list, inp_data_list): | ||||
node.set_value(as_raw_tensor(value)._dev_tensor()) | |||||
node.set_value(Tensor(value)._dev_tensor()) | |||||
func.execute() | func.execute() | ||||
out_data_list = [o.get_value().numpy() for o in out_node_list] | out_data_list = [o.get_value().numpy() for o in out_node_list] | ||||
return out_data_list | return out_data_list |
@@ -13,7 +13,7 @@ import megengine.functional as F | |||||
from megengine import Parameter, optimizer | from megengine import Parameter, optimizer | ||||
from megengine.jit import trace | from megengine.jit import trace | ||||
from megengine.module import Linear, Module | from megengine.module import Linear, Module | ||||
from megengine.tensor import tensor | |||||
from megengine.tensor import Tensor | |||||
class MLP(Module): | class MLP(Module): | ||||
@@ -54,7 +54,7 @@ def _test_optimizer(opt_str, test_case, check_class, update_lr=False): | |||||
for group in opt.param_groups: | for group in opt.param_groups: | ||||
group["lr"] += 0.01 | group["lr"] += 0.01 | ||||
check_func.lr += 0.01 | check_func.lr += 0.01 | ||||
data = tensor(np.random.random(data_shape).astype(np.float32)) | |||||
data = Tensor(np.random.random(data_shape).astype(np.float32)) | |||||
opt.clear_grad() | opt.clear_grad() | ||||
with gm: | with gm: | ||||
@@ -98,7 +98,7 @@ def _test_optimizer(opt_str, test_case, check_class, update_lr=False): | |||||
ori_params[param] = np.copy(param.numpy()) | ori_params[param] = np.copy(param.numpy()) | ||||
train_func( | train_func( | ||||
tensor(np.random.random(data_shape).astype(np.float32)), opt=opt, gm=gm | |||||
Tensor(np.random.random(data_shape).astype(np.float32)), opt=opt, gm=gm | |||||
) | ) | ||||
step += 1 | step += 1 | ||||
check_func(ori_params, net.parameters(), step) | check_func(ori_params, net.parameters(), step) | ||||
@@ -11,7 +11,7 @@ import pickle | |||||
import numpy as np | import numpy as np | ||||
from megengine.core.tensor.dtype import bfloat16 | from megengine.core.tensor.dtype import bfloat16 | ||||
from megengine.core.tensor.raw_tensor import as_raw_tensor | |||||
from megengine.tensor import Tensor | |||||
def test_define(): | def test_define(): | ||||
@@ -42,14 +42,14 @@ def test_cast(): | |||||
def test_shared_nd(): | def test_shared_nd(): | ||||
data = np.array([-3.4, 1.394683, 2.323497, -7.439948, -5.2397], dtype=bfloat16) | data = np.array([-3.4, 1.394683, 2.323497, -7.439948, -5.2397], dtype=bfloat16) | ||||
snd = as_raw_tensor(data, dtype=bfloat16, device="xpux") | |||||
snd = Tensor(data, dtype=bfloat16, device="xpux") | |||||
assert snd.numpy().dtype == bfloat16 | assert snd.numpy().dtype == bfloat16 | ||||
np.testing.assert_allclose( | np.testing.assert_allclose( | ||||
snd.numpy(), [-3.40625, 1.398438, 2.328125, -7.4375, -5.25], atol=1e-6 | snd.numpy(), [-3.40625, 1.398438, 2.328125, -7.4375, -5.25], atol=1e-6 | ||||
) | ) | ||||
data = np.array([-9.34964, -8.342, 9.4385, 0.18746, 1.48], dtype=bfloat16) | data = np.array([-9.34964, -8.342, 9.4385, 0.18746, 1.48], dtype=bfloat16) | ||||
snd = as_raw_tensor(data, dtype=bfloat16, device="xpux") | |||||
snd = Tensor(data, dtype=bfloat16, device="xpux") | |||||
np.testing.assert_allclose( | np.testing.assert_allclose( | ||||
snd.numpy(), [-9.375, -8.3125, 9.4375, 0.1875, 1.476562], atol=1e-6 | snd.numpy(), [-9.375, -8.3125, 9.4375, 0.1875, 1.476562], atol=1e-6 | ||||
) | ) | ||||
@@ -12,7 +12,7 @@ import numpy as np | |||||
import pytest | import pytest | ||||
from megengine.core.tensor.dtype import intb1, intb2, intb4 | from megengine.core.tensor.dtype import intb1, intb2, intb4 | ||||
from megengine.core.tensor.raw_tensor import as_raw_tensor | |||||
from megengine.tensor import Tensor | |||||
def bit_define_test(bit, low_bit_type): | def bit_define_test(bit, low_bit_type): | ||||
@@ -78,11 +78,11 @@ def _shared_nd_test(bit, low_bit_type): | |||||
min_value = 1 - (1 << bit) | min_value = 1 - (1 << bit) | ||||
data = np.arange(min_value, max_value + 2, 2, dtype=low_bit_type) | data = np.arange(min_value, max_value + 2, 2, dtype=low_bit_type) | ||||
snd = as_raw_tensor(data, dtype=low_bit_type, device="xpux") | |||||
snd = Tensor(data, dtype=low_bit_type, device="xpux") | |||||
np.testing.assert_allclose(snd.numpy(), range(min_value, max_value + 2, 2)) | np.testing.assert_allclose(snd.numpy(), range(min_value, max_value + 2, 2)) | ||||
data = np.arange(min_value, max_value + 2, 4, dtype=low_bit_type) | data = np.arange(min_value, max_value + 2, 4, dtype=low_bit_type) | ||||
snd = as_raw_tensor(data, dtype=low_bit_type, device="xpux") | |||||
snd = Tensor(data, dtype=low_bit_type, device="xpux") | |||||
np.testing.assert_allclose(snd.numpy(), range(min_value, max_value + 2, 4)) | np.testing.assert_allclose(snd.numpy(), range(min_value, max_value + 2, 4)) | ||||
@@ -32,8 +32,8 @@ from megengine.core.tensor.dtype import ( | |||||
quint4, | quint4, | ||||
quint8, | quint8, | ||||
) | ) | ||||
from megengine.core.tensor.raw_tensor import as_raw_tensor | |||||
from megengine.distributed.helper import get_device_count_by_fork | from megengine.distributed.helper import get_device_count_by_fork | ||||
from megengine.tensor import Tensor | |||||
def test_dtype_quint8(): | def test_dtype_quint8(): | ||||
@@ -71,7 +71,7 @@ def _get_compiled_result(inp, dtype, shape, device, calc_func=None): | |||||
temp_rst = calc_func(inp_node.outputs[0]) | temp_rst = calc_func(inp_node.outputs[0]) | ||||
oup_node = G.OutputNode(temp_rst) | oup_node = G.OutputNode(temp_rst) | ||||
func = graph.compile(oup_node.outputs[0]) | func = graph.compile(oup_node.outputs[0]) | ||||
inp_node.set_value(as_raw_tensor(inp, dtype=dtype, device=device)._dev_tensor()) | |||||
inp_node.set_value(Tensor(inp, dtype=dtype, device=device)._dev_tensor()) | |||||
func.execute() | func.execute() | ||||
return oup_node.get_value().numpy() | return oup_node.get_value().numpy() | ||||
@@ -9,15 +9,15 @@ | |||||
import numpy as np | import numpy as np | ||||
import pytest | import pytest | ||||
import megengine.core.tensor.raw_tensor | |||||
from megengine.core.tensor.core import apply | |||||
import megengine | |||||
from megengine.core._imperative_rt.core2 import apply | |||||
from megengine.tensor import Tensor | |||||
def elemwise(*args, mode): | def elemwise(*args, mode): | ||||
from megengine.core._imperative_rt.imperative import apply_op | |||||
from megengine.core.ops.builtin import Elemwise | from megengine.core.ops.builtin import Elemwise | ||||
return apply_op(Elemwise(mode), args) | |||||
return apply(Elemwise(mode), *args) | |||||
def test_basic_interface(): | def test_basic_interface(): | ||||
@@ -44,11 +44,11 @@ def test_simple_arith(): | |||||
from megengine.core.ops.builtin import Elemwise | from megengine.core.ops.builtin import Elemwise | ||||
x = np.random.rand(10).astype("float32") | x = np.random.rand(10).astype("float32") | ||||
xx = megengine.core._imperative_rt.put(x) | |||||
xx = Tensor(x) | |||||
(yy,) = elemwise(xx, xx, mode=Elemwise.Mode.MUL) | (yy,) = elemwise(xx, xx, mode=Elemwise.Mode.MUL) | ||||
np.testing.assert_allclose(x * x, megengine.core._imperative_rt.get_value(yy)) | |||||
megengine.core._imperative_rt.delete(xx) | |||||
megengine.core._imperative_rt.delete(yy) | |||||
np.testing.assert_allclose(x * x, yy.numpy()) | |||||
del xx | |||||
del yy | |||||
def test_tensor_on_device(): | def test_tensor_on_device(): | ||||
@@ -62,10 +62,9 @@ def test_tensor_on_device(): | |||||
def test_raw_tensor(): | def test_raw_tensor(): | ||||
from megengine.core.ops.builtin import Elemwise | from megengine.core.ops.builtin import Elemwise | ||||
from megengine.core.tensor.raw_tensor import as_raw_tensor | |||||
x = np.random.rand(10).astype("float32") | x = np.random.rand(10).astype("float32") | ||||
xx = as_raw_tensor(x) | |||||
xx = Tensor(x) | |||||
(yy,) = apply(Elemwise(Elemwise.Mode.MUL), xx, xx) | (yy,) = apply(Elemwise(Elemwise.Mode.MUL), xx, xx) | ||||
np.testing.assert_allclose(x * x, yy.numpy()) | np.testing.assert_allclose(x * x, yy.numpy()) | ||||
(yy,) = apply(Elemwise(Elemwise.Mode.MUL), xx, xx) | (yy,) = apply(Elemwise(Elemwise.Mode.MUL), xx, xx) | ||||
@@ -12,10 +12,10 @@ import numpy as np | |||||
import pytest | import pytest | ||||
import megengine | import megengine | ||||
import megengine.tensor as Tensor | |||||
from megengine.core._imperative_rt.core2 import apply | from megengine.core._imperative_rt.core2 import apply | ||||
from megengine.core._trace_option import use_symbolic_shape | from megengine.core._trace_option import use_symbolic_shape | ||||
from megengine.core.ops import builtin | from megengine.core.ops import builtin | ||||
from megengine.tensor import Tensor | |||||
def cvt_to_shape_desc(val, inpvar, config=None): | def cvt_to_shape_desc(val, inpvar, config=None): | ||||
@@ -8,8 +8,6 @@ | |||||
# "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
import pytest | import pytest | ||||
from megengine.core import Tensor | |||||
# from megengine.core.interpreter.hints import function | # from megengine.core.interpreter.hints import function | ||||
@@ -11,8 +11,8 @@ from concurrent.futures import Future | |||||
import numpy as np | import numpy as np | ||||
import megengine.functional as F | import megengine.functional as F | ||||
import megengine.tensor as Tensor | |||||
from megengine.core.tensor import megbrain_graph as mgb_graph | from megengine.core.tensor import megbrain_graph as mgb_graph | ||||
from megengine.tensor import Tensor | |||||
def test_io(): | def test_io(): | ||||
@@ -9,12 +9,12 @@ | |||||
import numpy as np | import numpy as np | ||||
import megengine.functional as F | import megengine.functional as F | ||||
from megengine.core.tensor.raw_tensor import as_raw_tensor | |||||
from megengine.tensor import Tensor | |||||
def test_as_raw_tensor(): | def test_as_raw_tensor(): | ||||
x = np.arange(6, dtype="float32").reshape(2, 3) | x = np.arange(6, dtype="float32").reshape(2, 3) | ||||
xx = as_raw_tensor(x, device="xpux") | |||||
xx = Tensor(x, device="xpux") | |||||
yy = F.add(xx, 1).numpy() | yy = F.add(xx, 1).numpy() | ||||
assert xx.dtype == np.float32 | assert xx.dtype == np.float32 | ||||
assert xx.device == "xpux" | assert xx.device == "xpux" | ||||
@@ -23,7 +23,7 @@ def test_as_raw_tensor(): | |||||
def test_as_raw_tensor_from_int64(): | def test_as_raw_tensor_from_int64(): | ||||
x = np.arange(6, dtype="int64").reshape(2, 3) | x = np.arange(6, dtype="int64").reshape(2, 3) | ||||
xx = as_raw_tensor(x, dtype="float32", device="xpux") | |||||
xx = Tensor(x, dtype="float32", device="xpux") | |||||
yy = F.add(xx, 1).numpy() | yy = F.add(xx, 1).numpy() | ||||
assert xx.dtype == np.float32 | assert xx.dtype == np.float32 | ||||
assert xx.device == "xpux" | assert xx.device == "xpux" | ||||