313 lines
6.4 KiB
Python
313 lines
6.4 KiB
Python
"""DGL Runtime NDArray API.
|
|
|
|
dgl.ndarray provides a minimum runtime array structure to be
|
|
used with C++ library.
|
|
"""
|
|
# pylint: disable=invalid-name,unused-import
|
|
from __future__ import absolute_import as _abs
|
|
|
|
import ctypes
|
|
import functools
|
|
import operator
|
|
|
|
import numpy as _np
|
|
|
|
from . import backend as F
|
|
from ._ffi.function import _init_api
|
|
from ._ffi.ndarray import (
|
|
_set_class_ndarray,
|
|
context,
|
|
DGLContext,
|
|
DGLDataType,
|
|
empty,
|
|
empty_shared_mem,
|
|
from_dlpack,
|
|
NDArrayBase,
|
|
numpyasarray,
|
|
)
|
|
from ._ffi.object import ObjectBase, register_object
|
|
|
|
|
|
class NDArray(NDArrayBase):
|
|
"""Lightweight NDArray class for DGL framework."""
|
|
|
|
def __len__(self):
|
|
return functools.reduce(operator.mul, self.shape, 1)
|
|
|
|
def shared_memory(self, name):
|
|
"""Return a copy of the ndarray in shared memory
|
|
|
|
Parameters
|
|
----------
|
|
name : str
|
|
The name of the shared memory
|
|
|
|
Returns
|
|
-------
|
|
NDArray
|
|
"""
|
|
return empty_shared_mem(name, True, self.shape, self.dtype).copyfrom(
|
|
self
|
|
)
|
|
|
|
|
|
def cpu(dev_id=0):
|
|
"""Construct a CPU device
|
|
|
|
Parameters
|
|
----------
|
|
dev_id : int, optional
|
|
The integer device id
|
|
|
|
Returns
|
|
-------
|
|
ctx : DGLContext
|
|
The created context
|
|
"""
|
|
return DGLContext(1, dev_id)
|
|
|
|
|
|
def gpu(dev_id=0):
|
|
"""Construct a CPU device
|
|
|
|
Parameters
|
|
----------
|
|
dev_id : int, optional
|
|
The integer device id
|
|
|
|
Returns
|
|
-------
|
|
ctx : DGLContext
|
|
The created context
|
|
"""
|
|
return DGLContext(2, dev_id)
|
|
|
|
|
|
def array(arr, ctx=cpu(0)):
|
|
"""Create an array from source arr.
|
|
|
|
Parameters
|
|
----------
|
|
arr : numpy.ndarray
|
|
The array to be copied from
|
|
|
|
ctx : DGLContext, optional
|
|
The device context to create the array
|
|
|
|
Returns
|
|
-------
|
|
ret : NDArray
|
|
The created array
|
|
"""
|
|
if not isinstance(arr, (_np.ndarray, NDArray)):
|
|
arr = _np.array(arr)
|
|
return empty(arr.shape, arr.dtype, ctx).copyfrom(arr)
|
|
|
|
|
|
def zerocopy_from_numpy(np_data):
|
|
"""Create an array that shares the given numpy data.
|
|
|
|
Parameters
|
|
----------
|
|
np_data : numpy.ndarray
|
|
The numpy data
|
|
|
|
Returns
|
|
-------
|
|
NDArray
|
|
The array
|
|
"""
|
|
arr, _ = numpyasarray(np_data)
|
|
handle = ctypes.pointer(arr)
|
|
return NDArray(handle, is_view=True)
|
|
|
|
|
|
def cast_to_signed(arr):
|
|
"""Cast this NDArray from unsigned integer to signed one.
|
|
|
|
uint64 -> int64
|
|
uint32 -> int32
|
|
|
|
Useful for backends with poor signed integer support (e.g., TensorFlow).
|
|
|
|
Parameters
|
|
----------
|
|
arr : NDArray
|
|
Input array
|
|
|
|
Returns
|
|
-------
|
|
NDArray
|
|
Cased array
|
|
"""
|
|
return _CAPI_DGLArrayCastToSigned(arr)
|
|
|
|
|
|
def get_shared_mem_array(name, shape, dtype):
|
|
"""Get a tensor from shared memory with specific name
|
|
|
|
Parameters
|
|
----------
|
|
name : str
|
|
The unique name of the shared memory
|
|
shape : tuple of int
|
|
The shape of the returned tensor
|
|
dtype : F.dtype
|
|
The dtype of the returned tensor
|
|
|
|
Returns
|
|
-------
|
|
F.tensor
|
|
The tensor got from shared memory.
|
|
"""
|
|
new_arr = empty_shared_mem(
|
|
name, False, shape, F.reverse_data_type_dict[dtype]
|
|
)
|
|
dlpack = new_arr.to_dlpack()
|
|
return F.zerocopy_from_dlpack(dlpack)
|
|
|
|
|
|
def create_shared_mem_array(name, shape, dtype):
|
|
"""Create a tensor from shared memory with the specific name
|
|
|
|
Parameters
|
|
----------
|
|
name : str
|
|
The unique name of the shared memory
|
|
shape : tuple of int
|
|
The shape of the returned tensor
|
|
dtype : F.dtype
|
|
The dtype of the returned tensor
|
|
|
|
Returns
|
|
-------
|
|
F.tensor
|
|
The created tensor.
|
|
"""
|
|
new_arr = empty_shared_mem(
|
|
name, True, shape, F.reverse_data_type_dict[dtype]
|
|
)
|
|
dlpack = new_arr.to_dlpack()
|
|
return F.zerocopy_from_dlpack(dlpack)
|
|
|
|
|
|
def exist_shared_mem_array(name):
|
|
"""Check the existence of shared-memory array.
|
|
|
|
Parameters
|
|
----------
|
|
name : str
|
|
The name of the shared-memory array.
|
|
|
|
Returns
|
|
-------
|
|
bool
|
|
The existence of the array
|
|
"""
|
|
return _CAPI_DGLExistSharedMemArray(name)
|
|
|
|
|
|
class SparseFormat:
|
|
"""Format code"""
|
|
|
|
ANY = 0
|
|
COO = 1
|
|
CSR = 2
|
|
CSC = 3
|
|
|
|
FORMAT2STR = {
|
|
0: "ANY",
|
|
1: "COO",
|
|
2: "CSR",
|
|
3: "CSC",
|
|
}
|
|
|
|
|
|
@register_object("aten.SparseMatrix")
|
|
class SparseMatrix(ObjectBase):
|
|
"""Sparse matrix object class in C++ backend."""
|
|
|
|
@property
|
|
def format(self):
|
|
"""Sparse format enum
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
"""
|
|
return _CAPI_DGLSparseMatrixGetFormat(self)
|
|
|
|
@property
|
|
def num_rows(self):
|
|
"""Number of rows.
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
"""
|
|
return _CAPI_DGLSparseMatrixGetNumRows(self)
|
|
|
|
@property
|
|
def num_cols(self):
|
|
"""Number of rows.
|
|
|
|
Returns
|
|
-------
|
|
int
|
|
"""
|
|
return _CAPI_DGLSparseMatrixGetNumCols(self)
|
|
|
|
@property
|
|
def indices(self):
|
|
"""Index arrays.
|
|
|
|
Returns
|
|
-------
|
|
list of ndarrays
|
|
"""
|
|
ret = [_CAPI_DGLSparseMatrixGetIndices(self, i) for i in range(3)]
|
|
return [F.zerocopy_from_dgl_ndarray(arr) for arr in ret]
|
|
|
|
@property
|
|
def flags(self):
|
|
"""Flag arrays
|
|
|
|
Returns
|
|
-------
|
|
list of boolean
|
|
"""
|
|
return _CAPI_DGLSparseMatrixGetFlags(self)
|
|
|
|
def __getstate__(self):
|
|
return (
|
|
self.format,
|
|
self.num_rows,
|
|
self.num_cols,
|
|
self.indices,
|
|
self.flags,
|
|
)
|
|
|
|
def __setstate__(self, state):
|
|
fmt, nrows, ncols, indices, flags = state
|
|
indices = [F.zerocopy_to_dgl_ndarray(idx) for idx in indices]
|
|
self.__init_handle_by_constructor__(
|
|
_CAPI_DGLCreateSparseMatrix, fmt, nrows, ncols, indices, flags
|
|
)
|
|
|
|
def __repr__(self):
|
|
return 'SparseMatrix(fmt="{}", shape=({},{}))'.format(
|
|
SparseFormat.FORMAT2STR[self.format], self.num_rows, self.num_cols
|
|
)
|
|
|
|
|
|
_set_class_ndarray(NDArray)
|
|
_init_api("dgl.ndarray")
|
|
_init_api("dgl.ndarray.uvm", __name__)
|
|
|
|
# An array representing null (no value) that can be safely converted to
|
|
# other backend tensors.
|
|
NULL = {
|
|
"int64": array(_np.array([], dtype=_np.int64)),
|
|
"int32": array(_np.array([], dtype=_np.int32)),
|
|
}
|