You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by zh...@apache.org on 2019/06/13 03:06:58 UTC

[incubator-mxnet] branch master updated: Make MXNDArrayFromDLPack backward compatible (#15227)

This is an automated email from the ASF dual-hosted git repository.

zhasheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git


The following commit(s) were added to refs/heads/master by this push:
     new a862270  Make MXNDArrayFromDLPack backward compatible (#15227)
a862270 is described below

commit a862270beb2d796c1ba311183f7f4a766a18ad6c
Author: Anirudh Subramanian <an...@ufl.edu>
AuthorDate: Wed Jun 12 20:06:13 2019 -0700

    Make MXNDArrayFromDLPack backward compatible (#15227)
    
    * Upgrade archive utility and add back FC improvement
    
    This reverts commit 65434886f6caa7210ed3ff39cd4e950c023d8328.
    
    * Make MXNDArrayFromDLPack C API backward compatible
    
    * Fix to comment
    
    * Add tests for dlpack
    
    * Revert "Upgrade archive utility and add back FC improvement"
    
    This reverts commit 40beeb2a7453f262e2820ff8faa6621abf81a88d.
    
    * Fix C API call
---
 include/mxnet/c_api.h                | 22 +++++++++++++++--
 python/mxnet/ndarray/ndarray.py      |  4 +--
 src/c_api/c_api.cc                   |  7 +++++-
 tests/python/unittest/test_dlpack.py | 48 ++++++++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h
index 1b1c10e..2d5122c 100644
--- a/include/mxnet/c_api.h
+++ b/include/mxnet/c_api.h
@@ -809,7 +809,8 @@ MXNET_DLL int MXNDArrayToDLPack(NDArrayHandle handle,
                                        DLManagedTensorHandle *out_dlpack);
 
 /*!
-* \brief Create a NDArray backed by a dlpack tensor.
+* \brief DEPRECATED. Use MXNDArrayFromDLPackEx instead.
+
 *
 * This allows us to create a NDArray using the memory
 * allocated by an external deep learning framework
@@ -823,10 +824,27 @@ MXNET_DLL int MXNDArrayToDLPack(NDArrayHandle handle,
 * \return 0 when success, -1 when failure happens
 */
 MXNET_DLL int MXNDArrayFromDLPack(DLManagedTensorHandle dlpack,
-                                  const bool transient_handle,
                                   NDArrayHandle *out_handle);
 
 /*!
+* \brief Create a NDArray backed by a dlpack tensor.
+*
+* This allows us to create a NDArray using the memory
+* allocated by an external deep learning framework
+* that is DLPack compatible.
+*
+* The memory is retained until the NDArray went out of scope.
+*
+* \param dlpack the pointer of the input DLManagedTensor
+* \param transient_handle whether the handle will be destructed before calling the deleter
+* \param out_handle pointer holder to get pointer of NDArray
+* \return 0 when success, -1 when failure happens
+*/
+MXNET_DLL int MXNDArrayFromDLPackEx(DLManagedTensorHandle dlpack,
+                                    const bool transient_handle,
+                                    NDArrayHandle *out_handle);
+
+/*!
  * \brief Delete a dlpack tensor
  * \param dlpack the pointer of the input DLManagedTensor
  * \return 0 when success, -1 when failure happens
diff --git a/python/mxnet/ndarray/ndarray.py b/python/mxnet/ndarray/ndarray.py
index 4b717e2..7e21dae 100644
--- a/python/mxnet/ndarray/ndarray.py
+++ b/python/mxnet/ndarray/ndarray.py
@@ -4156,7 +4156,7 @@ def from_dlpack(dlpack):
     assert ctypes.pythonapi.PyCapsule_IsValid(dlpack, _c_str_dltensor), ValueError(
         'Invalid DLPack Tensor. DLTensor capsules can be consumed only once.')
     dlpack_handle = ctypes.c_void_p(ctypes.pythonapi.PyCapsule_GetPointer(dlpack, _c_str_dltensor))
-    check_call(_LIB.MXNDArrayFromDLPack(dlpack_handle, False, ctypes.byref(handle)))
+    check_call(_LIB.MXNDArrayFromDLPackEx(dlpack_handle, False, ctypes.byref(handle)))
     # Rename PyCapsule (DLPack)
     ctypes.pythonapi.PyCapsule_SetName(dlpack, _c_str_used_dltensor)
     # delete the deleter of the old dlpack
@@ -4269,5 +4269,5 @@ def from_numpy(ndarray, zero_copy=True):
     ndarray.flags['WRITEABLE'] = False
     c_obj = _make_dl_managed_tensor(ndarray)
     handle = NDArrayHandle()
-    check_call(_LIB.MXNDArrayFromDLPack(ctypes.byref(c_obj), True, ctypes.byref(handle)))
+    check_call(_LIB.MXNDArrayFromDLPackEx(ctypes.byref(c_obj), True, ctypes.byref(handle)))
     return NDArray(handle=handle)
diff --git a/src/c_api/c_api.cc b/src/c_api/c_api.cc
index f5d72d5..a9a49b0 100644
--- a/src/c_api/c_api.cc
+++ b/src/c_api/c_api.cc
@@ -562,8 +562,13 @@ int MXNDArrayToDLPack(NDArrayHandle handle,
 }
 
 int MXNDArrayFromDLPack(DLManagedTensorHandle dlpack,
-                        const bool transient_handle,
                         NDArrayHandle *out_handle) {
+  return MXNDArrayFromDLPackEx(dlpack, false, out_handle);
+}
+
+int MXNDArrayFromDLPackEx(DLManagedTensorHandle dlpack,
+                          const bool transient_handle,
+                          NDArrayHandle *out_handle) {
   API_BEGIN();
   *out_handle = new NDArray(NDArray::FromDLPack(
               static_cast<DLManagedTensor*>(dlpack),
diff --git a/tests/python/unittest/test_dlpack.py b/tests/python/unittest/test_dlpack.py
new file mode 100644
index 0000000..fb64f8d
--- /dev/null
+++ b/tests/python/unittest/test_dlpack.py
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import ctypes
+import mxnet as mx
+from mxnet.base import NDArrayHandle, _LIB, c_str, check_call
+from mxnet.test_utils import assert_almost_equal
+
+def test_from_dlpack_backward_compatibility():
+    def from_dlpack_old(dlpack):
+
+        PyCapsuleDestructor = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
+        _c_str_dltensor = c_str('dltensor')
+        _c_str_used_dltensor = c_str('used_dltensor')
+        handle = NDArrayHandle()
+        dlpack = ctypes.py_object(dlpack)
+        assert ctypes.pythonapi.PyCapsule_IsValid(dlpack, _c_str_dltensor), ValueError(
+            'Invalid DLPack Tensor. DLTensor capsules can be consumed only once.')
+        dlpack_handle = ctypes.c_void_p(ctypes.pythonapi.PyCapsule_GetPointer(dlpack, _c_str_dltensor))
+        check_call(_LIB.MXNDArrayFromDLPack(dlpack_handle, ctypes.byref(handle)))
+        # Rename PyCapsule (DLPack)
+        ctypes.pythonapi.PyCapsule_SetName(dlpack, _c_str_used_dltensor)
+        # delete the deleter of the old dlpack
+        ctypes.pythonapi.PyCapsule_SetDestructor(dlpack, None)
+        return mx.nd.NDArray(handle=handle)
+
+    x = mx.nd.ones((2,3))
+    y = mx.nd.to_dlpack_for_read(x)
+    z = from_dlpack_old(y)
+    assert_almost_equal(x.asnumpy(), z.asnumpy(), rtol=1e-5, atol=1e-5)
+
+if __name__ == '__main__':
+    import nose
+    nose.runmodule()