使用提升条件互斥体时性能不佳
poor performance with boost conditional mutex
我是使用conditional_variables的新手,所以我可以很容易地在这里做一些愚蠢的事情,但是当我使用boost线程而不是直接调用函数时,我得到了一些奇怪的性能。 如果我将 func 上创建提升线程的行更改为直接调用 func,则代码运行速度会更快地运行多个订单。 我尝试使用源代码锻造的提升线程池软件,这没有什么区别......
这是代码:
#include <boost/thread.hpp>
using namespace boost;
condition_variable cond;
mutex conditionalMutex;
int numThreadsCompleted = 0;
int numActiveThreads = 0;
void func()
{
{
lock_guard<mutex> lock(conditionalMutex);
--numActiveThreads;
numThreadsCompleted++;
}
cond.notify_one();
};
int main()
{
int i=0;
while (i < 100000)
{
if (numActiveThreads == 0)
{
++numActiveThreads;
thread thd(func);
//Replace above with a direct call to func for several orders of magnitude
//performance increase...
++i;
}
else
{
unique_lock<mutex> lock(conditionalMutex);
while (numThreadsCompleted == 0)
{
cond.wait(lock);
}
numThreadsCompleted--;
}
}
return 0;
}
性能一定比直接调用函数差很多。启动一个线程,然后等待该线程结束。即使将启动线程的开销减少到零,也可以与该线程通信。而且您将至少有一个上下文切换,并且由于您的func()基本上什么都不做,因此开销成为重要因素。在 func() 中添加更多有效负载,比率将发生变化。如果必须做的事情很少,只需在发现这件事的线程上做。
顺便说一句:您有一个竞争条件,因为您在没有锁定互斥锁的情况下写入 numActiveThreads。上面的代码归结为:
int main()
{
int i=0;
while (i < 100000)
{
thread thd(func);
thd.join();
++i;
}
return 0;
}
而且真的没有理由为什么这应该比:
int main()
{
int i=0;
while (i < 100000)
{
func();
++i;
}
return 0;
}
您正在创建和销毁线程,这些线程通常作为一些较低级别的操作系统构造实现,通常是某种轻量级进程。 这种创造和破坏可能代价高昂。
最后,你基本上在做
- 创建线程
- 等待线程退出
一遍又一遍。 这意味着创建/销毁,你每次都在这样做,所以成本会加起来。
除了创建和销毁线程的开销之外,分支预测还可能导致性能差异。
如果没有线程,if 语句始终为 true,因为numActiveThreads
将在每次循环迭代的开始和结束时0
:
while (i < 100000)
{
if (numActiveThreads == 0) // branch always taken
{
++numActiveThreads; // numActiveThreads = 1
func(); // when this returns, numActiveThreads = 0
++i;
}
}
这导致:
- 分支预测永不失败。
- 没有线程创建/销毁的开销。
- 没有时间被阻塞等待获取
conditionalMutex
。
使用线程处理时,numActiveThreads
可能会也可能不会在顺序迭代中0
。 在我测试的大多数机器上,观察到了短的可预测模式,每次迭代时 if 语句和 else 语句之间的分支交替出现。 但是,有时 if 语句是在顺序迭代中选择的。 因此,时间可能会浪费在以下方面:
- 分支预测失败。
- 线程的创建和销毁。 如果创建和销毁是并发的,则同步可能会在基础线程库中发生。
- 已阻止等待获取
conditionMutex
或等待cond
。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在没有太多条件句的情况下,我如何避免被零除
- OpenMP阵列性能较差
- 递归列出所有目录中的C++与Python与Ruby的性能
- 基于多个条件处理地图中的所有元素
- 条件constexpr函数
- 无论条件是否为true,if总是在c++中执行
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 基于模板值的条件变量
- 大小相等但成员数量不同的结构之间的性能差异
- 为什么constexpr的性能比正常表达式差
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- 在相同条件下扩展多个"if"可提高性能
- C++ 条件运算符性能
- 使用提升条件互斥体时性能不佳
- 将提升::条件提高性能
- 内部评估的布尔条件以获得循环性能
- 在低光条件下(OpenCV)有更好的性能
- 条件样式不断变化的 IF 性能