Advertisement
Petrovi4

ForEach

Aug 26th, 2022
886
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.99 KB | None | 0 0
  1. #include <algorithm>
  2. #include <execution>
  3. #include <iostream>
  4. #include <list>
  5. #include <random>
  6. #include <string>
  7. #include <string_view>
  8. #include <type_traits>
  9. #include <vector>
  10. #include <future>
  11.  
  12. #include "log_duration.h"
  13.  
  14. using namespace std;
  15.  
  16. string GenerateWord(mt19937& generator, int max_length) {
  17.     const int length = uniform_int_distribution(1, max_length)(generator);
  18.     string word;
  19.     word.reserve(length);
  20.     for (int i = 0; i < length; ++i) {
  21.         word.push_back(uniform_int_distribution('a', 'z')(generator));
  22.     }
  23.     return word;
  24. }
  25.  
  26. template <template <typename> typename Container>
  27. Container<string> GenerateDictionary(mt19937& generator, int word_count, int max_length) {
  28.     vector<string> words;
  29.     words.reserve(word_count);
  30.     for (int i = 0; i < word_count; ++i) {
  31.         words.push_back(GenerateWord(generator, max_length));
  32.     }
  33.     return Container(words.begin(), words.end());
  34. }
  35.  
  36. struct Reverser {
  37.     void operator()(string& value) const {
  38.         reverse(value.begin(), value.end());
  39.     }
  40. };
  41.  
  42. template <typename Container, typename Function>
  43. void Test(string_view mark, Container keys, Function function) {
  44.     LOG_DURATION(mark);
  45.     function(keys, Reverser{});
  46. }
  47.  
  48. #define TEST(function) Test(#function, keys, function<remove_const_t<decltype(keys)>, Reverser>)
  49.  
  50. template <typename ForwardRange, typename Function>
  51. void ForEach1(ForwardRange& range, Function function) {
  52.     for_each(execution::par, range.begin(), range.end(), function);
  53. }
  54.  
  55. template <typename ForwardRange, typename Function>
  56. void ForEach(ForwardRange& range, Function function) {
  57.  
  58.     std::vector<std::future<void>> tasks;
  59.     int tmp = range.size()/std::thread::hardware_concurrency();
  60.     size_t range_size = std::max(tmp, 1);
  61.    
  62.     std::cerr << "Range_size = " << range_size << std::endl;
  63.     tasks.reserve(range_size);
  64.     auto begin = range.begin();
  65.     auto end = range.end();
  66.    
  67.     for (size_t left = distance(begin, end); left > 0;) {
  68.         const size_t current_page_size = std::min(range_size, left);
  69.         const auto current_page_end = next(begin, current_page_size);
  70.            
  71.         tasks.push_back( std::async([begin, current_page_end, function] {std::for_each(begin, current_page_end, function);}  ));
  72.            
  73.         left -= current_page_size;
  74.         begin = current_page_end;
  75.     }
  76.        
  77.     for (size_t i = 0; i < tasks.size(); ++i){
  78.         tasks[i].get();
  79.     }
  80. }
  81.  
  82. int main() {
  83.     // для итераторов с произвольным доступом тоже должно работать
  84.     vector<string> strings = {"cat", "dog", "code"};
  85.  
  86.     ForEach(strings, [](string& s) {
  87.         reverse(s.begin(), s.end());
  88.     });
  89.  
  90.     for (string_view s : strings) {
  91.         cout << s << " ";
  92.     }
  93.     cout << endl;
  94.     // вывод: tac god edoc
  95.  
  96.     mt19937 generator;
  97.     const auto keys = GenerateDictionary<list>(generator, 50'000, 5'000);
  98.  
  99.     TEST(ForEach1);
  100.     TEST(ForEach);
  101.  
  102.     return 0;
  103. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement