我需要创建一个无限循环,在这个循环中必须有一些函数必须并行运行,因为它们访问的是只读结构,所以没有竞争条件的风险,所以我想同时运行它们以获得一些性能。
问题是我不知道如何有效地达到这个结果。
这是一个例子,我在循环中并行运行四个函数与特定的帧率(想法从循环在特定的帧率是从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;
}
它可以工作,但是效率很低,因为我在每次迭代中创建和删除四个线程对象。
相反,我希望保持线程始终处于活动状态,然后调用循环内的函数,并使用某种锁定机制(mutex
、semaphore
)在循环内等待所有函数都运行完毕,然后再开始下一次循环迭代。
怎么能达到这个结果呢?
1条答案
按热度按时间2w2cym1i1#
如果您不想依赖于线程重用,则不必求助于池:
在您的特定情况下,您可能不需要为完全开发的线程池而烦恼,因为您希望每个函数由相应的线程运行一次。
因此,您的连接就变成了对要执行某个特定作业的线程的查询:
很明显,一旦线程i应该运行的函数完成,它就会写入
done[i] = true;
。您将以大致相同的方式分发工作包。