This repository has been archived by the owner on Nov 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6.8k
Fix ndarray aux data issue #7098
Merged
piiswrong
merged 7 commits into
apache:sparse
from
reminisce:fix_ndarray_aux_data_issue
Jul 25, 2017
Merged
Changes from 6 commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f35093c
Fix getting sparse ndarray data/aux_data issues
reminisce d398d81
Add tests for func csr and row_sparse
reminisce 02d7bea
Make get/set data/aux_data thread safe
reminisce 0a7ef74
Fix a bug
reminisce af20cd8
Fix typo and comment
reminisce e59e125
More comments
reminisce c087977
Correct comment
reminisce File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,7 @@ | |
from . import ndarray | ||
from .ndarray import _DTYPE_NP_TO_MX, _DTYPE_MX_TO_NP | ||
from .ndarray import _STORAGE_TYPE_STR_TO_ID | ||
from .ndarray import NDArray, _storage_type, _zeros_ndarray | ||
from .ndarray import NDArray, _storage_type, _zeros_ndarray, array | ||
from . import cast_storage | ||
from . import slice as nd_slice | ||
|
||
|
@@ -220,20 +220,19 @@ def _aux_type(self, i): | |
|
||
@property | ||
def data(self): | ||
"""The values array of the SparseNDArray. This is a read-only view of the values array. | ||
They reveal internal implementation details and should be used with care. | ||
"""Get a deep copy of the values array of the SparseNDArray. | ||
|
||
Returns | ||
------- | ||
NDArray | ||
This SparseNDArray's values array. | ||
A deep copy of the SparseNDArray's values array. | ||
""" | ||
return self._data() | ||
|
||
@property | ||
def _num_aux(self): | ||
''' The number of aux data used to help store the sparse ndarray. | ||
''' | ||
"""The number of aux data used to help store the sparse ndarray. | ||
""" | ||
return len(_STORAGE_AUX_TYPES[self.stype]) | ||
|
||
@property | ||
|
@@ -253,7 +252,6 @@ def _aux_types(self): | |
|
||
def asnumpy(self): | ||
"""Return a dense ``numpy.ndarray`` object with value copied from this array | ||
|
||
""" | ||
return self.todense().asnumpy() | ||
|
||
|
@@ -311,21 +309,23 @@ def copyto(self, other): | |
def todense(self): | ||
return todense(self) | ||
|
||
def _aux_data(self, i, writable=False): | ||
""" Get an NDArray referencing the ith aux data array associated with the SparseNDArray. | ||
def _aux_data(self, i): | ||
""" Get a deep copy NDArray of the i-th aux data array associated with the SparseNDArray. | ||
This function blocks. Do not use it in performance critical code. | ||
""" | ||
self.wait_to_read() | ||
hdl = NDArrayHandle() | ||
check_call(_LIB.MXNDArrayGetAuxNDArray(self.handle, i, ctypes.byref(hdl))) | ||
return NDArray(hdl, writable) | ||
return NDArray(hdl) | ||
|
||
def _data(self, writable=False): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's okay to remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed. |
||
""" Get an NDArray referencing the value array associated with the SparseNDArray. | ||
def _data(self): | ||
""" Get a deep copy NDArray of the value array associated with the SparseNDArray. | ||
This function blocks. Do not use it in performance critical code. | ||
""" | ||
self.wait_to_read() | ||
hdl = NDArrayHandle() | ||
check_call(_LIB.MXNDArrayGetDataNDArray(self.handle, ctypes.byref(hdl))) | ||
return NDArray(hdl, writable) | ||
return NDArray(hdl) | ||
|
||
# pylint: disable=abstract-method | ||
class CSRNDArray(SparseNDArray): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. |
||
|
@@ -351,8 +351,8 @@ def __reduce__(self): | |
|
||
@property | ||
def indices(self): | ||
"""The indices array of the SparseNDArray. This is a read-only view of the indices array. | ||
They reveal internal implementation details and should be used with care. | ||
"""The indices array of the SparseNDArray with `csr` storage type. | ||
This generates a deep copy of the column indices of the current `csr` matrix. | ||
|
||
Returns | ||
------- | ||
|
@@ -364,8 +364,7 @@ def indices(self): | |
@property | ||
def indptr(self): | ||
"""The indptr array of the SparseNDArray with `csr` storage type. | ||
This is a read-only view of the indptr array. | ||
They reveal internal implementation details and should be used with care. | ||
This generates a deep copy of the `indptr` of the current `csr` matrix. | ||
|
||
Returns | ||
------- | ||
|
@@ -405,8 +404,8 @@ def __reduce__(self): | |
|
||
@property | ||
def indices(self): | ||
"""The indices array of the SparseNDArray. This is a read-only view of the indices array. | ||
They reveal internal implementation details and should be used with care. | ||
"""The indices array of the SparseNDArray with `row_sparse` storage type. | ||
This generates a deep copy of the row indices of the current row-sparse matrix. | ||
|
||
Returns | ||
------- | ||
|
@@ -490,31 +489,36 @@ def csr(data, indptr, indices, shape, ctx=None, dtype=None, indptr_type=None, in | |
assert(len(shape) == 2) | ||
result = CSRNDArray(_new_alloc_handle(storage_type, shape, ctx, False, dtype, | ||
[indptr_type, indices_type], aux_shapes)) | ||
# assign indptr, indices and data | ||
data_ref = result._data(True) | ||
indptr_ref = result._aux_data(0, True) | ||
indices_ref = result._aux_data(1, True) | ||
data_ref[:] = data | ||
indptr_ref[:] = indptr | ||
indices_ref[:] = indices | ||
# TODO(junwu): Convert data, indptr, and indices to mxnet NDArrays | ||
# if they are not for now. In the future, we should provide a c-api | ||
# to accept np.ndarray types to copy from to result.data and aux_data | ||
if not isinstance(data, NDArray): | ||
data = array(data, ctx, dtype) | ||
if not isinstance(indptr, NDArray): | ||
indptr = array(indptr, ctx, indptr_type) | ||
if not isinstance(indices, NDArray): | ||
indices = array(indices, ctx, indices_type) | ||
check_call(_LIB.MXNDArraySyncCopyFromNDArray(result.handle, data.handle, ctypes.c_int(-1))) | ||
check_call(_LIB.MXNDArraySyncCopyFromNDArray(result.handle, indptr.handle, ctypes.c_int(0))) | ||
check_call(_LIB.MXNDArraySyncCopyFromNDArray(result.handle, indices.handle, ctypes.c_int(1))) | ||
return result | ||
|
||
|
||
def row_sparse(values, indices, shape, ctx=None, dtype=None, indices_type=None): | ||
def row_sparse(data, indices, shape, ctx=None, dtype=None, indices_type=None): | ||
"""Creates a row sparse array with a set of tensor slices at given indices. | ||
|
||
Parameters | ||
---------- | ||
values: array_like | ||
data: array_like | ||
An object exposing the array interface, with shape [D0, D1, .. Dn], where D0 is | ||
the number of rows with non-zeros entries. | ||
indices: array_like | ||
An object exposing the array interface, with shape [D0]. | ||
ctx : Context, optional | ||
Device context (default is the current default context). | ||
dtype : str or numpy.dtype, optional | ||
The data type of the output array. The default dtype is ``values.dtype`` | ||
if `values` is an `NDArray`, `float32` otherwise. | ||
The data type of the output array. The default dtype is ``data.dtype`` | ||
if `data` is an `NDArray`, `float32` otherwise. | ||
indices_type: str or numpy.dtype, optional | ||
The data type of the indices array. The default dtype is ``indices.dtype`` | ||
if `indicies` is an `NDArray`, `int32` otherwise. | ||
|
@@ -540,21 +544,26 @@ def row_sparse(values, indices, shape, ctx=None, dtype=None, indices_type=None): | |
if ctx is None: | ||
ctx = Context.default_ctx | ||
# prepare src array and types | ||
values, dtype = _prepare_src_array(values, dtype, mx_real_t) | ||
data, dtype = _prepare_src_array(data, dtype, mx_real_t) | ||
indices, indices_type = _prepare_src_array(indices, indices_type, | ||
_STORAGE_AUX_TYPES[storage_type][0]) | ||
# verify types | ||
assert('int64' in str(indices_type)), "expected int64 for indices" | ||
# verify shapes | ||
assert(values.ndim == len(shape)) | ||
assert(data.ndim == len(shape)) | ||
assert(indices.ndim == 1) | ||
result = RowSparseNDArray(_new_alloc_handle(storage_type, shape, ctx, False, dtype, | ||
[indices_type], [indices.shape])) | ||
# assign indices and values | ||
values_ref = result._data(True) | ||
indices_ref = result._aux_data(0, True) | ||
values_ref[:] = values | ||
indices_ref[:] = indices | ||
|
||
# TODO(junwu): Convert data, indptr, and indices to mxnet NDArrays | ||
# if they are not for now. In the future, we should provide a c-api | ||
# to accept np.ndarray types to copy from to result.data and aux_data | ||
if not isinstance(data, NDArray): | ||
data = array(data, ctx, dtype) | ||
if not isinstance(indices, NDArray): | ||
indices = array(indices, ctx, indices_type) | ||
check_call(_LIB.MXNDArraySyncCopyFromNDArray(result.handle, data.handle, ctypes.c_int(-1))) | ||
check_call(_LIB.MXNDArraySyncCopyFromNDArray(result.handle, indices.handle, ctypes.c_int(0))) | ||
return result | ||
|
||
|
||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anirudh2290 the _sync_copy_from function you'll implement will have similar logic like this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eric-haibin-lin Thank you for the info!