gpt4 book ai didi

c++ - 为什么添加线程不能带来进一步的性能提升

转载 作者:行者123 更新时间:2023-12-03 07:50:36 26 4
gpt4 key购买 nike

我正在学习 C++ 多线程编程。我的测试程序很简单,功能就是统计一个原子变量从0到10000000(高一点也没关系)。我不明白为什么当我将线程数从8设置为16后,执行时间反而增加了一点,而不是大幅下降。

std::atomic<int> atomicCounter{0};
void addcount(int threadId) {
while(atomicCounter.load() < 10000000) {
atomicCounter.fetch_add(1);
}
}

void test() {
const int maxNumThreads = 8;
// Time::now() is to get the timestamp accurate to ns
auto s_ts = Time::now();
std::vector<std::thread> threads;
for (int i = 0; i < maxNumThreads; i++) {
threads.emplace_back([&]() {
addcount(i);
});
}

// join the threads
for (auto& thread : threads) {
thread.join();
}
threads.clear();
auto e_ts = Time::now();
LOG(INFO) << "Executing time : " << (e_ts - s_ts) / 1000 << " us";
}

我通过改变maxNumThreads在8线程和16线程下进行了多次测试,平均执行时间分别为1.7ms和1.9ms。我的测试在配备 i9-12900k 处理器的机器上运行,该处理器有 16 个内核并支持 24 个并行超线程。

衷心感谢您的任何建议!


我想起了我的案例中明显的问题,因此我按如下方式修改了上面的代码,然后重新运行测试。结果符合预期(执行时间从 3.0ms 下降到 1.9ms)。感谢您的所有回答和评论!

std::atomic<int> atomicCounter{0};
void addcount(int threadId) {
while(atomicCounter.load() < 1000) {
//simulate threads fetch jobs from a queue and execute them once a time
atomicCounter.fetch_add(1);
for(int i = 0; i < 10000000; i++);
}
}

void test() {
const int maxNumThreads = 8;
// get the timestamp accurate to ns
auto s_ts = Time::now();
std::vector<std::thread> threads;
for (int i = 0; i < maxNumThreads; i++) {
threads.emplace_back([&]() {
addcount(i);
});
}

// Join the threads
for (auto& thread : threads) {
thread.join();
}
threads.clear();
auto e_ts = Time::now();
LOG(INFO) << "Executing time : " << (e_ts - s_ts) / 1000 << " us";
}

最佳答案

您不能指望 16 个线程递增同一原子变量的速度比一个线程快。之所以不这样做是因为,无论有多少个线程,都只有一个变量,并且所有线程都必须轮流访问它。

想象一个满是 child 的教室,有一 block 白板和一辆装满弹珠的独轮车。目标是数弹珠。于是,老师在白板上画了一个方框,在方框里写下了数字“0”,并指示 children :

  • 排队,
  • 从独轮车中取出一颗弹珠,
  • 增加框中的数字,然后
  • 走到队列后面,重复上述操作,直到手推车空了。

添加更多 child 并不会让这个过程变得更快。我们需要的是更好的算法:

  • 每个 child 都会得到一个袋子,
  • 在独轮车前排队,
  • 在你的包里装满弹珠,
  • 将包带回办公 table ,数一下里面有多少颗弹珠,
  • 在白板前排队,
  • 将您在办公 table 上数出的弹珠数量与盒子中的数量相加,
  • 从独轮车上取出另一个装满弹珠的袋子(如果它不是空的),然后重复。

第二种算法比第一种算法更复杂,但它为 children 提供了更多的时间并行彼此工作,而不是争夺独轮车和白板的使用权。每个 child 大部分时间都呆在自己的办公 table 前,数自己装满弹珠的袋子,彼此之间根本不互动。

在第二种情况下添加更多 child 确实可以更快地完成工作。*


* 但返回是递减的。每个添加的 child 的值(value)都会比之前添加的 child 少一些。您可能会达到添加更多 child 没有意义的地步。这取决于他们在白板上完成工作的速度以及他们在办公 table 上数弹珠的时间。请参阅https://en.m.wikipedia.org/wiki/Amdahl%27s_law

关于c++ - 为什么添加线程不能带来进一步的性能提升,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77244159/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com