sort_by_key.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_ALGORITHM_SORT_BY_KEY_HPP
  11. #define BOOST_COMPUTE_ALGORITHM_SORT_BY_KEY_HPP
  12. #include <iterator>
  13. #include <boost/static_assert.hpp>
  14. #include <boost/utility/enable_if.hpp>
  15. #include <boost/compute/system.hpp>
  16. #include <boost/compute/command_queue.hpp>
  17. #include <boost/compute/algorithm/detail/merge_sort_on_cpu.hpp>
  18. #include <boost/compute/algorithm/detail/merge_sort_on_gpu.hpp>
  19. #include <boost/compute/algorithm/detail/insertion_sort.hpp>
  20. #include <boost/compute/algorithm/detail/radix_sort.hpp>
  21. #include <boost/compute/algorithm/reverse.hpp>
  22. #include <boost/compute/detail/iterator_range_size.hpp>
  23. #include <boost/compute/type_traits/is_device_iterator.hpp>
  24. namespace boost {
  25. namespace compute {
  26. namespace detail {
  27. template<class KeyIterator, class ValueIterator>
  28. inline void
  29. dispatch_gpu_sort_by_key(KeyIterator keys_first,
  30. KeyIterator keys_last,
  31. ValueIterator values_first,
  32. less<typename std::iterator_traits<KeyIterator>::value_type> compare,
  33. command_queue &queue,
  34. typename boost::enable_if_c<
  35. is_radix_sortable<
  36. typename std::iterator_traits<KeyIterator>::value_type
  37. >::value
  38. >::type* = 0)
  39. {
  40. size_t count = detail::iterator_range_size(keys_first, keys_last);
  41. if(count < 32){
  42. detail::serial_insertion_sort_by_key(
  43. keys_first, keys_last, values_first, compare, queue
  44. );
  45. }
  46. else {
  47. detail::radix_sort_by_key(
  48. keys_first, keys_last, values_first, queue
  49. );
  50. }
  51. }
  52. template<class KeyIterator, class ValueIterator>
  53. inline void
  54. dispatch_gpu_sort_by_key(KeyIterator keys_first,
  55. KeyIterator keys_last,
  56. ValueIterator values_first,
  57. greater<typename std::iterator_traits<KeyIterator>::value_type> compare,
  58. command_queue &queue,
  59. typename boost::enable_if_c<
  60. is_radix_sortable<
  61. typename std::iterator_traits<KeyIterator>::value_type
  62. >::value
  63. >::type* = 0)
  64. {
  65. size_t count = detail::iterator_range_size(keys_first, keys_last);
  66. if(count < 32){
  67. detail::serial_insertion_sort_by_key(
  68. keys_first, keys_last, values_first, compare, queue
  69. );
  70. }
  71. else {
  72. // radix sorts in descending order
  73. detail::radix_sort_by_key(
  74. keys_first, keys_last, values_first, false, queue
  75. );
  76. }
  77. }
  78. template<class KeyIterator, class ValueIterator, class Compare>
  79. inline void dispatch_gpu_sort_by_key(KeyIterator keys_first,
  80. KeyIterator keys_last,
  81. ValueIterator values_first,
  82. Compare compare,
  83. command_queue &queue)
  84. {
  85. size_t count = detail::iterator_range_size(keys_first, keys_last);
  86. if(count < 32){
  87. detail::serial_insertion_sort_by_key(
  88. keys_first, keys_last, values_first, compare, queue
  89. );
  90. } else {
  91. detail::merge_sort_by_key_on_gpu(
  92. keys_first, keys_last, values_first, compare, queue
  93. );
  94. }
  95. }
  96. template<class KeyIterator, class ValueIterator, class Compare>
  97. inline void dispatch_sort_by_key(KeyIterator keys_first,
  98. KeyIterator keys_last,
  99. ValueIterator values_first,
  100. Compare compare,
  101. command_queue &queue)
  102. {
  103. if(queue.get_device().type() & device::gpu) {
  104. dispatch_gpu_sort_by_key(keys_first, keys_last, values_first, compare, queue);
  105. return;
  106. }
  107. ::boost::compute::detail::merge_sort_by_key_on_cpu(
  108. keys_first, keys_last, values_first, compare, queue
  109. );
  110. }
  111. } // end detail namespace
  112. /// Performs a key-value sort using the keys in the range [\p keys_first,
  113. /// \p keys_last) on the values in the range [\p values_first,
  114. /// \p values_first \c + (\p keys_last \c - \p keys_first)) using \p compare.
  115. ///
  116. /// If no compare function is specified, \c less is used.
  117. ///
  118. /// Space complexity: \Omega(2n)
  119. ///
  120. /// \see sort()
  121. template<class KeyIterator, class ValueIterator, class Compare>
  122. inline void sort_by_key(KeyIterator keys_first,
  123. KeyIterator keys_last,
  124. ValueIterator values_first,
  125. Compare compare,
  126. command_queue &queue = system::default_queue())
  127. {
  128. BOOST_STATIC_ASSERT(is_device_iterator<KeyIterator>::value);
  129. BOOST_STATIC_ASSERT(is_device_iterator<ValueIterator>::value);
  130. ::boost::compute::detail::dispatch_sort_by_key(
  131. keys_first, keys_last, values_first, compare, queue
  132. );
  133. }
  134. /// \overload
  135. template<class KeyIterator, class ValueIterator>
  136. inline void sort_by_key(KeyIterator keys_first,
  137. KeyIterator keys_last,
  138. ValueIterator values_first,
  139. command_queue &queue = system::default_queue())
  140. {
  141. BOOST_STATIC_ASSERT(is_device_iterator<KeyIterator>::value);
  142. BOOST_STATIC_ASSERT(is_device_iterator<ValueIterator>::value);
  143. typedef typename std::iterator_traits<KeyIterator>::value_type key_type;
  144. ::boost::compute::sort_by_key(
  145. keys_first, keys_last, values_first, less<key_type>(), queue
  146. );
  147. }
  148. } // end compute namespace
  149. } // end boost namespace
  150. #endif // BOOST_COMPUTE_ALGORITHM_SORT_BY_KEY_HPP