C++ (Qt)do { // эта функция может быть распараллелена doHardComputing(); // А это легковесная функция. Она использует результаты, полученные doHardComputing doSomething(); } while (condition); // Всё это крутится в цикле пока не сработает условие выхода.
C++ (Qt)do { std::vector<std::thread> threads; for (size_t i = 0; i < NThreads; ++i) threads.emplace_back(worker); for (auto & th : threads) th.join(); doSomething(); } while(condition);
C++ (Qt)#include <iostream>#include <thread>#include <mutex>#include <condition_variable>#include <atomic>#include <vector>#include <algorithm> std::mutex mutex; std::condition_variable cv_worker;std::condition_variable cv_loop; std::atomic_bool is_done(false); static constexpr int NThreads = 8; void worker(std::vector<bool> & flags, unsigned int id){ while (!is_done) { // Имитация расчётов.. std::this_thread::sleep_for(std::chrono::seconds(5)); { // Каждый worker имеет свой флажёк, который говорит о том, что он выполнил расчёты и готов спать) std::unique_lock<std::mutex> lk(mutex); flags[id] = false; } cv_loop.notify_one(); // Пытаемся разбудить потребителя (main_loop) // И засыпаем std::unique_lock<std::mutex> lk(mutex); cv_worker.wait(lk, [&]() { return flags[id] || is_done; }); }} void main_loop(std::vector<bool> & flags){ int i = 0; auto cond = [](int i) { return i > 10; }; // условие выхода, для наглядности do { { // Спим до тех пор, пока все workerы не выполнят вычисления (все флажки = false) std::unique_lock<std::mutex> lk(mutex); cv_loop.wait(lk, [&]() { return !std::any_of(flags.begin(), flags.end(), [](bool x){ return x; }); }); } // Имитация вычислений.. std::this_thread::sleep_for(std::chrono::seconds(1)); { // После вычислений заряжаем флажки std::unique_lock<std::mutex> lk(mutex); std::fill(flags.begin(), flags.end(), true); if (cond(i++)) is_done = true; } // Будим всех воркеров и засыпаем cv_worker.notify_all(); } while (!is_done);} int main(){ std::vector<bool> flags(NThreads, false); // флажки std::thread mainthread(main_loop, std::ref(flags)); // Это наш потребитель std::vector<std::thread> threads; // Это наши производители workerы for (unsigned int i = 0; i < NThreads; ++i) threads.emplace_back(worker, std::ref(flags), i); mainthread.join(); for (auto & th : threads) th.join(); return 0;}
C++ (Qt) std::thread consumer([&]() { while (!abortFlag) { std::unique_lock<std::mutex> lock(m); /* каждый из worker'ов, закончив работу, уменьшает атомарный счетчик workerInProcess и пытается нас (производителя) будить - но мы игнорируем побудку если хотя бы один worker активен. Собсно идея в этом */ while (workerInProcess) { if (abortFlag) return; cond_var.wait(lock); } /* В этот момент все worker'ы отстрелялись и висят на (захваченном нами) мутексе, перезаряжаемся */ if (CheckDone()) break; SetupWorkersData(); // заряжаем новые данные worker'ов workerInProcess = NUM_WORKERS; cond_var.notify_all(); // стартуем worker'ов, сами засыпаем } /* даем worker'ам выйти */ abortFlag = true; cond_var.notify_all(); });
std::thread worker([&]() { while (true) { // Пресекаем "ложные побудки" { std::unique_lock<std::mutex> lock(m); while (!HasData()) { if (abortFlag) return; cond_var.wait(lock); // освобождаем мутекс и спим } }// считаем DoWorkerJob(); // уменьшаем счетчик и будим всех --workerInProcess; cond_var.notify_all(); });
C++ (Qt)#pragma omp parallel{ do { #pragma omp task { worker(); } #pragma omp taskwait doSomething(); } while (condition);}
void worker(std::vector<bool> & flags, unsigned int id){ while (!is_done) { // Имитация расчётов.. std::this_thread::sleep_for(std::chrono::seconds(5));
C++ (Qt) { // Каждый worker имеет свой флажёк, который говорит о том, что он выполнил расчёты и готов спать) std::unique_lock<std::mutex> lk(mutex); flags[id] = false; }
C++ (Qt)#pragma omp parallel forfor (int i = 0; i < data.size(); ++i) DoCalc(data[i]);
C++ (Qt)void worker(std::vector<bool> & flags, unsigned int id){...}
C++ (Qt)void worker(bool & flag)
C++ (Qt)bool loop_function() { ... } void do_work() { ... } concurrent_loop cloop(num_threads); cloop.start(loop_function, do_work); cloop.join();
C++ (Qt)do { std::vector<std::thread> threads; for (unsigned int i = 0; i < num_threads; ++i) threads.emplace_back(do_work); for (auto & th : threads) th.join(); } while (loop_function());
C++ (Qt)template <class Done>void worker(Done done){ // hard computing... done();} void caller(){ const std::size_t N = 4; std::vector<bool> flags(N, false); for (int i = 0; i < N; ++i) worker([&flags, i]() { flags[i] = true; });}