[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