【问题标题】:cache coherence overhead compared with linux signal / conditional variable与linux信号/条件变量相比的缓存一致性开销
【发布时间】:2015-12-29 08:11:09
【问题描述】:

我有一个关于缓存一致性开销的问题。我想设计一个响应速度非常快的通信隧道。这是在内存中与不同 cpu 中的两个线程/进程通信。它是一对一或广播通信,这意味着它只有一个作家,但可能有一个或多个读者。他们使用共享内存。隧道可能是一个圆形缓冲区,其中一个整数作为其在头部的写入位置。假设 writer 和每个 reader 在不同的 CPU 中,并且都是没有上下文切换的实时系统。

一种方法是,每个读取器都保持自己的读取位置,并且它们旋转并循环以检查它们在缓冲区中写入器位置的位置。一旦他们发现这两个整数不同,这意味着 readReady 和 reader 可以读取一个元素并将其读取位置向前移动一个元素。这是读取修改写入条件,但由于它是非常原子的基本类型(如整数或字节),只有一次写入,并且假设内存对齐也是常规的,这应该是安全且快速的。唯一的问题是当写入者将值写入缓存时(假设intel缓存被写回),修改不会立即传播到其他缓存,读取者读取自己的缓存并认为值没有改变。硬件将自动进行缓存一致性,以便读者可以尽快获得修改,但这会带来一些开销。

我知道最传统的实现方式是使用信号或条件变量让阅读器等待作者的通知。我担心这些方法可能有系统调用并带来数百个周期开销,或者使线程休眠等待并带来更大的延迟。我不是这个问题的专家。如果我们唯一关心的是延迟,我想知道哪种方式更好?或者有没有更好的方法?谢谢

【问题讨论】:

  • I want to know which way is better if the only thing we concern is latency? - 即使从延迟的角度来看,选择也非常依赖:来自目标机器、来自其工作负载、来自缓冲区的使用场景(有多少争用,等待多长时间)等等。最有效的选择方法是测量实际工作量所需的值并进行比较。
  • 衡量标准是时间。这意味着从编写者修改值到读者知道值被修改为止。假设它们在具有共享内存的一台机器中的两个 cpu(一个 cpu 的不同核心)中。 cpu 非常干净并且处于实时调度 (FIFO) 中,读取器继续旋转以检查值是否已修改,没有其他工作负载。
  • 我之前的评论是错误的,没关系。实际上,从延迟的角度来看,busy-waiting 总是更好的选择。至于缓存一致性延迟,您可以在读取值之前使用cache drop 指令。但我不确定它是否会给您带来比简单的循环阅读更多的好处。

标签: c++ linux multithreading caching signals


【解决方案1】:

如果您关心的只是延迟,那么忙碌等待将大大降低延迟。不幸的是,它也会给您带来更高的功耗和更高的 CPU 使用率。

对于某些应用程序,高 CPU 使用率不是问题,但如果用户有笔记本电脑或手机类型的设备,这是一个非常糟糕的解决方案,因为它会消耗电池(在某些设备的情况下) ,减慢速度,因为您已经设法将 CPU 加热到足以启动热管理以降低设备速度)。即使在插电的服务器上,功耗也不容忽视——服务器机房中 CPU 产生的热量必须通过空调排出——至于运行成本,空调的成本通常与空调的成本相同。运行服务器本身。因此,如果您编写的应用程序比其他人都好,但在繁忙的等待中消耗更多的电量,那么与同一市场的竞争产品相比,您可能会处于劣势。

这对系统中其他应用程序的性能也很不利。同样,如果您有一个具有足够核心的专用系统来处理您的应用程序以及它需要的任何其他内容,这也不是问题。如果它在通用机器上运行,那将是一个问题。

当然,这也取决于您是否希望一个线程不断地发送消息,或者它是否时不时地处于空闲状态。

一个简单的系统调用的实际长度大约是 100-1000 个周期(取决于什么操作系统版本、什么处理器等),如果操作系统决定运行其他东西,它很可能最终会被一个更大的数字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-31
    • 2011-11-14
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    相关资源
    最近更新 更多