Browse Source

An intermediate version of sort_mtobliv where you pass it the output buffer

This can save a large memory copy if you can use a separate buffer
Ian Goldberg 1 year ago
parent
commit
159edb1326
2 changed files with 36 additions and 23 deletions
  1. 11 4
      Enclave/sort.hpp
  2. 25 19
      Enclave/sort.tcc

+ 11 - 4
Enclave/sort.hpp

@@ -54,13 +54,20 @@ void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
     // the number of non-padding items
     std::function<void(const uint8_t*, const T*, uint32_t Nr)>);
 
+// As above, but also pass an Nr*msg_size-byte buffer outbuf to put
+// the sorted values into, instead of passing a callback.  This calls
+// the above function, then copies the data in sorted order into outbuf.
+// Note: the outbuf buffer cannot overlap the items buffer.
+template<typename T>
+void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
+    uint32_t Nr, uint32_t Na, uint8_t *outbuf);
+
 // As above, but the first Nr msg_size-byte entries in the items array
 // will end up with the sorted values.  Note: if Nr < Na, entries beyond
 // Nr may also change, but you should not even look at those values!
-// This calls the above function, and then copies the data in sorted
-// order into a temporary buffer, then copies that buffer back into the
-// items array, so it's less efficient, both in memory and CPU, than the
-// above function.
+// This calls the above function with a temporary buffer, then copies
+// that buffer back into the items array, so it's less efficient, both
+// in memory and CPU, than the above functions.
 template<typename T>
 void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
     uint32_t Nr, uint32_t Na);

+ 25 - 19
Enclave/sort.tcc

@@ -132,27 +132,21 @@ static void *move_sorted(void *voidargs)
     }
 }
 
-// As above, but the first Nr msg_size-byte entries in the items array
-// will end up with the sorted values.  Note: if Nr < Na, entries beyond
-// Nr may also change, but you should not even look at those values!
-// This calls the above function, and then copies the data in sorted
-// order into a temporary buffer, then copies that buffer back into the
-// items array, so it's less efficient, both in memory and CPU, than the
-// above function.
+// As above, but also pass an Nr*msg_size-byte buffer outbuf to put
+// the sorted values into, instead of passing a callback.  This calls
+// the above function, then copies the data in sorted order into outbuf.
+// Note: the outbuf buffer cannot overlap the items buffer.
 template<typename T>
 void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
-    uint32_t Nr, uint32_t Na)
+    uint32_t Nr, uint32_t Na, uint8_t *outbuf)
 {
-    sort_mtobliv<T>(nthreads, items, msg_size, Nr, Na, [nthreads, msg_size]
+    sort_mtobliv<T>(nthreads, items, msg_size, Nr, Na,
+        [nthreads, msg_size, outbuf]
         (const uint8_t* origitems, const T* keys, uint32_t Nr) {
-            // A temporary buffer into which to copy the items in sorted
-            // order
-            uint8_t *tempbuf = new uint8_t[Nr * msg_size];
-
             // Special-case nthreads=1 for efficiency
             if (nthreads <= 1) {
                 move_sorted_args<T> args = {
-                    keys, origitems, tempbuf, 0, Nr, msg_size
+                    keys, origitems, outbuf, 0, Nr, msg_size
                 };
                 move_sorted<T>(&args);
             } else {
@@ -163,7 +157,7 @@ void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
                 for (threadid_t i=0; i<nthreads; ++i) {
                     uint32_t num = inc + (i < extra);
                     args[i] = {
-                        keys, origitems, tempbuf, last, num, msg_size
+                        keys, origitems, outbuf, last, num, msg_size
                     };
                     last += num;
                 }
@@ -182,9 +176,21 @@ void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
                     threadpool_join(g_thread_id+i, NULL);
                 }
             }
-
-            // Copy the temporary buffer back to items
-            memmove(origitems, tempbuf, Nr * msg_size);
-            delete[] tempbuf;
         });
 }
+
+// As above, but the first Nr msg_size-byte entries in the items array
+// will end up with the sorted values.  Note: if Nr < Na, entries beyond
+// Nr may also change, but you should not even look at those values!
+// This calls the above function with a temporary buffer, then copies
+// that buffer back into the items array, so it's less efficient, both
+// in memory and CPU, than the above functions.
+template<typename T>
+void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
+    uint32_t Nr, uint32_t Na)
+{
+    uint8_t *tempbuf = new uint8_t[Nr * msg_size];
+    sort_mtobliv<T>(nthreads, items, msg_size, Nr, Na, tempbuf);
+    memmove(items, tempbuf, Nr * msg_size);
+    delete[] tempbuf;
+}