【发布时间】: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