c++ 具有必须并行运行的函数的无限循环

ee7vknir  于 2022-12-24  发布在  其他
关注(0)|答案(1)|浏览(118)

我需要创建一个无限循环,在这个循环中必须有一些函数必须并行运行,因为它们访问的是只读结构,所以没有竞争条件的风险,所以我想同时运行它们以获得一些性能。
问题是我不知道如何有效地达到这个结果。
这是一个例子,我在循环中并行运行四个函数与特定的帧率(想法从循环在特定的帧率是从here):

#include <iostream>
#include <thread>
#include <random>
#include <condition_variable>
#include <mutex>

int getRandomIntBetween(int minValue, int maxValue) {
  std::random_device rd;
  std::mt19937 rng(rd());
  std::uniform_int_distribution<int> uni(minValue, maxValue);
  return uni(rng);
}

void fun1() {
  int randomInterval = getRandomIntBetween(10, 90);
  std::this_thread::sleep_for(std::chrono::milliseconds(randomInterval));
  std::cout << "fun1 done in " << randomInterval << "ms" << std::endl;
}

void fun2() {
  int randomInterval = getRandomIntBetween(10, 90);
  std::this_thread::sleep_for(std::chrono::milliseconds(randomInterval));
  std::cout << "fun2 done in " << randomInterval << "ms" << std::endl;
}

void fun3() {
  int randomInterval = getRandomIntBetween(10, 200);
  std::this_thread::sleep_for(std::chrono::milliseconds(randomInterval));
  std::cout << "fun3 done in " << randomInterval << "ms" << std::endl;
}

void fun4() {
  int randomInterval = getRandomIntBetween(3, 300);
  std::this_thread::sleep_for(std::chrono::milliseconds(randomInterval));
  std::cout << "fun4 done in " << randomInterval << "ms" << std::endl;

}

int main(int argc, char* argv[]) {
  const int64_t frameDurationInUs = 1.0e6 / 1;
  std::cout << "Parallel looping testing" << std::endl;
  std::condition_variable cv;
  std::mutex  mut;
  bool stop = false;
  size_t counter{ 0 };
  using delta = std::chrono::duration<int64_t, std::ratio<1, 1000000>>;
  auto next = std::chrono::steady_clock::now() + delta{ frameDurationInUs };
  std::unique_lock<std::mutex> lk(mut);
  while (!stop) {
    mut.unlock();

    if (counter % 10 == 0) {
      std::cout << counter << " frames..." << std::endl;
    }
    std::thread t1{ &fun1 };
    std::thread t2{ &fun2 };
    std::thread t3{ &fun3 };
    std::thread t4{ &fun4 };

    counter++;
    t1.join();
    t2.join();
    t3.join();
    t4.join();
    mut.lock();
    cv.wait_until(lk, next);
    next += delta{ frameDurationInUs };
  }

  return 0;
}

它可以工作,但是效率很低,因为我在每次迭代中创建和删除四个线程对象。
相反,我希望保持线程始终处于活动状态,然后调用循环内的函数,并使用某种锁定机制(mutexsemaphore)在循环内等待所有函数都运行完毕,然后再开始下一次循环迭代。
怎么能达到这个结果呢?

2w2cym1i

2w2cym1i1#

如果您不想依赖于线程重用,则不必求助于池:
在您的特定情况下,您可能不需要为完全开发的线程池而烦恼,因为您希望每个函数由相应的线程运行一次。
因此,您的连接就变成了对要执行某个特定作业的线程的查询:

std::array<std::atomic<bool>, 4> done;
// loop:
std::fill(begin(done), end(done), false);
// ... run threads
for (std::size_t i = 0; i < 4; ++i) {
  while (done[i] == false) {} // wait for thread i to finish
}

很明显,一旦线程i应该运行的函数完成,它就会写入done[i] = true;
您将以大致相同的方式分发工作包。

相关问题