【问题标题】:wont infinite loop waste cpu resource?不会无限循环浪费cpu资源吗?
【发布时间】:2014-08-04 09:27:24
【问题描述】:

我计划将boost::lockfree::queue 用于我的多线程应用程序。 boost example 说明了这样的无锁队列消费:

boost::atomic<bool> done (false);
void consumer(void)
{
    int value;
    while (!done) {
        while (queue.pop(value))
            ++consumer_count;
    }

    while (queue.pop(value))
        ++consumer_count;
}

我的问题是这部分:

    while (!done) {
    //do something
    }

我通常在这种情况下使用condition variable,但是上面代码sn-p的简单性远比条件变量的复杂性更诱人。

虽然consumer 有自己的线程,但它几乎在整个程序期间循环。我更担心,因为很多时候//do something 部分没有被调用(队列为空),并且很多可以分配给其他线程的 CPU 时间被这个线程浪费了。我对吗? THIS 是一种常见的做法吗?

我需要有人告诉我我错了,我不应该因为这样的原因而担心这个。 要么 建议我一个更好的方法。

谢谢

【问题讨论】:

  • 该代码不是生产代码。它用于基准测试。
  • @KerrekSB 所以你不建议在这种情况下使用无限循环?
  • @rahman 这不是导致您所期望的问题的循环。事实上,在使用条件变量时,通常也需要循环来确保正确性。循环不等待锁是让忙等待变得浪费的原因。此外,它并不是真正的无限,因为它在done 为真时结束。
  • @rahman:“这种情况”是什么意思?如果你想对你的数据结构进行基准测试,那么代码是合适的。
  • @KerrekSB 不,我不是要进行基准测试。我真的要在我的应用程序中使用无锁功能。生产和消费之间的延迟并不重要。我只是不想在向这个队列发送数据时锁定线程。您也可以在接受的答案下方查看我的评论,并给我您的意见。谢谢

标签: c++ multithreading boost lock-free busy-waiting


【解决方案1】:

对于延迟敏感的应用程序,即唤醒线程所花费的时间不可接受的应用程序,这是一种非常常见的做法。

是的,在这种情况下(称为“旋转”),CPU 时间被浪费在检查布尔值上。 Spinlocks 以类似的方式实现,使其更适合于优先考虑忙等待的场景。

当生产者到消费者路径的延迟不重要时,您应该更喜欢条件变量(甚至是显式休眠)来与其他线程/进程共享 CPU。而且无论如何,当延迟很关键时,您很少需要无锁容器(这通常会暴露大量开销以避免锁定)

【讨论】:

  • -1 - 大部分时间让线程自转并不是“很常见” - 这是非常特殊的 - 它说这个线程非常重要,它可以占用 CPU 内核,无论程序在哪里运行,这通常仅适用于硬件专用于该应用程序的情况。在示例中,正如 Kerrek 所观察到的那样,它是为进行基准测试而完成的。有问题的队列接口最好与定期轮询结合使用,而不是被视为鼓励旋转。 “当延迟很关键时,你很少需要无锁结构”——根本不正确……许多原子操作都是无锁且可取的。
  • 如果您阅读这句话,我明确表示“对于 延迟敏感 应用程序”,这不是一般性陈述。而且我认为这种情况很常见(顺便说一句,在专用内核上运行的服务器应用程序)。至于第二个陈述,我的意思是“容器”(我编辑)。当延迟很关键时,很少需要无锁队列......
  • @TonyD 在阅读了 quantdev 的答案后,因为latency of the the producer-to-consumer path is not critical... 我采用了你们俩建议的解决方案。如果我理解正确,两个陈述几乎相同:used in combination with periodic pollingexplicit sleeping。所以我在外循环中使用了: boost::this_thread::sleep(boost::posix_time::seconds(0.5)) 。你们认为我在正确的道路上吗?
  • @rahman:不是真正的正确路径...硬编码睡眠会不必要地延迟事件的处理,一切都会变得有点笨拙 - 最好只使用旨在支持阻塞而不是坚持无特殊原因的无锁队列,例如英特尔 tbb 的 concurrent_bounded_queue。但是,如果您使用的图书馆没有此类产品,那么睡觉总比没有好。
  • @quantdev 重新阅读您的答案,这是“延迟敏感”这个词太弱了,无法匹配“即醒来......不可接受” - “延迟关键”更适合,但我是有点苛刻,会删除我的反对票。关于具有更差延迟的无锁容器 - 这很快就会变得复杂 - 对于那些真正需要用实际工作负载对锁定和无锁替代方案进行基准测试的人来说总是有好处的,但警告它并非全部都在无锁中是公平的青睐。干杯。
【解决方案2】:

忙碌等待的效率是否高于阻塞取决于您平均要等待多长时间。一些循环迭代可能比上下文切换更快。

使用无锁队列的要点是,它是无锁的。如果要阻止,最好按照您的建议将条件变量与另一个队列一起使用。

【讨论】:

    猜你喜欢
    • 2016-06-27
    • 2012-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 2012-11-11
    • 2020-05-18
    相关资源
    最近更新 更多