[arrayfire] 32/408: FEAT: Implementing array::lock() and array::unlock()

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:11:10 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/sid
in repository arrayfire.

commit 152fccf2c9a8e317fd6e6b7e87684668b239101d
Author: Pavan Yalamanchili <pavan at arrayfire.com>
Date:   Wed Jun 24 07:09:29 2015 -0400

    FEAT: Implementing array::lock() and array::unlock()
    
    - Added relevant C APIs
    - Added 64 bit int support for af_get_device_ptr
    - Added relevant tests
---
 include/af/array.h            |  19 +++++--
 include/af/device.h           |  30 +++++++++--
 src/api/c/device.cpp          |  73 +++++++++++++++++++++++++
 src/api/c/index.cpp           |   1 -
 src/api/cpp/array.cpp         |  10 +++-
 src/backend/cpu/Array.hpp     |   2 +-
 src/backend/cpu/memory.cpp    |  42 +++++++++------
 src/backend/cpu/memory.hpp    |   3 +-
 src/backend/cuda/Array.hpp    |   2 +-
 src/backend/cuda/memory.cpp   |  53 ++++++++++++------
 src/backend/cuda/memory.hpp   |   3 +-
 src/backend/opencl/Array.hpp  |   2 +-
 src/backend/opencl/memory.cpp |  46 ++++++++++------
 src/backend/opencl/memory.hpp |   4 +-
 test/memory.cpp               | 123 ++++++++++++++++++++++++++++++++----------
 test/memory_lock.cpp          |  95 ++++++++++++++++++++++++++++++++
 16 files changed, 411 insertions(+), 97 deletions(-)

diff --git a/include/af/array.h b/include/af/array.h
index 318f68d..73b1b5b 100644
--- a/include/af/array.h
+++ b/include/af/array.h
@@ -114,6 +114,7 @@ namespace af
             template<typename T> T scalar() const;
             template<typename T> T* device() const;
             void unlock() const;
+            void lock() const;
 
                   array::array_proxy row(int index);
             const array::array_proxy row(int index) const;
@@ -670,9 +671,6 @@ namespace af
            @}
         */
 
-        void unlock() const;
-
-
         // INDEXING
         // Single arguments
 
@@ -911,6 +909,21 @@ namespace af
         ///
         /// For dense matrix, this is the same as count<int>(arr);
         int nonzeros() const;
+
+
+        ///
+        /// \brief Locks the device buffer in the memory manager.
+        ///
+        /// This method can be called to take control of the device pointer from the memory manager.
+        /// While a buffer is locked, the memory manager does not free the memory.
+        void lock() const;
+
+        ///
+        /// \brief Unlocks the device buffer in the memory manager.
+        ///
+        /// This method can be called after called after calling \ref array::lock()
+        /// Calling this method gives back the control of the device pointer to the memory manager.
+        void unlock() const;
     };
     // end of class array
 
