我编写了一个C ++库来完成一些非常繁重的CPU工作(所有数学和计算),如果留给自己的设备,将很容易消耗100%的所有可用CPU资源(它也是多线程的数字)计算机上可用的逻辑核心数。)
因此,我在主计算循环中有一个回调,使用该库的软件应该调用:
while(true)
{
//do math here
callback(percent_complete);
}
在回调中,客户端调用Sleep(x)来减慢线程。
最初,客户端代码是一个固定的Sleep(100)调用,但这会导致糟糕的不可靠性能,因为有些机器比其他机器更快地完成数学运算,但所有机器上的睡眠都是相同的。所以现在客户端检查系统时间,如果超过1秒(= =几次迭代),它将休眠半秒钟。
这是减慢线程的可接受方式吗?我应该使用信号量/互斥量而不是Sleep()来最大化性能吗?每1秒处理工作正在睡觉x毫秒,还是有什么不对的,我没有注意到?
我问的原因是,即使taskman显示该进程占用了大约10%的CPU,机器仍然严重陷入困境。我已经探讨过硬盘和内存争用无济于事,所以现在我想知道我放慢线程的方式是否导致了这个问题。
谢谢!
答案 0 :(得分:23)
为什么不对计算线程使用较低的优先级?这将确保安排其他线程,同时允许您的计算线程尽可能快地运行,如果没有其他线程需要运行。
答案 1 :(得分:4)
100%的CPU有什么问题?这是你应该努力的,而不是试图避免。这些数学计算很重要,不是吗?除非你试图避免占用操作系统未明确管理的其他资源(互斥锁,磁盘等)并由主线程使用,否则通常试图减慢线程速度是一个坏主意。那么在多核系统上(几乎所有系统都将会出现)?你绝对没有理由放慢线程。
操作系统具有线程量子的概念。它将确保您的系统上没有重要的线程被饿死。并且,正如我所提到的,在多核系统上,在一个CPU上引入一个线程并不会损害其他内核上的其他线程的性能。
我还在另一条评论中看到,这个线程也在做大量的磁盘I / O - 这些操作已经导致你的线程在等待结果时产生,所以睡眠将什么都不做。
一般情况下,如果你正在调用Sleep(x),你的设计就会出现错误/懒惰的情况,如果x == 0,你就会打开自己的锁定(调用Sleep(0)的线程)实际上可以立即重新安排,使其成为一个noop)。
答案 2 :(得分:2)
睡眠对于限制应用程序应该没问题,从你的评论就是你所追求的。也许你只需要更精确地睡多久就可以了。
我使用这种功能的唯一软件是BOINC client。我不知道它使用了什么机制,但它是开源和多平台的,所以请自己帮忙。
它有一个配置选项(“限制CPU使用到X%”)。我希望实现的方法是使用与clock()
或GetSystemTimes()
等平台相关的API,并将处理器时间与已用时钟时间进行比较。做一些真正的工作,检查你是否超过或低于标准,如果你睡了一段时间才能重新回到原地。
BOINC客户端可以很好地处理优先级,即使在100%最大CPU时也不会对其他应用程序造成任何性能问题。我使用油门的原因是,否则,客户端会一直运行CPU,并提高风扇速度和噪音。所以我在风扇保持安静的水平上运行它。有了更好的冷却,我可能不需要它: - )
答案 3 :(得分:0)
看看cpulimit。它会根据需要发送SIGSTOP
和SIGCONT
,以使进程低于给定的CPU使用百分比。
即便如此,WTF仍在“关于你的软件杀死PC性能的疯狂投诉和异乎寻常的评论”。我更有可能抱怨你的软件很慢而且没有充分利用我的硬件,但我不是你的客户。
编辑:在Windows上,SuspendThread()
和ResumeThread()
可能会产生类似的行为。
答案 4 :(得分:0)
另一个不那么复杂的方法可能是对一次迭代进行计时,让线程在下一次迭代之前休眠(x * t)毫秒,其中t是一次迭代的毫秒时间,x是选择的休眠时间分数(在0和1之间)。