[arrayfire] 62/408: PERF: Do not make copies if the number of references is only 1

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:11:16 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 51b90c78e8b6ae3755755f2b461db185f0e13566
Author: Pavan Yalamanchili <pavan at arrayfire.com>
Date:   Tue Jun 30 11:04:22 2015 -0400

    PERF: Do not make copies if the number of references is only 1
---
 src/api/c/assign.cpp |  29 +++++++++--
 test/memory.cpp      | 138 ++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 155 insertions(+), 12 deletions(-)

diff --git a/src/api/c/assign.cpp b/src/api/c/assign.cpp
index d1ac902..6b7a18e 100644
--- a/src/api/c/assign.cpp
+++ b/src/api/c/assign.cpp
@@ -116,9 +116,19 @@ af_err af_assign_seq(af_array *out,
             ARG_ASSERT(2, (index[i].step>=0));
         }
 
-        af_array res;
-        if (*out != lhs) AF_CHECK(af_copy_array(&res, lhs));
-        else             res = lhs;
+        af_array res = 0;
+
+        if (*out != lhs) {
+            int count = 0;
+            AF_CHECK(af_get_data_ref_count(&count, lhs));
+            if (count > 1) {
+                AF_CHECK(af_copy_array(&res, lhs));
+            } else {
+                AF_CHECK(af_retain_array(&res, lhs));
+            }
+        } else {
+            res = lhs;
+        }
 
         try {
 
@@ -190,8 +200,17 @@ af_err af_assign_gen(af_array *out,
         ARG_ASSERT(1, (lhs!=0));
         ARG_ASSERT(4, (rhs!=0));
 
-        if (*out != lhs) AF_CHECK(af_copy_array(&output, lhs));
-        else             output = lhs;
+        if (*out != lhs) {
+            int count = 0;
+            AF_CHECK(af_get_data_ref_count(&count, lhs));
+            if (count > 1) {
+                AF_CHECK(af_copy_array(&output, lhs));
+            } else {
+                AF_CHECK(af_retain_array(&output, lhs));
+            }
+        } else {
+            output = lhs;
+        }
 
         ArrayInfo lInfo = getInfo(lhs);
         ArrayInfo rInfo = getInfo(rhs);
diff --git a/test/memory.cpp b/test/memory.cpp
index 603fd58..57f8124 100644
--- a/test/memory.cpp
+++ b/test/memory.cpp
@@ -263,18 +263,15 @@ TEST(Memory, Assign)
     ASSERT_EQ(lock_bytes, 1 * step_bytes);
 
     {
-        // Should just a copy
         af::array b = af::randu(num / 2);
         a(af::seq(num / 2)) = b;
 
         af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
                           &lock_bytes, &lock_buffers);
 
-        // FIXME: An extra buffer is used because of copy on write
-        // Fix to not perform a copy when the buffer does not have children
-        ASSERT_EQ(alloc_buffers, 3u);
+        ASSERT_EQ(alloc_buffers, 2u);
         ASSERT_EQ(lock_buffers, 2u);
-        ASSERT_EQ(alloc_bytes, 3 * step_bytes);
+        ASSERT_EQ(alloc_bytes, 2 * step_bytes);
         ASSERT_EQ(lock_bytes, 2 * step_bytes);
     }
 
@@ -283,13 +280,140 @@ TEST(Memory, Assign)
     af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
                       &lock_bytes, &lock_buffers);
 
-    ASSERT_EQ(alloc_buffers, 3u);
+    ASSERT_EQ(alloc_buffers, 2u);
     ASSERT_EQ(lock_buffers, 1u);
-    ASSERT_EQ(alloc_bytes, 3 * step_bytes);
+    ASSERT_EQ(alloc_bytes, 2 * step_bytes);
     ASSERT_EQ(lock_bytes, 1 * step_bytes);
 
 }
 
+TEST(Memory, AssignLoop)
+{
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    cleanSlate(); // Clean up everything done so far
+
+    const int num = step_bytes / sizeof(float);
+    const int cols = 100;
+
+    af::array a = af::randu(num, cols);
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 1u);
+    ASSERT_EQ(lock_buffers, 1u);
+    ASSERT_EQ(alloc_bytes, cols * step_bytes);
+    ASSERT_EQ(lock_bytes, cols * step_bytes);
+
+    for (int i = 0; i < cols; i++) {
+
+        af::array b = af::randu(num);
+        a(af::span, i) = b;
+
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 2u); // 3 because you need another scratch space for b
+        ASSERT_EQ(lock_buffers, 2u);
+        ASSERT_EQ(alloc_bytes, (cols + 1) * step_bytes);
+        ASSERT_EQ(lock_bytes, (cols + 1) * step_bytes);
+    }
+}
+
+TEST(Memory, AssignRef)
+{
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    cleanSlate(); // Clean up everything done so far
+
+    const int num = step_bytes / sizeof(float);
+
+    af::array a = af::randu(num);
+    af::array a_ref = a;
+
+    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);
+
+    {
+        af::array b = af::randu(num / 2);
+        // This should do a full copy of a
+        a(af::seq(num / 2)) = b;
+
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 3u);
+        ASSERT_EQ(lock_buffers, 3u);
+        ASSERT_EQ(alloc_bytes, 3 * step_bytes);
+        ASSERT_EQ(lock_bytes, 3 * step_bytes);
+    }
+
+
+    // b should not have deleted a
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 3u);
+    ASSERT_EQ(lock_buffers, 2u); // a_ref
+    ASSERT_EQ(alloc_bytes, 3 * step_bytes);
+    ASSERT_EQ(lock_bytes, 2 * step_bytes); // a_ref
+
+}
+
+TEST(Memory, AssignRefLoop)
+{
+    size_t alloc_bytes, alloc_buffers;
+    size_t lock_bytes, lock_buffers;
+
+    cleanSlate(); // Clean up everything done so far
+
+    const int num = step_bytes / sizeof(float);
+    const int cols = 100;
+
+    af::array a = af::randu(num, cols);
+    af::array a_ref = a;
+
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 1u);
+    ASSERT_EQ(lock_buffers, 1u);
+    ASSERT_EQ(alloc_bytes, cols * step_bytes);
+    ASSERT_EQ(lock_bytes, cols * step_bytes);
+
+    for (int i = 0; i < cols; i++) {
+
+        af::array b = af::randu(num);
+        a(af::span, i) = b;
+
+        af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                          &lock_bytes, &lock_buffers);
+
+        ASSERT_EQ(alloc_buffers, 3u);
+        ASSERT_EQ(lock_buffers, 3u);
+        ASSERT_EQ(alloc_bytes, (2 * cols + 1) * step_bytes);
+        ASSERT_EQ(lock_bytes, (2 * cols + 1) * step_bytes);
+    }
+
+
+    // b should not have deleted a
+    af::deviceMemInfo(&alloc_bytes, &alloc_buffers,
+                      &lock_bytes, &lock_buffers);
+
+    ASSERT_EQ(alloc_buffers, 3u);
+    ASSERT_EQ(lock_buffers, 2u); // a_ref
+    ASSERT_EQ(alloc_bytes, (2 * cols + 1) * step_bytes);
+    ASSERT_EQ(lock_bytes, 2 * cols * step_bytes); // a_ref
+
+}
 
 TEST(Memory, device)
 {

-- 
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