diff --git a/include/af/device.h b/include/af/device.h
index 1020ceb..3297c1a 100644
--- a/include/af/device.h
+++ b/include/af/device.h
@@ -202,11 +202,6 @@ extern "C" {
     AFAPI af_err af_sync(const int device);
 
     /**
-       \ingroup device_func_device
-    */
-    AFAPI af_err af_get_device_ptr(void **ptr, const af_array arr);
-
-    /**
        \ingroup device_func_alloc
     */
     AFAPI af_err af_alloc_device(void **ptr, const dim_t bytes);
@@ -257,6 +252,31 @@ extern "C" {
     */
     AFAPI af_err af_get_mem_step_size(size_t *step_bytes);
 
+    /**
+       Lock the device buffer in the memory manager.
+
+       Locked buffers are not freed by memory manager until \ref af_unlock_device_ptr is called.
+       \ingroup device_func_mem
+    */
+    AFAPI af_err af_lock_device_ptr(const af_array arr);
+
+    /**
+       Lock the device buffer in the memory manager.
+
+       Locked buffers are not freed by memory manager until \ref af_unlock_device_ptr is called.
+       \ingroup device_func_mem
+    */
+    AFAPI af_err af_unlock_device_ptr(const af_array arr);
+
+    /**
+       Get the device pointer and lock the buffer in memory manager.
+
+       Locked buffers are not freed by memory manager until \ref af_unlock_device_ptr is called.
+       \ingroup device_func_mem
+    */
+    AFAPI af_err af_get_device_ptr(void **ptr, const af_array arr);
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/api/c/device.cpp b/src/api/c/device.cpp
index fe8948b..23fcdd0 100644
--- a/src/api/c/device.cpp
+++ b/src/api/c/device.cpp
@@ -119,6 +119,8 @@ af_err af_device_array(af_array *arr, const void *data,
         case c64: res = getHandle(createDeviceDataArray<cdouble>(d, data)); break;
         case s32: res = getHandle(createDeviceDataArray<int    >(d, data)); break;
         case u32: res = getHandle(createDeviceDataArray<uint   >(d, data)); break;
+        case s64: res = getHandle(createDeviceDataArray<intl   >(d, data)); break;
+        case u64: res = getHandle(createDeviceDataArray<uintl  >(d, data)); break;
         case u8 : res = getHandle(createDeviceDataArray<uchar  >(d, data)); break;
         case b8 : res = getHandle(createDeviceDataArray<char   >(d, data)); break;
         default: TYPE_ERROR(4, type);
@@ -147,6 +149,8 @@ af_err af_get_device_ptr(void **data, const af_array arr)
         case c64: *data = getDevicePtr(getArray<cdouble>(arr)); break;
         case s32: *data = getDevicePtr(getArray<int    >(arr)); break;
         case u32: *data = getDevicePtr(getArray<uint   >(arr)); break;
+        case s64: *data = getDevicePtr(getArray<intl   >(arr)); break;
+        case u64: *data = getDevicePtr(getArray<uintl  >(arr)); break;
         case u8 : *data = getDevicePtr(getArray<uchar  >(arr)); break;
         case b8 : *data = getDevicePtr(getArray<char   >(arr)); break;
 
@@ -158,6 +162,75 @@ af_err af_get_device_ptr(void **data, const af_array arr)
     return AF_SUCCESS;
 }
 
+template <typename T>
+inline void lockDevicePtr(const af_array arr)
+{
+    memPop<T>((const T *)getArray<T>(arr).get());
+}
+
+af_err af_lock_device_ptr(const af_array arr)
+{
+    try {
+
+        // Make sure all kernels and memcopies are done before getting device pointer
+        detail::sync(getActiveDeviceId());
+
+        af_dtype type = getInfo(arr).getType();
+
+        switch (type) {
+        case f32: lockDevicePtr<float  >(arr); break;
+        case f64: lockDevicePtr<double >(arr); break;
+        case c32: lockDevicePtr<cfloat >(arr); break;
+        case c64: lockDevicePtr<cdouble>(arr); break;
+        case s32: lockDevicePtr<int    >(arr); break;
+        case u32: lockDevicePtr<uint   >(arr); break;
+        case s64: lockDevicePtr<intl   >(arr); break;
+        case u64: lockDevicePtr<uintl  >(arr); break;
+        case u8 : lockDevicePtr<uchar  >(arr); break;
+        case b8 : lockDevicePtr<char   >(arr); break;
+        default: TYPE_ERROR(4, type);
+        }
+
+    } CATCHALL;
+
+    return AF_SUCCESS;
+}
+
+template <typename T>
+inline void unlockDevicePtr(const af_array arr)
+{
+    memPush<T>((const T *)getArray<T>(arr).get());
+}
+
+af_err af_unlock_device_ptr(const af_array arr)
+{
+    try {
+
+        // Make sure all kernels and memcopies are done before getting device pointer
+        detail::sync(getActiveDeviceId());
+
+        af_dtype type = getInfo(arr).getType();
+
+        switch (type) {
+        case f32: unlockDevicePtr<float  >(arr); break;
+        case f64: unlockDevicePtr<double >(arr); break;
+        case c32: unlockDevicePtr<cfloat >(arr); break;
+        case c64: unlockDevicePtr<cdouble>(arr); break;
+        case s32: unlockDevicePtr<int    >(arr); break;
+        case u32: unlockDevicePtr<uint   >(arr); break;
+        case s64: unlockDevicePtr<intl   >(arr); break;
+        case u64: unlockDevicePtr<uintl  >(arr); break;
+        case u8 : unlockDevicePtr<uchar  >(arr); break;
+        case b8 : unlockDevicePtr<char   >(arr); break;
+        default: TYPE_ERROR(4, type);
+        }
+
+    } CATCHALL;
+
+    return AF_SUCCESS;
+}
+
+
 af_err af_alloc_device(void **ptr, const dim_t bytes)
 {
     try {
diff --git a/src/api/c/index.cpp b/src/api/c/index.cpp
index c8bc259..0e0d449 100644
--- a/src/api/c/index.cpp
+++ b/src/api/c/index.cpp
@@ -90,7 +90,6 @@ af_err af_lookup(af_array *out, const af_array in, const af_array indices, const
     try {
         ARG_ASSERT(3, (dim>=0 && dim<=3));
 
-        ArrayInfo inInfo = getInfo(in);
         ArrayInfo idxInfo= getInfo(indices);
 
         ARG_ASSERT(2, idxInfo.isVector() || idxInfo.isScalar());
diff --git a/src/api/cpp/array.cpp b/src/api/cpp/array.cpp
index cf73dbf..2891e69 100644
--- a/src/api/cpp/array.cpp
+++ b/src/api/cpp/array.cpp
@@ -1013,9 +1013,17 @@ namespace af
 #undef TEMPLATE_MEM_FUNC
 
     //FIXME: This needs to be implemented at a later point
-    void array::unlock() const {}
     void array::array_proxy::unlock() const {}
 
     int array::nonzeros() const { return count<int>(*this); }
 
+    void array::lock() const
+    {
+        AF_THROW(af_lock_device_ptr(get()));
+    }
+
+    void array::unlock() const
+    {
+        AF_THROW(af_unlock_device_ptr(get()));
+    }
 }
diff --git a/src/backend/cpu/Array.hpp b/src/backend/cpu/Array.hpp
index 43304a1..fa0afd9 100644
--- a/src/backend/cpu/Array.hpp
+++ b/src/backend/cpu/Array.hpp
@@ -73,7 +73,7 @@ namespace cpu
     template<typename T>
     void *getDevicePtr(const Array<T>& arr)
     {
-        memUnlink((T *)arr.get());
+        memPop((T *)arr.get());
         return (void *)arr.get();
     }
 
diff --git a/src/backend/cpu/memory.cpp b/src/backend/cpu/memory.cpp
index 12e6f6a..18a14c0 100644
--- a/src/backend/cpu/memory.cpp
+++ b/src/backend/cpu/memory.cpp
@@ -84,8 +84,8 @@ namespace cpu
 
                 if (!(iter->second).is_unlinked) {
                     freeWrapper(iter->first);
+                    total_bytes -= iter->second.bytes;
                 }
-                total_bytes -= iter->second.bytes;
             }
         }
 
@@ -93,7 +93,7 @@ namespace cpu
         mem_iter memory_end  = memory_map.end();
 
         while(memory_curr != memory_end) {
-            if (memory_curr->second.is_free) {
+            if (memory_curr->second.is_free && !memory_curr->second.is_unlinked) {
                 memory_map.erase(memory_curr++);
             } else {
                 ++memory_curr;
@@ -157,9 +157,10 @@ namespace cpu
         mem_iter iter = memory_map.find((void *)ptr);
 
         if (iter != memory_map.end()) {
-            if ((iter->second).is_unlinked) return;
 
             iter->second.is_free = true;
+            if ((iter->second).is_unlinked) return;
+
             used_bytes -= iter->second.bytes;
             used_buffers--;
 
@@ -169,28 +170,34 @@ namespace cpu
     }
 
     template<typename T>
-    void memUnlink(T *ptr)
+    void memPop(const T *ptr)
     {
         std::lock_guard<std::mutex> lock(memory_map_mutex);
 
         mem_iter iter = memory_map.find((void *)ptr);
 
         if (iter != memory_map.end()) {
-
             iter->second.is_unlinked = true;
-            iter->second.is_free = true;
-            used_bytes -= iter->second.bytes;
-            used_buffers--;
-
         } else {
             mem_info info = { false,
-                              false,
+                              true,
                               100 }; //This number is not relevant
 
-            memory_map[ptr] = info;
+            memory_map[(void *)ptr] = info;
         }
     }
 
+    template<typename T>
+    void memPush(const T *ptr)
+    {
+        std::lock_guard<std::mutex> lock(memory_map_mutex);
+        mem_iter iter = memory_map.find((void *)ptr);
+        if (iter != memory_map.end()) {
+            iter->second.is_unlinked = false;
+        }
+    }
+
+
     void deviceMemoryInfo(size_t *alloc_bytes, size_t *alloc_buffers,
                           size_t *lock_bytes,  size_t *lock_buffers)
     {
@@ -212,12 +219,13 @@ namespace cpu
         memFree<T>(ptr);
     }
 
-#define INSTANTIATE(T)                              \
-    template T* memAlloc(const size_t &elements);   \
-    template void memFree(T* ptr);                  \
-    template void memUnlink(T* ptr);                \
-    template T* pinnedAlloc(const size_t &elements);\
-    template void pinnedFree(T* ptr);               \
+#define INSTANTIATE(T)                                  \
+    template T* memAlloc(const size_t &elements);       \
+    template void memFree(T* ptr);                      \
+    template void memPop(const T* ptr);                 \
+    template void memPush(const T* ptr);                \
+    template T* pinnedAlloc(const size_t &elements);    \
+    template void pinnedFree(T* ptr);                   \
 
     INSTANTIATE(float)
     INSTANTIATE(cfloat)
diff --git a/src/backend/cpu/memory.hpp b/src/backend/cpu/memory.hpp
index 242e486..0b1c960 100644
--- a/src/backend/cpu/memory.hpp
+++ b/src/backend/cpu/memory.hpp
@@ -13,7 +13,8 @@ namespace cpu
 {
     template<typename T> T* memAlloc(const size_t &elements);
     template<typename T> void memFree(T* ptr);
-    template<typename T> void memUnlink(T *ptr);
+    template<typename T> void memPop(const T *ptr);
+    template<typename T> void memPush(const T *ptr);
 
     template<typename T> T* pinnedAlloc(const size_t &elements);
     template<typename T> void pinnedFree(T* ptr);
diff --git a/src/backend/cuda/Array.hpp b/src/backend/cuda/Array.hpp
index b5d5ea3..eaafd31 100644
--- a/src/backend/cuda/Array.hpp
+++ b/src/backend/cuda/Array.hpp
@@ -88,7 +88,7 @@ namespace cuda
     template<typename T>
     void *getDevicePtr(const Array<T>& arr)
     {
-        memUnlink((T *)arr.get());
+        memPop((T *)arr.get());
         return (void *)arr.get();
     }
 
diff --git a/src/backend/cuda/memory.cpp b/src/backend/cuda/memory.cpp
index cd9766e..9e0da35 100644
--- a/src/backend/cuda/memory.cpp
+++ b/src/backend/cuda/memory.cpp
@@ -64,6 +64,18 @@ namespace cuda
     }
 
     template<typename T>
+    void memPop(const T *ptr)
+    {
+        return;
+    }
+
+    template<typename T>
+    void memPush(const T *ptr)
+    {
+        return;
+    }
+
+    template<typename T>
     T* pinnedAlloc(const size_t &elements)
     {
         T* ptr = NULL;
@@ -144,8 +156,8 @@ namespace cuda
 
                 if (!(iter->second).is_unlinked) {
                     cudaFreeWrapper(iter->first);
+                    total_bytes[n] -= iter->second.bytes;
                 }
-                total_bytes[n] -= iter->second.bytes;
             }
         }
 
@@ -153,7 +165,7 @@ namespace cuda
         mem_iter memory_end  = memory_maps[n].end();
 
         while(memory_curr != memory_end) {
-            if (memory_curr->second.is_free) {
+            if (memory_curr->second.is_free  && !memory_curr->second.is_unlinked) {
                 memory_maps[n].erase(memory_curr++);
             } else {
                 ++memory_curr;
@@ -216,9 +228,9 @@ namespace cuda
 
         if (iter != memory_maps[n].end()) {
 
+            iter->second.is_free = true;
             if ((iter->second).is_unlinked) return;
 
-            iter->second.is_free = true;
             used_bytes[n] -= iter->second.bytes;
             used_buffers[n]--;
 
@@ -228,24 +240,30 @@ namespace cuda
     }
 
     template<typename T>
-    void memUnlink(T *ptr)
+    void memPop(const T *ptr)
     {
         int n = getActiveDeviceId();
         mem_iter iter = memory_maps[n].find((void *)ptr);
 
         if (iter != memory_maps[n].end()) {
-
-            iter->second.is_free = true;
             iter->second.is_unlinked = true;
-            used_bytes[n] -= iter->second.bytes;
-            used_buffers[n]--;
-
         } else {
+
             mem_info info = { false,
-                              false,
+                              true,
                               100 }; //This number is not relevant
 
-            memory_maps[n][ptr] = info;
+            memory_maps[n][(void *)ptr] = info;
+        }
+    }
+
+    template<typename T>
+    void memPush(const T *ptr)
+    {
+        int n = getActiveDeviceId();
+        mem_iter iter = memory_maps[n].find((void *)ptr);
+        if (iter != memory_maps[n].end()) {
+            iter->second.is_unlinked = false;
         }
     }
 
@@ -339,12 +357,13 @@ namespace cuda
 
 #endif
 
-#define INSTANTIATE(T)                              \
-    template T* memAlloc(const size_t &elements);   \
-    template void memFree(T* ptr);                  \
-    template void memUnlink(T* ptr);                \
-    template T* pinnedAlloc(const size_t &elements);\
-    template void pinnedFree(T* ptr);               \
+#define INSTANTIATE(T)                                  \
+    template T* memAlloc(const size_t &elements);       \
+    template void memFree(T* ptr);                      \
+    template void memPop(const T* ptr);                 \
+    template void memPush(const T* ptr);                \
+    template T* pinnedAlloc(const size_t &elements);    \
+    template void pinnedFree(T* ptr);                   \
 
     INSTANTIATE(float)
     INSTANTIATE(cfloat)
diff --git a/src/backend/cuda/memory.hpp b/src/backend/cuda/memory.hpp
index 12fe452..2e5fef2 100644
--- a/src/backend/cuda/memory.hpp
+++ b/src/backend/cuda/memory.hpp
@@ -13,7 +13,8 @@ namespace cuda
 {
     template<typename T> T* memAlloc(const size_t &elements);
     template<typename T> void memFree(T* ptr);
-    template<typename T> void memUnlink(T *ptr);
+    template<typename T> void memPop(const T *ptr);
+    template<typename T> void memPush(const T *ptr);
 
     template<typename T> T* pinnedAlloc(const size_t &elements);
     template<typename T> void pinnedFree(T* ptr);
diff --git a/src/backend/opencl/Array.hpp b/src/backend/opencl/Array.hpp
index 77c3dcc..658962f 100644
--- a/src/backend/opencl/Array.hpp
+++ b/src/backend/opencl/Array.hpp
@@ -78,7 +78,7 @@ namespace opencl
     template<typename T>
     void *getDevicePtr(const Array<T>& arr)
     {
-        memUnlink((T *)arr.get());
+        memPop((T *)arr.get());
         return (void *)((*arr.get())());
     }
 
diff --git a/src/backend/opencl/memory.cpp b/src/backend/opencl/memory.cpp
index 9d14c91..a545a3f 100644
--- a/src/backend/opencl/memory.cpp
+++ b/src/backend/opencl/memory.cpp
@@ -85,8 +85,8 @@ namespace opencl
 
                 if (!(iter->second).is_unlinked) {
                     destroy(iter->first);
+                    total_bytes[n] -= iter->second.bytes;
                 }
-                total_bytes[n] -= iter->second.bytes;
             }
         }
 
@@ -94,7 +94,7 @@ namespace opencl
         mem_iter memory_end  = memory_maps[n].end();
 
         while(memory_curr != memory_end) {
-            if (memory_curr->second.is_free) {
+            if (memory_curr->second.is_free  && !memory_curr->second.is_unlinked) {
                 memory_curr = memory_maps[n].erase(memory_curr);
             } else {
                 ++memory_curr;
@@ -155,9 +155,9 @@ namespace opencl
 
         if (iter != memory_maps[n].end()) {
 
+            iter->second.is_free = true;
             if ((iter->second).is_unlinked) return;
 
-            iter->second.is_free = true;
             used_bytes[n] -= iter->second.bytes;
             used_buffers[n]--;
         } else {
@@ -165,18 +165,13 @@ namespace opencl
         }
     }
 
-    void bufferUnlink(cl::Buffer *ptr)
+    void bufferPop(cl::Buffer *ptr)
     {
         int n = getActiveDeviceId();
         mem_iter iter = memory_maps[n].find(ptr);
 
         if (iter != memory_maps[n].end()) {
-
             iter->second.is_unlinked = true;
-            iter->second.is_free = true;
-            used_bytes[n] -= iter->second.bytes;
-            used_buffers[n]--;
-
         } else {
 
             mem_info info = { false,
@@ -187,6 +182,16 @@ namespace opencl
         }
     }
 
+    void bufferPush(cl::Buffer *ptr)
+    {
+        int n = getActiveDeviceId();
+        mem_iter iter = memory_maps[n].find(ptr);
+
+        if (iter != memory_maps[n].end()) {
+            iter->second.is_unlinked = false;
+        }
+    }
+
     void deviceMemoryInfo(size_t *alloc_bytes, size_t *alloc_buffers,
                           size_t *lock_bytes,  size_t *lock_buffers)
     {
@@ -211,9 +216,15 @@ namespace opencl
     }
 
     template<typename T>
-    void memUnlink(T *ptr)
+    void memPop(const T *ptr)
+    {
+        return bufferPop((cl::Buffer *)ptr);
+    }
+
+    template<typename T>
+    void memPush(const T *ptr)
     {
-        return bufferUnlink((cl::Buffer *)ptr);
+        return bufferPush((cl::Buffer *)ptr);
     }
 
     // pinned memory manager
@@ -330,12 +341,13 @@ namespace opencl
         return pinnedBufferFree((void *) ptr);
     }
 
-#define INSTANTIATE(T)                              \
-    template T* memAlloc(const size_t &elements);   \
-    template void memFree(T* ptr);                  \
-    template void memUnlink(T* ptr);                \
-    template T* pinnedAlloc(const size_t &elements);\
-    template void pinnedFree(T* ptr);               \
+#define INSTANTIATE(T)                                  \
+    template T* memAlloc(const size_t &elements);       \
+    template void memFree(T* ptr);                      \
+    template void memPop(const T* ptr);                 \
+    template void memPush(const T* ptr);                \
+    template T* pinnedAlloc(const size_t &elements);    \
+    template void pinnedFree(T* ptr);                   \
 
     INSTANTIATE(float)
     INSTANTIATE(cfloat)
diff --git a/src/backend/opencl/memory.hpp b/src/backend/opencl/memory.hpp
index f9cf183..c315a9a 100644
--- a/src/backend/opencl/memory.hpp
+++ b/src/backend/opencl/memory.hpp
@@ -16,11 +16,11 @@ namespace opencl
 
     cl::Buffer *bufferAlloc(const size_t &bytes);
     void bufferFree(cl::Buffer *buf);
-    void bufferUnlink(cl::Buffer *ptr);
 
     template<typename T> T *memAlloc(const size_t &elements);
     template<typename T> void memFree(T *ptr);
-    template<typename T> void memUnlink(T *ptr);
+    template<typename T> void memPop(const T *ptr);
+    template<typename T> void memPush(const T *ptr);
 
     template<typename T> T* pinnedAlloc(const size_t &elements);
     template<typename T> void pinnedFree(T* ptr);
diff --git a/test/memory.cpp b/test/memory.cpp
index 144039c..603fd58 100644
--- a/test/memory.cpp
+++ b/test/memory.cpp
@@ -23,7 +23,7 @@ using std::endl;
 
 const size_t step_bytes = 1024;
 
-void cleanSlate()
+static void cleanSlate()
 {
     size_t alloc_bytes, alloc_buffers;
     size_t lock_bytes, lock_buffers;
@@ -43,34 +43,6 @@ void cleanSlate()
     ASSERT_EQ(af::getMemStepSize(), step_bytes);
 }
 
-TEST(Memory, GetDevicePtr)
-{
-    size_t alloc_bytes, alloc_buffers;
-    size_t lock_bytes, lock_buffers;
-
-    cleanSlate(); // Clean up everything done so far
-
-    af::array a = af::randu(5, 5);
-
-    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
-                      &lock_bytes, &lock_buffers);
-
-    ASSERT_EQ(alloc_buffers, 1u);
-    ASSERT_EQ(lock_buffers, 1u);
-    ASSERT_EQ(alloc_bytes, 1 * step_bytes);
-    ASSERT_EQ(lock_bytes, 1 * step_bytes);
-
-    a.device<float>();
-
-    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
-                      &lock_bytes, &lock_buffers);
-
-    ASSERT_EQ(alloc_buffers, 1u);
-    ASSERT_EQ(lock_buffers, 0u); // 0 because device should unlock the buffer
-    ASSERT_EQ(alloc_bytes, 1 * step_bytes);
-    ASSERT_EQ(lock_bytes, 0u);
-}
-
 TEST(Memory, Scope)
 {
     size_t alloc_bytes, alloc_buffers;
@@ -317,3 +289,96 @@ TEST(Memory, Assign)
     ASSERT_EQ(lock_bytes, 1 * step_bytes);
 
 }
+
+
+TEST(Memory, device)
+{
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    cleanSlate(); // Clean up everything done so far
+
+    {
+        af::array a = af::randu(5, 5);
+
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 1u);
+        ASSERT_EQ(lock_buffers, 1u);
+        ASSERT_EQ(alloc_bytes, 1 * step_bytes);
+        ASSERT_EQ(lock_bytes, 1 * step_bytes);
+
+        a.device<float>();
+
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 1u);
+        ASSERT_EQ(lock_buffers, 1u);
+        ASSERT_EQ(alloc_bytes, 1 * step_bytes);
+        ASSERT_EQ(lock_bytes, 1 * lock_bytes);
+
+        a.unlock(); //to reset the lock flag
+    }
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 1u);
+    ASSERT_EQ(lock_buffers, 0u);
+    ASSERT_EQ(alloc_bytes, 1 * step_bytes);
+    ASSERT_EQ(lock_bytes, 0u);
+}
+
+TEST(Memory, unlock)
+{
+
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    cleanSlate(); // Clean up everything done so far
+
+    const dim_t num = step_bytes / sizeof(float);
+
+    std::vector<float> in(num);
+
+    af_array arr = 0;
+    ASSERT_EQ(AF_SUCCESS, af_create_array(&arr, &in[0], 1, &num, f32));
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 1u);
+    ASSERT_EQ(lock_buffers, 1u);
+    ASSERT_EQ(alloc_bytes, step_bytes);
+    ASSERT_EQ(lock_bytes, step_bytes);
+
+    // arr1 gets released by end of the following code block
+    {
+        af::array a(arr);
+        a.lock();
+
+        // No new memory should be allocated
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 1u);
+        ASSERT_EQ(lock_buffers, 1u);
+        ASSERT_EQ(alloc_bytes, step_bytes);
+        ASSERT_EQ(lock_bytes, step_bytes);
+
+        a.unlock();
+    }
+
+    // Making sure all unlocked buffers are freed
+    af::deviceGC();
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 0u);
+    ASSERT_EQ(lock_buffers, 0u);
+    ASSERT_EQ(alloc_bytes, 0u);
+    ASSERT_EQ(lock_bytes, 0u);
+}
diff --git a/test/memory_lock.cpp b/test/memory_lock.cpp
new file mode 100644
index 0000000..6a4fe86
--- /dev/null
+++ b/test/memory_lock.cpp
@@ -0,0 +1,95 @@
+/*******************************************************
+ * Copyright (c) 2014, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <gtest/gtest.h>
+#include <arrayfire.h>
+#include <af/dim4.hpp>
+#include <af/traits.hpp>
+#include <vector>
+#include <iostream>
+#include <string>
+#include <testHelpers.hpp>
+
+using std::vector;
+using std::string;
+using std::cout;
+using std::endl;
+
+const size_t step_bytes = 1024;
+
+static void cleanSlate()
+{
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    af::deviceGC();
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 0u);
+    ASSERT_EQ(lock_buffers, 0u);
+    ASSERT_EQ(alloc_bytes, 0u);
+    ASSERT_EQ(lock_bytes, 0u);
+
+    af::setMemStepSize(step_bytes);
+
+    ASSERT_EQ(af::getMemStepSize(), step_bytes);
+}
+
+// This test should be by itself as it leaks memory intentionally
+TEST(Memory, lock)
+{
+
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    cleanSlate(); // Clean up everything done so far
+
+    const dim_t num = step_bytes / sizeof(float);
+
+    std::vector<float> in(num);
+
+    af_array arr = 0;
+    ASSERT_EQ(AF_SUCCESS, af_create_array(&arr, &in[0], 1, &num, f32));
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 1u);
+    ASSERT_EQ(lock_buffers, 1u);
+    ASSERT_EQ(alloc_bytes, step_bytes);
+    ASSERT_EQ(lock_bytes, step_bytes);
+
+    // arr1 gets released by end of the following code block
+    {
+        af::array a(arr);
+        a.lock();
+
+        // No new memory should be allocated
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 1u);
+        ASSERT_EQ(lock_buffers, 1u);
+        ASSERT_EQ(alloc_bytes, step_bytes);
+        ASSERT_EQ(lock_bytes, step_bytes);
+    }
+
+    // Making sure all unlocked buffers are freed
+    af::deviceGC();
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 1u);
+    ASSERT_EQ(lock_buffers, 1u);
+    ASSERT_EQ(alloc_bytes, step_bytes);
+    ASSERT_EQ(lock_bytes, step_bytes);
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git



More information about the debian-science-commits mailing list