sort.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <[email protected]>
  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_HPP
  11. #define BOOST_COMPUTE_ALGORITHM_SORT_HPP
  12. #include <iterator>
  13. #include <boost/utility/enable_if.hpp>
  14. #include <boost/compute/system.hpp>
  15. #include <boost/compute/command_queue.hpp>
  16. #include <boost/compute/algorithm/detail/merge_sort_on_cpu.hpp>
  17. #include <boost/compute/algorithm/detail/merge_sort_on_gpu.hpp>
  18. #include <boost/compute/algorithm/detail/radix_sort.hpp>
  19. #include <boost/compute/algorithm/detail/insertion_sort.hpp>
  20. #include <boost/compute/algorithm/reverse.hpp>
  21. #include <boost/compute/container/mapped_view.hpp>
  22. #include <boost/compute/detail/iterator_range_size.hpp>
  23. #include <boost/compute/iterator/buffer_iterator.hpp>
  24. #include <boost/compute/type_traits/is_device_iterator.hpp>
  25. namespace boost {
  26. namespace compute {
  27. namespace detail {
  28. template<class T>
  29. inline void dispatch_gpu_sort(buffer_iterator<T> first,
  30. buffer_iterator<T> last,
  31. less<T>,
  32. command_queue &queue,
  33. typename boost::enable_if_c<
  34. is_radix_sortable<T>::value
  35. >::type* = 0)
  36. {
  37. size_t count = detail::iterator_range_size(first, last);
  38. if(count < 2){
  39. // nothing to do
  40. return;
  41. }
  42. else if(count <= 32){
  43. ::boost::compute::detail::serial_insertion_sort(first, last, queue);
  44. }
  45. else {
  46. ::boost::compute::detail::radix_sort(first, last, queue);
  47. }
  48. }
  49. template<class T>
  50. inline void dispatch_gpu_sort(buffer_iterator<T> first,
  51. buffer_iterator<T> last,
  52. greater<T> compare,
  53. command_queue &queue,
  54. typename boost::enable_if_c<
  55. is_radix_sortable<T>::value
  56. >::type* = 0)
  57. {
  58. size_t count = detail::iterator_range_size(first, last);
  59. if(count < 2){
  60. // nothing to do
  61. return;
  62. }
  63. else if(count <= 32){
  64. ::boost::compute::detail::serial_insertion_sort(
  65. first, last, compare, queue
  66. );
  67. }
  68. else {
  69. // radix sorts in descending order
  70. ::boost::compute::detail::radix_sort(first, last, false, queue);
  71. }
  72. }
  73. template<class Iterator, class Compare>
  74. inline void dispatch_gpu_sort(Iterator first,
  75. Iterator last,
  76. Compare compare,
  77. command_queue &queue)
  78. {
  79. size_t count = detail::iterator_range_size(first, last);
  80. if(count < 2){
  81. // nothing to do
  82. return;
  83. }
  84. else if(count <= 32){
  85. ::boost::compute::detail::serial_insertion_sort(
  86. first, last, compare, queue
  87. );
  88. }
  89. else {
  90. ::boost::compute::detail::merge_sort_on_gpu(
  91. first, last, compare, queue
  92. );
  93. }
  94. }
  95. // sort() for device iterators
  96. template<class Iterator, class Compare>
  97. inline void dispatch_sort(Iterator first,
  98. Iterator last,
  99. Compare compare,
  100. command_queue &queue,
  101. typename boost::enable_if<
  102. is_device_iterator<Iterator>
  103. >::type* = 0)
  104. {
  105. if(queue.get_device().type() & device::gpu) {
  106. dispatch_gpu_sort(first, last, compare, queue);
  107. return;
  108. }
  109. ::boost::compute::detail::merge_sort_on_cpu(first, last, compare, queue);
  110. }
  111. // sort() for host iterators
  112. template<class Iterator, class Compare>
  113. inline void dispatch_sort(Iterator first,
  114. Iterator last,
  115. Compare compare,
  116. command_queue &queue,
  117. typename boost::disable_if<
  118. is_device_iterator<Iterator>
  119. >::type* = 0)
  120. {
  121. typedef typename std::iterator_traits<Iterator>::value_type T;
  122. size_t size = static_cast<size_t>(std::distance(first, last));
  123. // create mapped buffer
  124. mapped_view<T> view(
  125. boost::addressof(*first), size, queue.get_context()
  126. );
  127. // sort mapped buffer
  128. dispatch_sort(view.begin(), view.end(), compare, queue);
  129. // return results to host
  130. view.map(queue);
  131. }
  132. } // end detail namespace
  133. /// Sorts the values in the range [\p first, \p last) according to
  134. /// \p compare.
  135. ///
  136. /// \param first first element in the range to sort
  137. /// \param last last element in the range to sort
  138. /// \param compare comparison function (by default \c less)
  139. /// \param queue command queue to perform the operation
  140. ///
  141. /// For example, to sort a vector on the device:
  142. /// \code
  143. /// // create vector on the device with data
  144. /// float data[] = { 2.f, 4.f, 1.f, 3.f };
  145. /// boost::compute::vector<float> vec(data, data + 4, queue);
  146. ///
  147. /// // sort the vector on the device
  148. /// boost::compute::sort(vec.begin(), vec.end(), queue);
  149. /// \endcode
  150. ///
  151. /// The sort() algorithm can also be directly used with host iterators. This
  152. /// example will automatically transfer the data to the device, sort it, and
  153. /// then transfer the data back to the host:
  154. /// \code
  155. /// std::vector<int> data = { 9, 3, 2, 5, 1, 4, 6, 7 };
  156. ///
  157. /// boost::compute::sort(data.begin(), data.end(), queue);
  158. /// \endcode
  159. ///
  160. /// Space complexity: \Omega(n)
  161. ///
  162. /// \see is_sorted()
  163. template<class Iterator, class Compare>
  164. inline void sort(Iterator first,
  165. Iterator last,
  166. Compare compare,
  167. command_queue &queue = system::default_queue())
  168. {
  169. ::boost::compute::detail::dispatch_sort(first, last, compare, queue);
  170. }
  171. /// \overload
  172. template<class Iterator>
  173. inline void sort(Iterator first,
  174. Iterator last,
  175. command_queue &queue = system::default_queue())
  176. {
  177. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  178. ::boost::compute::sort(
  179. first, last, ::boost::compute::less<value_type>(), queue
  180. );
  181. }
  182. } // end compute namespace
  183. } // end boost namespace
  184. #endif // BOOST_COMPUTE_ALGORITHM_SORT_HPP