2008-08-05 19 views
37

我只是想知道是否有一种优雅的方式来设置特定线程进行密集计算的最大CPU负载。


现在我已经找到线程中最耗时的循环(它只能进行压缩),并使用带硬编码值的GetTickCount()Sleep()。它确保循环持续一段时间,并且在一定的最短时间内睡眠。它或多或少地确保线程不会占用超过50%的CPU。
但是,行为取决于CPU内核的数量(巨大的缺点)并且简单丑陋(更小的缺点:))。
有什么想法?在C++中CPU节流

+1

你想实现什么样的可见行为?也就是说,这个监督人员想要从你的线索中得到什么?他们绝不应该使用超过80%的CPU吗?可以将进程基地优先级设置为闲置可能使WD平静吗? – wordmonger 2008-08-11 19:52:53

回答

17

我不知道有任何API可以让操作系统的调度程序做你想做的事情(即使你的线程空闲优先级,如果没有更高优先级的就绪线程,你将运行)。不过,我认为你可以根据你已经在做的事情来制作一个相当优雅的节流功能。基本上(我没有一个Windows开发机器,方便):

选择一个线程每次迭代将默认的睡眠时间。然后,在每个迭代(或每n次迭代,从而使流量调节功能本身并不成为一个显著的CPU负载),

  1. 计算自从上次你节流功能使用您的线程的CPU时间量被称为(我会称之为dCPU)。您可以使用GetThreadTimes() API来获取线程执行的时间。
  2. 计算自上次调用throttling函数以来流逝的实时量(我将调用此dClock)。
  3. dCPU/dClock是CPU使用率(一个CPU)的百分比。如果它高于你想要的,增加你的睡眠时间,如果降低,减少睡眠时间。
  4. 让您的线程在计算时间内休眠。

根据您的看门狗如何计算CPU使用率,您可能需要使用GetProcessAffinityMask()来查明系统有多少个CPU。 dCPU /(dClock * CPU)是可用CPU总时间的百分比。

对于初始睡眠时间和增加/减少量,您仍然需要选择一些神奇数字,但我认为可以调整此算法以使线程保持相当接近CPU的确定百分比。

+0

如果你的目标是为了避免浪费CPU时间,更便宜的启发式可能是更好的选择。根据您的线程在高系统负载下自行挨饿的问题的多少,您可以*检查经过的挂钟时间。在x86上,这很便宜,因为基于`rdtsc`的时间函数甚至不需要进入内核模式。进行多次系统调用甚至是“n”次迭代都比只做一次更糟糕,除非它可以让你大量增加`n`并且仍然可以得到你想要的行为。 – 2016-05-11 07:57:39

2

我想不出你想要什么任何跨平台的方式(或者任何保证方式完全停止),但由于您使用的GetTickCount也许你不感兴趣的跨平台:)

我会使用进程间通信并将密集的进程设置为很好的级别以获得您所需的内容,但我不确定这适合您的情况。

编辑: 我同意Bernard这就是为什么我认为一个过程而不是一个线程可能更合适,但它可能不符合您的目的。

4

在linux上,您可以使用nice()更改线程的调度优先级。

+0

其他平台也有类似的功能,请参阅:https://stackoverflow.com/questions/18884510/portable-way-of-setting-stdthread-priority-in-c11我认为这可以是一个很好的解决方案,尽管不同的语义 - 即没有50%的CPU消耗保证 – milianw 2018-01-08 09:03:16

2

问题是,当你有工作要离开CPU空闲时,这是不正常的。通常情况下,您将后台任务设置为IDLE优先级,并让操作系统处理交互式任务未使用的所有CPU时间。

这听起来像问题是看门狗过程。

如果您的后台任务受到CPU限制,那么您希望它为其任务执行所有未使用的CPU时间。

也许你应该看看修复看门狗程序?

+1

想要一个空闲的CPU是非常合理的。也许你想做一些计算,但不关心它完成的速度有多快,只要它不会使笔记本电脑上的CPU风扇旋转起来。 – Ringding 2009-09-21 10:32:35

0

您可能能够更改线程的优先级,但更改最大利用率要么需要轮询和黑客来限制正在发生的事情,要么使用可设置进程的最大利用率的操作系统工具。 但是,我没有看到你想要这样做的任何情况。