def _datadesc(obj: Any): from dace import data if isinstance(obj, data.Data): return obj elif symbolic.issymbolic(obj): return data.Scalar(symbolic.symtype(obj)) elif isinstance(obj, dtypes.typeclass): return data.Scalar(obj) return data.Scalar(dtypes.typeclass(type(obj)))
def create_datadescriptor(obj): """ Creates a data descriptor from various types of objects. @see: dace.data.Data """ from dace import dtypes # Avoiding import loops if isinstance(obj, Data): return obj elif hasattr(obj, '__descriptor__'): return obj.__descriptor__() elif hasattr(obj, 'descriptor'): return obj.descriptor elif isinstance(obj, (list, tuple, numpy.ndarray)): if isinstance(obj, (list, tuple)): # Lists and tuples are cast to numpy obj = numpy.array(obj) if obj.dtype.fields is not None: # Struct dtype = dtypes.struct( 'unnamed', **{ k: dtypes.typeclass(v[0].type) for k, v in obj.dtype.fields.items() }) else: dtype = dtypes.typeclass(obj.dtype.type) return Array(dtype=dtype, strides=tuple(s // obj.itemsize for s in obj.strides), shape=obj.shape) # special case for torch tensors. Maybe __array__ could be used here for a more # general solution, but torch doesn't support __array__ for cuda tensors. elif type(obj).__module__ == "torch" and type(obj).__name__ == "Tensor": try: import torch return Array(dtype=dtypes.TORCH_DTYPE_TO_TYPECLASS[obj.dtype], strides=obj.stride(), shape=tuple(obj.shape)) except ImportError: raise ValueError( "Attempted to convert a torch.Tensor, but torch could not be imported" ) elif symbolic.issymbolic(obj): return Scalar(symbolic.symtype(obj)) elif isinstance(obj, dtypes.typeclass): return Scalar(obj) elif obj in {int, float, complex, bool, None}: return Scalar(dtypes.typeclass(obj)) elif callable(obj): # Cannot determine return value/argument types from function object return Scalar(dtypes.callback(None)) return Scalar(dtypes.typeclass(type(obj)))
def _create_datadescriptor(obj): """ Creates a data descriptor from various types of objects. @see: dace.data.Data """ if isinstance(obj, data.Data): return obj try: return obj.descriptor except AttributeError: if isinstance(obj, numpy.ndarray): return data.Array(dtype=types.typeclass(obj.dtype.type), shape=obj.shape) if symbolic.issymbolic(obj): return data.Scalar(symbolic.symtype(obj)) if isinstance(obj, types.typeclass): return data.Scalar(obj) return data.Scalar(types.typeclass(type(obj)))
def create_datadescriptor(obj): """ Creates a data descriptor from various types of objects. @see: dace.data.Data """ from dace import dtypes # Avoiding import loops if isinstance(obj, Data): return obj try: return obj.descriptor except AttributeError: if isinstance(obj, numpy.ndarray): return Array(dtype=dtypes.typeclass(obj.dtype.type), shape=obj.shape) if symbolic.issymbolic(obj): return Scalar(symbolic.symtype(obj)) if isinstance(obj, dtypes.typeclass): return Scalar(obj) return Scalar(dtypes.typeclass(type(obj)))
def create_datadescriptor(obj): """ Creates a data descriptor from various types of objects. @see: dace.data.Data """ from dace import dtypes # Avoiding import loops if isinstance(obj, Data): return obj elif hasattr(obj, '__descriptor__'): return obj.__descriptor__() elif hasattr(obj, 'descriptor'): return obj.descriptor elif isinstance(obj, (list, tuple, numpy.ndarray)): if isinstance(obj, (list, tuple)): # Lists and tuples are cast to numpy obj = numpy.array(obj) if obj.dtype.fields is not None: # Struct dtype = dtypes.struct( 'unnamed', **{ k: dtypes.typeclass(v[0].type) for k, v in obj.dtype.fields.items() }) else: dtype = dtypes.typeclass(obj.dtype.type) return Array(dtype=dtype, strides=tuple(s // obj.itemsize for s in obj.strides), shape=obj.shape) elif symbolic.issymbolic(obj): return Scalar(symbolic.symtype(obj)) elif isinstance(obj, dtypes.typeclass): return Scalar(obj) elif obj in {int, float, complex, bool, None}: return Scalar(dtypes.typeclass(obj)) elif callable(obj): # Cannot determine return value/argument types from function object return Scalar(dtypes.callback(None)) return Scalar(dtypes.typeclass(type(obj)))
def create_datadescriptor(obj, no_custom_desc=False): """ Creates a data descriptor from various types of objects. @see: dace.data.Data """ from dace import dtypes # Avoiding import loops if isinstance(obj, Data): return obj elif not no_custom_desc and hasattr(obj, '__descriptor__'): return obj.__descriptor__() elif not no_custom_desc and hasattr(obj, 'descriptor'): return obj.descriptor elif isinstance(obj, (list, tuple, numpy.ndarray)): if isinstance(obj, (list, tuple)): # Lists and tuples are cast to numpy obj = numpy.array(obj) if obj.dtype.fields is not None: # Struct dtype = dtypes.struct('unnamed', **{k: dtypes.typeclass(v[0].type) for k, v in obj.dtype.fields.items()}) else: dtype = dtypes.typeclass(obj.dtype.type) return Array(dtype=dtype, strides=tuple(s // obj.itemsize for s in obj.strides), shape=obj.shape) # special case for torch tensors. Maybe __array__ could be used here for a more # general solution, but torch doesn't support __array__ for cuda tensors. elif type(obj).__module__ == "torch" and type(obj).__name__ == "Tensor": try: # If torch is importable, define translations between typeclasses and torch types. These are reused by daceml. # conversion happens here in pytorch: # https://github.com/pytorch/pytorch/blob/143ef016ee1b6a39cf69140230d7c371de421186/torch/csrc/utils/tensor_numpy.cpp#L237 import torch TYPECLASS_TO_TORCH_DTYPE = { dtypes.bool_: torch.bool, dtypes.int8: torch.int8, dtypes.int16: torch.int16, dtypes.int32: torch.int32, dtypes.int64: torch.int64, dtypes.uint8: torch.uint8, dtypes.float16: torch.float16, dtypes.float32: torch.float32, dtypes.float64: torch.float64, dtypes.complex64: torch.complex64, dtypes.complex128: torch.complex128, } TORCH_DTYPE_TO_TYPECLASS = {v: k for k, v in TYPECLASS_TO_TORCH_DTYPE.items()} return Array(dtype=TORCH_DTYPE_TO_TYPECLASS[obj.dtype], strides=obj.stride(), shape=tuple(obj.shape)) except ImportError: raise ValueError("Attempted to convert a torch.Tensor, but torch could not be imported") elif dtypes.is_gpu_array(obj): interface = obj.__cuda_array_interface__ dtype = dtypes.typeclass(numpy.dtype(interface['typestr']).type) itemsize = numpy.dtype(interface['typestr']).itemsize if len(interface['shape']) == 0: return Scalar(dtype, storage=dtypes.StorageType.GPU_Global) return Array(dtype=dtype, shape=interface['shape'], strides=(tuple(s // itemsize for s in interface['strides']) if interface['strides'] else None), storage=dtypes.StorageType.GPU_Global) elif symbolic.issymbolic(obj): return Scalar(symbolic.symtype(obj)) elif isinstance(obj, dtypes.typeclass): return Scalar(obj) elif (obj is int or obj is float or obj is complex or obj is bool or obj is None): return Scalar(dtypes.typeclass(obj)) elif isinstance(obj, type) and issubclass(obj, numpy.number): return Scalar(dtypes.typeclass(obj)) elif isinstance(obj, (Number, numpy.number, numpy.bool, numpy.bool_)): return Scalar(dtypes.typeclass(type(obj))) elif obj is type(None): # NoneType is void * return Scalar(dtypes.pointer(dtypes.typeclass(None))) elif callable(obj): # Cannot determine return value/argument types from function object return Scalar(dtypes.callback(None)) elif isinstance(obj, str): return Scalar(dtypes.string()) raise TypeError(f'Could not create a DaCe data descriptor from object {obj}. ' 'If this is a custom object, consider creating a `__descriptor__` ' 'adaptor method to the type hint or object itself.')
def create_datadescriptor(obj): """ Creates a data descriptor from various types of objects. @see: dace.data.Data """ from dace import dtypes # Avoiding import loops if isinstance(obj, Data): return obj elif hasattr(obj, '__descriptor__'): return obj.__descriptor__() elif hasattr(obj, 'descriptor'): return obj.descriptor elif isinstance(obj, (list, tuple, numpy.ndarray)): if isinstance(obj, (list, tuple)): # Lists and tuples are cast to numpy obj = numpy.array(obj) if obj.dtype.fields is not None: # Struct dtype = dtypes.struct( 'unnamed', **{ k: dtypes.typeclass(v[0].type) for k, v in obj.dtype.fields.items() }) else: dtype = dtypes.typeclass(obj.dtype.type) return Array(dtype=dtype, strides=tuple(s // obj.itemsize for s in obj.strides), shape=obj.shape) # special case for torch tensors. Maybe __array__ could be used here for a more # general solution, but torch doesn't support __array__ for cuda tensors. elif type(obj).__module__ == "torch" and type(obj).__name__ == "Tensor": try: import torch return Array(dtype=dtypes.TORCH_DTYPE_TO_TYPECLASS[obj.dtype], strides=obj.stride(), shape=tuple(obj.shape)) except ImportError: raise ValueError( "Attempted to convert a torch.Tensor, but torch could not be imported" ) elif dtypes.is_gpu_array(obj): interface = obj.__cuda_array_interface__ dtype = dtypes.typeclass(numpy.dtype(interface['typestr']).type) itemsize = numpy.dtype(interface['typestr']).itemsize if len(interface['shape']) == 0: return Scalar(dtype, storage=dtypes.StorageType.GPU_Global) return Array(dtype=dtype, shape=interface['shape'], strides=(tuple(s // itemsize for s in interface['strides']) if interface['strides'] else None), storage=dtypes.StorageType.GPU_Global) elif symbolic.issymbolic(obj): return Scalar(symbolic.symtype(obj)) elif isinstance(obj, dtypes.typeclass): return Scalar(obj) elif (obj is int or obj is float or obj is complex or obj is bool or obj is None): return Scalar(dtypes.typeclass(obj)) elif isinstance(obj, type) and issubclass(obj, numpy.number): return Scalar(dtypes.typeclass(obj)) elif isinstance(obj, (Number, numpy.number, numpy.bool, numpy.bool_)): return Scalar(dtypes.typeclass(type(obj))) elif callable(obj): # Cannot determine return value/argument types from function object return Scalar(dtypes.callback(None)) elif isinstance(obj, str): return Scalar(dtypes.string()) raise TypeError( f'Could not create a DaCe data descriptor from object {obj}. ' 'If this is a custom object, consider creating a `__descriptor__` ' 'adaptor method to the type hint or object itself.')