诸如ARM之类的CPU具有弱内存模型。假设我们有两个线程T1和T2。
| T1 | T2 |
|---------|---------|
| Instr A | Instr C |
| Instr B | Instr D |在弱顺序中,任何指令都可以在任何时间运行,这意味着"D -> A -> B -> C“是可能的。
我的第一个问题是,为什么这是有益的?我的第二个问题是选择(优化)是如何完成的?是CPU随机挑选它们,还是背后有算法?是CPU在做选择,还是有另一个芯片在做这项工作(内存芯片或其他什么)?
发布于 2019-11-19 23:32:04
没有全球仲裁者会做这样的事情。如果有的话,总是按顺序做事情也是同样有效的。
立即可用的唯一数据是本地数据。每次执行都是基于快速可用的信息做出决策。
没有以相反的顺序而不是以书面顺序执行任何东西的压力。保留并不是先验的更好。但是B的数据可能在A的数据之前可用,然后B可能首先被执行,因为等待A完成将使计算资源不被使用。
因此,这一切都是在需要的时候让所有数据都可用的问题,以及处理器之间通信的延迟。您可以将其视为与只能通过非常缓慢的交流方式进行交流的人员合作的团队努力:他们将根据当地可用的信息完成尽可能多的工作。任何中央权力机构都不会准确地了解最近完成的工作的状态。
发布于 2020-02-02 00:20:50
为什么退出弱内存模型?
出于性能原因。弱内存模型允许编译器和硬件优化,从而提高系统性能。在编译和硬件实现中强制实施强内存模型(顺序一致性模型)的成本是严重的性能降级。
允许的指令重新排序是什么(如何进行选择)?
它特定于每种内存模型。有几种弱内存模型,指令重新排序规则是其规范的一部分。
指令重排序在编译器和硬件优化中普遍使用,以实现更高的性能。这些优化的基本前提是,只要保留程序的功能正确性,指令就可以重新排序。
在顺序(单线程)程序中,只需确保“如果两个操作正在访问相同的内存位置,并且其中一个是写操作,或者如果它们之间存在数据或控制依赖关系,则按程序顺序执行两个操作”,就可以保证功能正确性。
对于多线程程序,功能正确性还取决于加载和存储到同一线程中不同内存位置的相对顺序。内存模型规范指定了在不影响功能正确性的情况下对两条内存指令进行重新排序的条件。
发布于 2021-04-06 14:30:10
除了上面的答案之外:
如果没有围栏,则需要保留的唯一顺序是数据依赖顺序。因此,在单个CPU上,负载X应该在它之前看到对X的最新存储。但是,如果指令没有任何数据依赖性,则可以按任何顺序执行它们。
现代CPU的使用无序执行,最大限度地提高了指令流中的并行度。通过这种方式,独立的指令可以并行运行,并且它可以防止CPU因内存访问而停滞。
CPU使用其他技术,如存储缓冲区、加载缓冲区、写入合并等,所有这些都可能导致加载和存储被无序执行。这很好,因为它对执行这些加载和存储的内核是不可见的。问题是,当内核与其他内核共享内存时,这些重新排序可能会变得可见。
对于顺序一致性(SC),不允许重新排序;因此,所有4个栅栏都需要保留-> LoadLoadStoreLoad。
在X86上,存储缓冲区可能会导致较旧的存储使用较新的负载重新排序到不同的地址;因此,StoreLoad将被丢弃,而SC仅保留LoadLoadStoreStore。这种内存模型称为TSO (Total Store Order,总存储顺序)。
TSO可以通过允许来自相同内核的写操作被重新排序来放松(例如,写合并或不按顺序退出的存储缓冲区)。这将导致PMO (部分存储顺序)。
SC/TSO/PMO的问题是不允许某些重新排序,这可能会导致性能下降;假设在同一个CPU上有两个独立的负载,那么由于LoadLoad的原因,这些负载不能重新排序。在实践中,这可以通过推测性地执行指令来解决,如果检测到乱序加载,则刷新流水线并重新启动。这使得CPU更复杂,性能更差。
像SC,TSO,PMO这样的模型是强一致性模型,因为ever load和每个store都有一定的排序语义。但在弱序一致性模型中,在普通加载/存储(无排序语义)和同步操作(例如,提供排序语义的获取加载和释放存储)之间存在分离。具有获取加载和释放存储的弱内存模型称为释放一致性。
这些弱模型的最大优势是它们允许更高的并行度和更简单的CPU设计。它将负担转移到软件上。
在实践中,您通常使用提供特定内存模型的编程语言/API进行编程,它需要确保编译器没有违反该模型,并且向硬件添加了足够的顺序,例如以栅栏的形式。如果您看过Java或C11,并且正确地使用了它们,那么相同的代码可以在具有强内存模型(如X86 )的CPU和具有弱内存模型(如ARM )的CPU上正常运行。
https://stackoverflow.com/questions/58870009
复制相似问题