8

我编写了一个 C++ 库,它可以完成一些非常繁重的 CPU 工作(所有这些都是数学和计算),如果留给它自己的设备,很容易消耗 100% 的所有可用 CPU 资源(它也是多线程的可用逻辑的数量机器上的核心)。

因此,我在主计算循环中有一个回调,使用该库的软件应该调用该回调:

while(true)
{
    //do math here
    callback(percent_complete);
}

在回调中,客户端调用 Sleep(x) 来减慢线程。

最初,客户端代码是一个固定的 Sleep(100) 调用,但这会导致性能不可靠,因为有些机器比其他机器更快地完成数学运算,但所有机器上的睡眠都是相同的。所以现在客户端检查系统时间,如果超过 1 秒(这 == 几次迭代),它将休眠半秒。

这是减慢线程速度的可接受方式吗?我应该使用信号量/互斥体而不是 Sleep() 以最大限度地提高性能吗?每 1 秒的处理工作正常睡眠 x 毫秒还是有什么我没有注意到的错误?

我问的原因是,即使 taskman 显示该进程占用了大约 10% 的 CPU,机器仍然严重陷入困境。我已经探索过硬盘和内存争用无济于事,所以现在我想知道我减慢线程的方式是否导致了这个问题。

谢谢!

4

5 回答 5

23

为什么不对计算线程使用较低的优先级?这将确保调度其他线程,同时允许您的计算线程在不需要运行其他线程时尽可能快地运行。

于 2010-01-17T15:28:12.267 回答
4

CPU 100% 有什么问题?这是你应该努力的,而不是试图避免的。这些数学计算很重要,不是吗?除非您试图避免占用一些其他资源(互斥体、磁盘等)未由操作系统明确管理并由主线程使用,否则通常尝试减慢线程速度是一个坏主意。在多核系统上(几乎所有系统都将是,向前发展)呢?你会毫无理由地减慢线程速度。

操作系统有线程量子的概念。它将确保您系统上的重要线程不会被饿死。而且,正如我所提到的,在多核系统上,一个 CPU 上的一个线程根本不会损害其他内核上的其他线程的性能。

我还在另一条评论中看到该线程也在执行大量磁盘 I/O - 这些操作已经导致您的线程在等待结果时让步,因此休眠将无济于事。

一般来说,如果你调用 Sleep(x),那么你的设计有问题/懒惰,如果 x==0,你就会打开活锁(调用 Sleep(0) 的线程实际上可以是立即重新安排,使其成为noop)。

于 2010-01-17T17:50:48.260 回答
2

睡眠应该可以很好地限制应用程序,从您的评论来看,这就是您所追求的。也许你只需要更准确地说你睡了多长时间。

我使用此类功能的唯一软件是BOINC 客户端。我不知道它使用什么机制,但它是开源和多平台的,所以请自助。

它有一个配置选项(“将 CPU 使用限制为 X%”)。我希望实现的方式是使用依赖于平台的 API,例如clock()or GetSystemTimes(),并将处理器时间与经过的挂钟时间进行比较。做一些实际的工作,检查你是否超过或低于标准,如果你超过标准,睡一会儿再回到低于标准。

BOINC 客户端可以很好地处理优先级,即使在 100% 最大 CPU 下也不会对其他应用程序造成任何性能问题。我使用油门的原因是,否则,客户端会一直运行 CPU,从而提高风扇速度和噪音。所以我在风扇保持安静的水平上运行它。有了更好的冷却,也许我不需要它:-)

于 2010-01-17T15:43:19.843 回答
0

看看cpulimit。它发送SIGSTOPSIGCONT根据需要将进程保持在给定的 CPU 使用百分比以下。

即便如此,WTF 在“关于你的软件破坏 PC 性能的疯狂投诉和古怪评论”。我更有可能抱怨您的软件运行缓慢并且没有充分利用我的硬件,但我不是您的客户。

编辑:在 Windows 上,SuspendThread()可能ResumeThread()会产生类似的行为。

于 2010-01-17T15:53:00.993 回答
0

另一种不太复杂的方法可能是对一次迭代进行计时并让线程在下一次迭代之前休眠 (x * t) 毫秒,其中 t 是一次迭代的毫秒时间,x 是选择的休眠时间分数(介于 0 和1)。

于 2010-01-17T16:14:15.997 回答