【发布时间】:2016-05-17 09:54:06
【问题描述】:
如果使用 __thread 声明变量或常量大小的数组,支持虚拟地址范围是否可以跨线程共享缓存行? (例如,如果线程本地整数的两个副本位于同一缓存行上,性能会因为缓存行反弹而受到影响。)答案是否取决于 gcc/Linux 版本和硬件架构?
【问题讨论】:
如果使用 __thread 声明变量或常量大小的数组,支持虚拟地址范围是否可以跨线程共享缓存行? (例如,如果线程本地整数的两个副本位于同一缓存行上,性能会因为缓存行反弹而受到影响。)答案是否取决于 gcc/Linux 版本和硬件架构?
【问题讨论】:
根据臭名昭著的专家、前 glibc 维护者 Ultrich Drepper 的说法,“不在普通数据段中分配;相反,每个线程都有自己的单独区域来存储这些变量。变量可以有静态初始化器。所有线程本地变量可由所有其他线程寻址,但除非线程将指向线程局部变量的指针传递给其他线程,否则其他线程无法找到该变量。由于变量是线程局部的,因此错误共享是不是问题——除非程序人为地制造了问题。”
如果你研究,Memory part 6: More things programmers can do 线程局部变量,如果传递了一个指针,可能正在访问同一个缓存行。
为避免此问题,请不要传递有问题的地址。由于描述了将频繁的 rw 变量组合在一起以共享结构中的缓存行的特定技术,当不使用 TLS 时,只要 __thread 变量指针不被其他线程使用,填充以避免多个线程写入同一缓存行,应该避免缓存行弹跳。
希望链接器实现者了解 CPU 架构,您不能选择在虚拟和物理内存地址空间中分配多线程本地存储的位置,应该安全地假设他们和 CPU 设计人员在避免性能问题方面做了合理的工作由于虚假冲突。您可能会在不同的进程之间偶然发生相同的问题,如果缓存关联性反弹是一个常见问题,请不要介意线程。
【讨论】: