sort.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #ifndef __SORT_HPP__
  2. #define __SORT_HPP__
  3. #include <functional>
  4. #include "WaksmanNetwork.hpp"
  5. // We have Nr elements to sort, at the beginning of an array of
  6. // allocated size Na items. Nr and Na are _not_ secret. The strategy
  7. // is to get the smallest (precomputed) WaksmanNetwork (on a random
  8. // permutation) and WNEvalPlan, each of size Nw, where Nr <= Nw <= Na.
  9. // Nw is also not secret. Then mark the Nw-Nr items following the given
  10. // elements as padding, use the WaksmanNetwork and WNEvalPlan to shuffle
  11. // the Nw items, then non-obliviously sort the non-padding items. The
  12. // sort itself is done by making an index array holding just the sort
  13. // keys and original indices into the array, but only of the non-padding
  14. // items. Sort the index array, and call back a std::function with the
  15. // sorted index array and the shuffled array so that it can read out the
  16. // elements in sorted order. This function does not have to be
  17. // oblivious to what elements it is reading, because they've already
  18. // been obliviously shuffled.
  19. // Precompute a WaksmanNetwork of size N for a random permutation. This
  20. // call does not itself use threads, but may be called from a background
  21. // thread. These are consumed as they are used, so you need to keep
  22. // making more. Returns the number of WaksmanNetworks available at that
  23. // size.
  24. size_t sort_precompute(uint32_t N);
  25. // Return a vector of the precomputed sizes we've used since we were
  26. // last asked
  27. std::vector<uint32_t> sort_get_used();
  28. // Precompute a WNEvalPlan for a given size and number of threads.
  29. // These are not consumed as they are used, so you only need to call
  30. // this once for each (size,nthreads) pair you need. The precomputation
  31. // itself only uses a single thread, but also may be called from a
  32. // background thread.
  33. void sort_precompute_evalplan(uint32_t N, threadid_t nthreads);
  34. // Shuffle Nr items at the beginning of an allocated array of Na items
  35. // using up to nthreads threads. The items to shuffle are byte arrays
  36. // of size msg_size. Return Nw, the size of the Waksman network we
  37. // used, which must satisfy Nr <= Nw <= Na.
  38. uint32_t shuffle_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
  39. uint32_t Nr, uint32_t Na);
  40. // Sort Nr items at the beginning of an allocated array of Na items
  41. // using up to nthreads threads. The items to sort are byte arrays of
  42. // size msg_size. The keys are of type T. T must have set_key<T> and
  43. // compare_keys<T> defined. The items will be shuffled in-place, and a
  44. // sorted array of keys will be passed to the provided callback
  45. // function.
  46. template<typename T>
  47. void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
  48. uint32_t Nr, uint32_t Na,
  49. // the arguments to the callback are items, the sorted keys, and
  50. // the number of non-padding items
  51. std::function<void(const uint8_t*, const T*, uint32_t Nr)>);
  52. // As above, but also pass an Nr*msg_size-byte buffer outbuf to put
  53. // the sorted values into, instead of passing a callback. This calls
  54. // the above function, then copies the data in sorted order into outbuf.
  55. // Note: the outbuf buffer cannot overlap the items buffer.
  56. template<typename T>
  57. void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
  58. uint32_t Nr, uint32_t Na, uint8_t *outbuf);
  59. // As above, but the first Nr msg_size-byte entries in the items array
  60. // will end up with the sorted values. Note: if Nr < Na, entries beyond
  61. // Nr may also change, but you should not even look at those values!
  62. // This calls the above function with a temporary buffer, then copies
  63. // that buffer back into the items array, so it's less efficient, both
  64. // in memory and CPU, than the above functions.
  65. template<typename T>
  66. void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
  67. uint32_t Nr, uint32_t Na);
  68. template<typename T>
  69. inline void set_key(T* key, const uint8_t *item, uint32_t index);
  70. template<typename T>
  71. int compare_keys(const void* a, const void* b);
  72. // The different kinds of keys we sort on
  73. // The 32-bit userid (which is the 10-bit node id and the 22-bit
  74. // per-node userid)
  75. struct UidKey {
  76. uint64_t uid_index;
  77. inline uint32_t index() const { return (uint32_t) uid_index; }
  78. };
  79. // The above and also the priority (for public routing)
  80. struct UidPriorityKey {
  81. uint64_t uid_priority;
  82. uint32_t idx;
  83. inline uint32_t index() const { return idx; }
  84. };
  85. // Just the nodeid (not the per-node userid) and the priority (for
  86. // public routing)
  87. struct NidPriorityKey {
  88. uint64_t nid_priority;
  89. uint32_t idx;
  90. inline uint32_t index() const { return idx; }
  91. };
  92. #include "sort.tcc"
  93. #endif