【发布时间】:2017-01-17 12:52:01
【问题描述】:
我想从这个link讨论golang中的以下结构
// Local per-P Pool appendix.
57 type poolLocal struct {
58 private interface{} // Can be used only by the respective P.
59 shared []interface{} // Can be used by any P.
60 Mutex // Protects shared.
61 pad [128]byte // Prevents false sharing.
62 }
由于使用了 Mutex,上述结构一次只能访问一个线程。编码器将在线程开始时锁定结构,并在线程完成时将其解锁。所以内存不在线程之间共享。所以不会超过一个核心 访问内存。因此,据我了解,虚假分享不会发生。如果不能发生虚假共享,编码器为什么要填充结构 有额外的字节(填充[128]字节)?我的理解错了吗?
【问题讨论】:
-
是的,您的理解是错误的:“错误共享”与访问同一内存的多个线程无关(如果一个写入,则为竞争条件),但与处理器缓存行有关:只需 google 即可获得“错误共享” :
-
@Volker Thabk 你。我明白了。让我澄清一下。假设有两个线程 t1 和 t2 在核心 C1 和 C2 上运行。让 t1 先运行(现在 t2 等待,因为有静音锁)。让 t1 将数据写入 c1 的 L1 缓存(存储我们的结构的缓存行)。现在 t2 在 C2 中准备就绪。但是 C2 中的 L2 缓存必须(通过 MESI 协议)更新为新值。在此之后,t2 可以继续其工作。这就是发生错误共享的地方。我说的对吗?
-
当您进行填充时,每个线程将在 L1 中分配一个缓存行,该缓存行将指向 L2 或更高内存中的不同内存位置。由于每个线程都在不同的内存位置上工作,因此它们不共享,因此没有 MESI 和错误共享。我说的对吗?
-
“过早的优化是万恶之源。” - Tony Hoare 爵士的名言(由 Donald Knuth 推广)。从中学习。并停止优化缓存行,除非您有完美的代码并衡量这是您当前的 #1 性能瓶颈。
标签: multithreading go mutex false-sharing