dsi*_*cha 12 concurrency x86 multithreading caching low-level
在像x86这样提供缓存一致性的CPU上,从实际角度来看这有什么用呢?我知道这个想法是在一个核心上完成内存更新,在所有其他核心上立即可见.这是一个有用的属性.但是,如果不用汇编语言编写,就不能过分依赖它,因为编译器可以在寄存器中存储变量赋值,而不会将它们写入内存.这意味着必须采取明确的步骤,以确保在当前线程中可以看到在其他线程中完成的内容.因此,从实际角度来看,缓存一致性实现了什么?
nos*_*nos 10
简而言之,非缓存一致系统特别难以编程,特别是如果你想保持效率 - 这也是今天大多数NUMA系统都是缓存一致的主要原因.
如果缓存不一致,那么"显式步骤"将必须强制执行一致性 - 显式步骤通常是关键部分/互斥体(例如,C/C++中的volatile很简单).对于诸如互斥体之类的服务来说,如果不是不可能只跟踪那些已经发生变化且需要在所有缓存中更新的内存,那将非常困难 - 这可能需要更新所有内存,即使它甚至可以跟踪哪些核心在其缓存中具有哪些内存.
可以预测硬件可以在跟踪已更改的内存地址/范围方面做得更好,更有效,并使它们保持同步.
并且,假设一个进程在核心1上运行并被抢占.当它再次被安排时,它被安排在核心2上.
如果高速缓存不是非常重要的话,这将是非常致命的,否则核心1的高速缓存中可能存在过程数据的残余,这在核心2的高速缓存中不存在.但是,对于以这种方式工作的系统,操作系统必须在调度线程时强制执行缓存一致性 - 这可能是"更新所有内核之间的缓存中的所有内存"操作,或者它可能跟踪脏页面MMU的帮助,只同步已更改的内存页面 - 再次,硬件可能使缓存以更精细和有效的方式保持连贯.
其他作者的回应并未涵盖一些细微差别.
首先,考虑一个CPU不是逐字节处理内存,而是使用缓存行.一行可能有64个字节.现在,如果我在位置P分配一个2字节的内存,而另一个CPU在位置P + 8分配一个8字节的内存,并且P和P + 8都存在于同一个缓存线上,请观察没有缓存一致性两个CPU不能同时更新P和P + 8而不会破坏彼此的变化!因为每个CPU都在高速缓存行上进行读 - 修改 - 写,所以它们都可能写出不包含其他CPU更改的行的副本!最后一位作家将获胜,你对记忆的一次修改会"消失"!
另一件要记住的是一致性和一致性之间的区别.因为即使x86派生的CPU使用存储缓冲区,也没有保证您可能期望已经完成的指令已经修改了内存,使得其他CPU可以看到这些修改,即使编译器已决定将值写回记忆(也许是因为volatile?).相反,mod可能位于商店缓冲区中.通常使用的所有CPU都是缓存一致的,但很少有CPU具有与x86一样宽容的一致性模型.有关此主题的更多信息,请查看http://www.cs.nmsu.edu/~pfeiffer/classes/573/notes/consistency.html.
希望这有帮助,顺便说一句,我在Corensic工作,这是一家正在构建并发调试器的公司,您可能想要查看.当关于并发性,连贯性和一致性的假设证明是没有根据的时候,它有助于拾取碎片:)
想象一下你这样做:
lock(); //some synchronization primitive e.g. a semaphore/mutex
globalint = somevalue;
unlock();
Run Code Online (Sandbox Code Playgroud)
如果没有缓存一致性,那么最后unlock()必须确保globalint现在可以在任何地方看到,使用缓存一致性,您需要做的就是将其写入内存并让硬件发挥作用.一个软件解决方案可以保持哪些内存存在于哪个内存中,哪些内核,以及以某种方式确保它们在原子上同步.
如果您能找到一个软件解决方案来跟踪需要保持同步的高速缓存中存在的所有内存,那么您将赢得奖励,这比当前的硬件解决方案更有效.
| 归档时间: |
|
| 查看次数: |
3284 次 |
| 最近记录: |