缓存一致性:线程与核心

时间:2019-05-22 15:22:10

标签: multithreading caching concurrency

我目前正在研究并发系统,当同时使用多个线程和多个内核时,我对高速缓存一致性的概念有些困惑。

据我所知一些假设:

  • 核心具有缓存
  • 核心一次可能有多个线程(如果是超线程的话)
  • 线程是一行正在处理的命令
  • 因此,线程不是物理硬件,线程没有缓存,而是使用内核的缓存

假设一个核心具有,我们有两个线程,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。如果我没记错的话,执行my_z = x;的x值仍将存在于该内核的缓存中。

奖金问题:线程的私有变量如何存储在内存中?它们是否与使用时将其复制到内核的缓存中的任何变量的存储方式相同?如果是这样的话,如果多个线程同时使用或计划使用缓存,则在内核的缓存中有一个私有变量是否会成为问题?

根据@biziclop的要求,该书陈述了以下假设:

  • 我们使用MIMD系统,即节点具有相同的体系结构。 (不过,书中并未具体说明这是哪种架构)
  • 我们的程序是SPMD。因此,我们将编写一个可以使用分支来具有多种行为的程序。
  • 我们假设核心是相同的,但异步运行。
  • 我们使用C语言进行编程,在本节中,我们重点介绍Pthreads。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

  

这本书为什么要指定每个线程都有自己的缓存?

作者马虎。线程没有缓存。运行线程的处理器核心具有缓存。

  

这本书以前曾说过“如果线程多于核心”。难道[暗示]暗示一个内核有多个线程(超线程),或者是否正在进行某种线程调度,以便每个内核一次只有一个线程?

其中之一可能是对的。我们已经确定作者在语言上有些草率,因此将其引语排除在上下文之外,无法判断它是在谈论比核心还是更多软件线程更多的硬件线程。

  

线程的私有变量如何存储在内存中?

一个进程中的所有线程都看到相同的确切虚拟地址空间。从最广泛的意义上讲,“专用”只是描述了仅由一个线程使用的内存位置,而为什么仅由一个线程使用并不重要。

从更狭义的意义上讲,每个线程都有一堆函数激活记录(也称为“调用栈”),其中包含所有活动函数调用的参数和局部变量。在许多编程语言中,一个线程不可能与其他任何线程共享其args或locals,因此这些内存位置自动为“私有”。在其他编程语言中,共享arg或局部变量是可能,但是程序员必须编写显式代码以共享它们,无论如何,这可能是一个坏主意。

  

如果多个线程同时使用或计划使用缓存,则在内核的缓存中具有私有变量是否会成为问题?

当两个不同的内存位置都哈希到同一个缓存位置时,称为冲突。是的碰撞有时会发生。如果某个高速缓存行包含变量X,并且线程T要访问恰好使用同一高速缓存行的变量Y,那么内存系统将使线程T等待从主内存中获取数据的时间。

这种现象也称为“虚假共享”(通常是在出现问题时使用),您可以通过Google的策略来避免这种情况,例如如果以及何时您确定它实际上降低了您的程序。