【发布时间】:2019-05-22 15:22:09
【问题描述】:
我目前正在研究并发系统,当同时处理多个线程和多个内核时,我对缓存一致性的概念有些困惑。
据我了解的一些假设:
- 核心有缓存
- 内核一次可能有多个线程(如果是超线程)
- 线程是正在处理的单行命令
- 因此,线程不是物理硬件,线程没有缓存并使用内核的缓存
假设 一个核心有我们有两个线程,x 是一个值为 5 的共享变量。两者都想执行:
my_y = x;
其中my_y 是由两个线程定义的私有变量。现在假设线程 0 执行:
x++;
最后,假设线程 1 现在执行:
my_z = x;
my_z 是另一个私有变量。
我的书是这样说的:
my_z的值是多少?是五吗?或者是六个?问题是x有(至少)三个副本:一个在主内存中,一个在线程 0 的缓存中,一个在线程 1 的缓存中。
这是如何工作的? x 怎么至少有三份副本,为什么书中规定每个线程都有自己的缓存?对我来说,运行这两个线程的核心在其缓存中具有 x 的值是有意义的,因此两个线程在“它们的”(共享)缓存中都有值。
换句话说,当x++ 被更新时,核心缓存中的值也会被更新。然后,线程 1 将执行my_z = x;,它仍在内核的缓存中并且是最新的。因此,不会有一致性问题,因为两个线程基本上共享缓存。
这本书可能假设每个内核只有一个线程,但该书之前确实提到了“如果线程数多于内核数”。 “如果线程数多于内核数”是否意味着一个内核有多个线程(超线程),或者是否发生了某种线程调度以使每个内核一次只有一个线程?
即使是这种情况(核心的调度,一个核心一次只能有一个线程),如果一个核心拥有线程0,则执行x++,然后获取试图执行@的线程1 987654334@ 如果我没记错的话,x 的值仍会存在于该内核的缓存中。
额外问题:线程的私有变量如何存储在内存中?它们的存储方式是否与使用时被复制到核心缓存中的任何变量相同?如果是这种情况,如果多个线程正在使用缓存(无论是同时还是调度),那么在内核的缓存中拥有一个私有变量会不会有问题?
根据@biziclop 的要求,本书陈述了以下假设:
- 我们使用 MIMD 系统,即节点具有相同的架构。 (不过,这本书并没有具体说明这是哪种架构)
- 我们的程序是 SPMD。因此,我们将编写一个可以使用分支来实现多种行为的程序。
- 我们假设内核相同,但异步运行。
- 我们使用 C 语言进行编程,在本节中,我们主要关注 Pthreads。
任何帮助将不胜感激!
【问题讨论】:
-
不要忘记(在高度优化的代码中)变量通常会在寄存器中存储很长时间,与任何 L1 或 L2 缓存无关。不过,如果您能指定我们正在谈论的语言/架构,那将会有所帮助。
-
谢谢,@biziclop。我在帖子中添加了更多信息。
-
IMO,如果您不是在学习设计计算机硬件,那么在您的职业生涯中尝试了解超线程的微妙之处可能还为时过早。如果您正在编写将在某些多处理器操作系统下以用户模式运行的代码,那么无论如何您将无法控制哪个内核的哪个“硬件线程”将在任何给定时刻运行您的代码。如果您根据您选择的任何编程语言的“内存模型”编写代码,那么无论操作系统选择哪些硬件资源来运行您的程序线程,它都会正确运行。
标签: multithreading caching concurrency