背景:
我用C++编写的应用程序中创建了3个线程:
- AnalysisThread(或生产者):它读取一个输入文件,解析它并生成模式,并将其加入到
std::queue
1中。 - PatternIdRequestThread(或消费者):它从队列中出队模式,并通过客户端(用C++编写)将它们逐个发送到数据库,该客户端返回模式的uid,然后将其分配给相应的模式。
- ResultPersistenceThread:它还做了一些其他事情,与数据库通信,就CPU使用率而言,它的表现很好。
前两个线程占用60-80%的CPU使用率,平均每个线程占用35%。
问题:
我不明白为什么有些线程会占用高CPU使用率。
我将其分析如下:如果操作系统决定像context-switch, interrupt和scheduling这样的决策,以确定哪个线程应该访问系统资源(如CPU时间),那么为什么同一个进程中的一些线程会比其他线程使用更多的CPU?看起来像一些线程强制从操作系统枪口下获取CPU,或者操作系统对某些线程有着真正的偏爱,从一开始就对它们有偏见,给予它们所有的资源。为什么它不能公正地给予它们平等的资源呢?我知道这是天真的想法。但是,如果我沿着这条路线思考,我会更加困惑:操作系统根据线程要完成的工作量来给线程访问CPU的权限,但是在完全执行之前,操作系统如何计算或预测工作量呢?
我想知道高CPU使用率的原因是什么?我们如何识别它们?是否可能仅通过查看代码来识别它们?有哪些工具可用?
我正在使用Visual Studio 2010。
1. 我对std :: queue也有疑问。我知道标准容器不是线程安全的。但是,如果恰好有一个线程将项目排队到队列中,则如果恰好有一个线程从中提取项目,则安全吗?我想象它就像一条管道,在一端插入数据,在另一端删除数据,那么如果同时进行,为什么会不安全呢?但这不是本主题的真正问题,您可以在答案中添加注释以解决此问题。
更新:
我发现我的消费线程正在使用忙等待,现在我已经用Sleep解决了3秒钟。这个修复是临时的,很快我会使用Event替代它。但即使使用Sleep,CPU使用率也降至30-40%,偶尔会上升到50%,从可用性角度来看,这似乎并不理想,因为系统无法响应用户当前正在使用的其他应用程序。
有没有办法仍然可以改善高CPU使用率?如前所述,生产线程(现在使用大多数CPU周期)读取文件,在其中解析数据包(某种格式),并生成模式。如果使用sleep,则CPU使用率将减少,但这是一个好主意吗?有哪些常见方法可以解决这个问题?
std::endl
在每次写入后清空缓冲区)。 - Xeostd::queue
(无论是哪种方式),所有对它的访问都必须受到保护。使用条件变量。(虽然可以使用原子变量在实现中实现无锁队列,但这不是std::queue
。) - James Kanze