【问题标题】:Best way to slow down a thread? Is using Sleep() OK?减慢线程的最佳方法?使用 Sleep() 可以吗?
【发布时间】:2011-01-06 02:08:26
【问题描述】:

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

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

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

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

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

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

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

谢谢!

【问题讨论】:

    标签: c++ performance multithreading sleep cpu-usage


    【解决方案1】:

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

    【讨论】:

    • 实际上,这在 Windows 上不是很可靠。我已经将该库移植到 OS X 上,它的运行就像一个优先级较低的梦想,但在 Windows 上它仍然会导致问题。还有其他一些事情:出于营销/技术支持的目的,我们发现让软件在任务管理器中占用超过 20% 的 CPU 是一个坏主意,否则你会收到一些关于你的软件会破坏 PC 性能的疯狂抱怨和古怪评论.人们看到 50% 的 CPU 使用率和恐慌!
    • 我不能说为什么你的端口表现得如此。根据我的经验,调度在 Windows 上运行良好。无论如何,考虑到这个问题,我认为最好使用优先级来解决,并将调度留给操作系统。
    • 计算机大师,线程优先级在 Windows 上工作得相当可靠。但是,如果您正在执行大量 I/O(无论是直接的还是由内存分页引起的都没有关系),您可能还希望降低 I/O 优先级。请参阅 SetThreadPriority 和 THREAD_MODE_BACKGROUND_BEGIN。
    • 谢谢,阿瓦卡。我没有想到这一点 - 确实涉及到相当多的文件读写(尽管它现在以 4MB 块缓冲,但我不确定是不是我第一次尝试降低线程优先级时),并且大量的内存分页(这本身就是另一个问题)。我会试一试:)
    • 一个可能的区别是 Mac 硬件可以更优雅地发挥最大作用,而许多人不能长时间坐在他们的风扇旁边。
    【解决方案2】:

    睡眠应该可以很好地限制应用程序,您的 cmets 就是您所追求的。也许您只需要更准确地了解您的睡眠时间。

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

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

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

    【讨论】:

    • 在 Linux 上,如果您以更高的 nice 级别运行进程,则操作系统将保持 CPU 时钟较低,假设您的硬件支持 CPU 速度扩展。这样可以在不进行人为节流的情况下保持低功耗、低热量和低噪音。
    • 甜蜜。完全切换到 linux 是我一直在考虑的一个选项,但到目前为止总是拒绝...
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

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

        一般来说,如果您调用 Sleep(x),则说明您的设计有问题/懒惰,如果 x==0,您将自己打开活锁(调用 Sleep(0) 的线程实际上可以立即重新安排,使其成为无事)。

        【讨论】:

        • 也许一些上下文会有所帮助:数学是计算备份程序的两个文件之间的最小差异。 “设置它并忘记它”备份程序不应该占用 100% CPU,而单一用途的“文件差异”程序应该。这就是这个设计的关键:)
        • 啊,我明白了;这正是发明流程和 IO 优先级的原因。您应该这样做并让操作系统调度程序处理这些事情。跳过睡眠。
        • 我认为 Computer Guru 是在说他的备份程序不应该占用 100% 的 CPU,即使系统完全空闲。 karunski 说 linux 只是通过分配足够低的优先级来实现这一点,但这并不是 POSIX 中定义的优先级。进程之间的相对优先级(“如果它会饿死一些重要的东西”)和我猜你可以称之为绝对优先级(“永远不要这么快”)之间存在差异。
        • 我不相信你的规则“如果它是唯一的活动任务,让操作系统将你的进程置于 100%,应该总是被认为是好的”。由于加热原因。风扇噪音,如果系统散热能力差,则有降低节流的风险,更不用说守护进程的判断力差了。后台进程应该谨慎。
        猜你喜欢
        • 2012-05-28
        • 1970-01-01
        • 2020-09-01
        • 2011-12-06
        • 2020-06-16
        • 2011-12-03
        • 1970-01-01
        • 1970-01-01
        • 2014-03-02
        相关资源
        最近更新 更多