reduce_by_key.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2015 Jakub Szuppe <j.szuppe@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_DETAIL_REDUCE_BY_KEY_HPP
  11. #define BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP
  12. #include <algorithm>
  13. #include <iterator>
  14. #include <boost/compute/command_queue.hpp>
  15. #include <boost/compute/functional.hpp>
  16. #include <boost/compute/container/vector.hpp>
  17. #include <boost/compute/detail/iterator_range_size.hpp>
  18. #include <boost/compute/algorithm/detail/serial_reduce_by_key.hpp>
  19. #include <boost/compute/algorithm/detail/reduce_by_key_with_scan.hpp>
  20. #include <boost/compute/type_traits.hpp>
  21. namespace boost {
  22. namespace compute {
  23. namespace detail {
  24. template<class InputKeyIterator, class InputValueIterator,
  25. class OutputKeyIterator, class OutputValueIterator,
  26. class BinaryFunction, class BinaryPredicate>
  27. size_t reduce_by_key_on_gpu(InputKeyIterator keys_first,
  28. InputKeyIterator keys_last,
  29. InputValueIterator values_first,
  30. OutputKeyIterator keys_result,
  31. OutputValueIterator values_result,
  32. BinaryFunction function,
  33. BinaryPredicate predicate,
  34. command_queue &queue)
  35. {
  36. return detail::reduce_by_key_with_scan(keys_first, keys_last, values_first,
  37. keys_result, values_result, function,
  38. predicate, queue);
  39. }
  40. template<class InputKeyIterator, class InputValueIterator,
  41. class OutputKeyIterator, class OutputValueIterator>
  42. bool reduce_by_key_on_gpu_requirements_met(InputKeyIterator keys_first,
  43. InputValueIterator values_first,
  44. OutputKeyIterator keys_result,
  45. OutputValueIterator values_result,
  46. const size_t count,
  47. command_queue &queue)
  48. {
  49. const device &device = queue.get_device();
  50. return (count > 256)
  51. && !(device.type() & device::cpu)
  52. && reduce_by_key_with_scan_requirements_met(keys_first, values_first,
  53. keys_result,values_result,
  54. count, queue);
  55. return true;
  56. }
  57. template<class InputKeyIterator, class InputValueIterator,
  58. class OutputKeyIterator, class OutputValueIterator,
  59. class BinaryFunction, class BinaryPredicate>
  60. inline std::pair<OutputKeyIterator, OutputValueIterator>
  61. dispatch_reduce_by_key(InputKeyIterator keys_first,
  62. InputKeyIterator keys_last,
  63. InputValueIterator values_first,
  64. OutputKeyIterator keys_result,
  65. OutputValueIterator values_result,
  66. BinaryFunction function,
  67. BinaryPredicate predicate,
  68. command_queue &queue)
  69. {
  70. typedef typename
  71. std::iterator_traits<OutputKeyIterator>::difference_type key_difference_type;
  72. typedef typename
  73. std::iterator_traits<OutputValueIterator>::difference_type value_difference_type;
  74. const size_t count = detail::iterator_range_size(keys_first, keys_last);
  75. if (count < 2) {
  76. boost::compute::copy_n(keys_first, count, keys_result, queue);
  77. boost::compute::copy_n(values_first, count, values_result, queue);
  78. return
  79. std::make_pair<OutputKeyIterator, OutputValueIterator>(
  80. keys_result + static_cast<key_difference_type>(count),
  81. values_result + static_cast<value_difference_type>(count)
  82. );
  83. }
  84. size_t result_size = 0;
  85. if(reduce_by_key_on_gpu_requirements_met(keys_first, values_first, keys_result,
  86. values_result, count, queue)){
  87. result_size =
  88. detail::reduce_by_key_on_gpu(keys_first, keys_last, values_first,
  89. keys_result, values_result, function,
  90. predicate, queue);
  91. }
  92. else {
  93. result_size =
  94. detail::serial_reduce_by_key(keys_first, keys_last, values_first,
  95. keys_result, values_result, function,
  96. predicate, queue);
  97. }
  98. return
  99. std::make_pair<OutputKeyIterator, OutputValueIterator>(
  100. keys_result + static_cast<key_difference_type>(result_size),
  101. values_result + static_cast<value_difference_type>(result_size)
  102. );
  103. }
  104. } // end detail namespace
  105. } // end compute namespace
  106. } // end boost namespace
  107. #endif // BOOST_COMPUTE_ALGORITHM_DETAIL_REDUCE_BY_KEY_HPP