Repository: cupy/cupy

Issue:
Support DLPack
Recently Facebook Research released [Tensor Comprehension](https://github.com/facebookresearch/TensorComprehensions) which enables to optimize a custom kernel to be as fast as cuDNN operators. This great tool may be able to be integrated with CuPy if CuPy supports DLPack as the GPU array layout. Let's start supporting DLPack in CuPy.

ref: https://github.com/dmlc/dlpack/blob/master/include/dlpack/dlpack.h#L94


Discussion:
Hi @mitmul , I also wrote down some docs on what integration with TC involves https://facebookresearch.github.io/TensorComprehensions/integrating_any_ml_framework.html that you might find helpful. It has some reference implementation links as well.

let us know if I can help with any questions. :) 

Thank you @prigoyal. I started working on this here: #1082 

Resolving patch:
diff --git a/cupy/__init__.py b/cupy/__init__.py
--- a/cupy/__init__.py
+++ b/cupy/__init__.py
@@ -598,6 +598,11 @@ def isscalar(num):
 from cupy.core import ElementwiseKernel  # NOQA
 from cupy.core import ReductionKernel  # NOQA
 
+# -----------------------------------------------------------------------------
+# DLPack
+# -----------------------------------------------------------------------------
+
+from cupy.core import fromDlpack  # NOQA
 
 # The following function is left for backward compatibility.
 # New CuPy specific routines should reside in cupyx package.
diff --git a/cupy/core/__init__.py b/cupy/core/__init__.py
--- a/cupy/core/__init__.py
+++ b/cupy/core/__init__.py
@@ -56,5 +56,6 @@
 from cupy.core.core import tensordot_core  # NOQA
 from cupy.core.core import true_divide  # NOQA
 from cupy.core.core import ufunc  # NOQA
+from cupy.core.dlpack import fromDlpack  # NOQA
 from cupy.core.internal import complete_slice  # NOQA
 from cupy.core.internal import get_size  # NOQA
diff --git a/cupy_setup_build.py b/cupy_setup_build.py
--- a/cupy_setup_build.py
+++ b/cupy_setup_build.py
@@ -30,6 +30,7 @@
         'name': 'cuda',
         'file': [
             'cupy.core.core',
+            'cupy.core.dlpack',
             'cupy.core.flags',
             'cupy.core.internal',
             'cupy.cuda.cublas',


Test patch:
diff --git a/tests/cupy_tests/core_tests/test_dlpack.py b/tests/cupy_tests/core_tests/test_dlpack.py
new file mode 100644
--- /dev/null
+++ b/tests/cupy_tests/core_tests/test_dlpack.py
@@ -0,0 +1,44 @@
+import unittest
+
+import cupy
+from cupy import testing
+
+
+@testing.parameterize(*testing.product({
+    'dtype': [
+        cupy.uint8, cupy.uint16, cupy.uint32, cupy.uint64,
+        cupy.int8, cupy.int16, cupy.int32, cupy.int64,
+        cupy.float16, cupy.float32, cupy.float64],
+}))
+class TestDLPackConversion(unittest.TestCase):
+
+    def setUp(self):
+        if cupy.issubdtype(self.dtype, cupy.unsignedinteger):
+            self.array = cupy.random.randint(
+                0, 10, size=(2, 3)).astype(self.dtype)
+        elif cupy.issubdtype(self.dtype, cupy.integer):
+            self.array = cupy.random.randint(
+                -10, 10, size=(2, 3)).astype(self.dtype)
+        elif cupy.issubdtype(self.dtype, cupy.floating):
+            self.array = cupy.random.rand(
+                2, 3).astype(self.dtype)
+
+    def test_conversion(self):
+        tensor = self.array.toDlpack()
+        array = cupy.fromDlpack(tensor)
+        testing.assert_array_equal(self.array, array)
+        testing.assert_array_equal(self.array.data.ptr, array.data.ptr)
+
+
+class TestDLTensorMemory(unittest.TestCase):
+
+    def test_deleter(self):
+        pool = cupy.get_default_memory_pool()
+        pool.free_all_blocks()
+        array = cupy.empty(10)
+        tensor = array.toDlpack()
+        assert pool.n_free_blocks() == 0
+        del array
+        assert pool.n_free_blocks() == 0
+        del tensor
+        assert pool.n_free_blocks() == 1