sort.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. // Precompute a WNEvalPlan for a given size and number of threads.
  26. // These are not consumed as they are used, so you only need to call
  27. // this once for each (size,nthreads) pair you need. The precomputation
  28. // itself only uses a single thread, but also may be called from a
  29. // background thread.
  30. void sort_precompute_evalplan(uint32_t N, threadid_t nthreads);
  31. // Shuffle Nr items at the beginning of an allocated array of Na items
  32. // using up to nthreads threads. The items to shuffle are byte arrays
  33. // of size msg_size. Return Nw, the size of the Waksman network we
  34. // used, which must satisfy Nr <= Nw <= Na.
  35. uint32_t shuffle_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
  36. uint32_t Nr, uint32_t Na);
  37. // Sort Nr items at the beginning of an allocated array of Na items
  38. // using up to nthreads threads. The items to sort are byte arrays of
  39. // size msg_size. The keys are of type T. T must have set_key<T> and
  40. // compare_keys<T> defined. The items will be shuffled in-place, and a
  41. // sorted array of keys will be passed to the provided callback
  42. // function.
  43. template<typename T>
  44. void sort_mtobliv(threadid_t nthreads, uint8_t* items, uint16_t msg_size,
  45. uint32_t Nr, uint32_t Na,
  46. // the arguments to the callback are items, the sorted keys, and
  47. // the number of non-padding items
  48. std::function<void(const uint8_t*, const T*, uint32_t Nr)>);
  49. // As above, but the first Nr msg_size-byte entries in the items array
  50. // will end up with the sorted values. Note: if Nr < Na, entries beyond
  51. // Nr may also change, but you should not even look at those values!
  52. // This calls the above function, and then copies the data in sorted
  53. // order into a temporary buffer, then copies that buffer back into the
  54. // items array, so it's less efficient, both in memory and CPU, than the
  55. // above function.
  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);
  59. template<typename T>
  60. inline void set_key(T* key, const uint8_t *item, uint32_t index);
  61. template<typename T>
  62. int compare_keys(const void* a, const void* b);
  63. // The different kinds of keys we sort on
  64. // The 32-bit userid (which is the 10-bit node id and the 22-bit
  65. // per-node userid)
  66. struct UidKey {
  67. uint64_t uid_index;
  68. inline uint32_t index() const { return (uint32_t) uid_index; }
  69. };
  70. // The above and also the priority (for public routing)
  71. struct UidPriorityKey {
  72. uint64_t uid_priority;
  73. uint32_t idx;
  74. inline uint32_t index() const { return idx; }
  75. };
  76. // Just the nodeid (not the per-node userid) and the priority (for
  77. // public routing)
  78. struct NidPriorityKey {
  79. uint64_t nid_priority;
  80. uint32_t idx;
  81. inline uint32_t index() const { return idx; }
  82. };
  83. #include "sort.tcc"
  84. #endif