printSTL

printРаспараллеливание программ

В стандарт С++ 2011 года были добавлены классы для работы с потоками, мьютексами, переменными для блокировки по условию, атомарные переменные, асинхронные вызовы и способы получения результатов от них. В 2020 были добавлены сопрограммы, семафоры, дополнительные классы для синхронизации и управления потоками.
Классы и функции, необходимые для распараллеливания программ, описаны в заголовочном файле <thread>. Кроме того, для распараллеливания вычислений, не требующих синхронизации и блокировок, можно использовать набор атомарных операций и типов, описанный в <atomic>
mutex m;
void input(string msg, int &n)
{ lock_guard<mutex> lm(m); // блокировка выполнения функции в других потоках
  cout<<msg;
  cin>>n;
}
void f(string t) // функция, которая будет выполняться параллельно
{ int n;
  input(t+" thread:",n);
  for(int i=0;i<n;++i)
    this_thread::sleep_for(100ms); // задержка 100мс
  cout<<t<<" thread finished\n";
}
int main()
{ thread t1(f, string("First")); // запуск потоков управления
  thread t2(f, string("Second")); 
  t1.join(); // ожидание завершения
  t2.join();
}
Для обработки данных большого объема в C++17 добавлены параллельные версии для многих стандартных алгоритмов. В качестве первого аргумента при вызове указывается режим выполнения execution::par (возможна разделение данных на части и их параллельная обработка) или execution::par_unseq (возможна векторизация, т.е. одновременная обработка групп данных), по умолчанию применяется режим execution::seq (без распараллеливания).

#include <execution>
#include <algorithm>
#include <future>
// подсчитать, сколько значений в массиве a больше x
int count0(int a[], int n, int x) 
{ // последовательная версия
  return std::count_if(a,a+n,[=](int v){ return v>x; });
}
int count1(int a[], int n, int x) 
{ // параллельная версия, в MinGW не реализовано
  return std::count_if(std::execution::par,a,a+n,[=](int v){ return v>x; });
}
int count2(int a[], int n, int x)
{ // разбиение на отрезки с асинхронным вычислением
  if (n < 1000000)
    return std::count_if(a,a+n,[=](int v){ return v>x; });
  future<int> res = std::async(count2, a+n/2,n-n/2,x);
  return count2(a,n/2,x) + res.get();
}
loading