如果系统是高速缓存连贯的,您是否可以在固定到不同处理器的两个线程之间破坏读取/写入操作? 如果通常可以进行撕裂,那么这种微体系结构将如何实现64位原子操作?

问题描述

如果同一处理器中有两个线程,则读/写操作可能会失败。

例如,在线程1和线程2在同一内核上运行的32位系统上:

  1. 线程1将64位整数0xffffffffffffffffff分配给全局变量X,该变量最初为零。
  2. 在X中将前32位设置为前32位,现在X为0xffffffff00000000
  3. 线程2将X读取为0xffffffff00000000
  4. 线程1写入最后32位。

读取的残缺发生在步骤3中。

但是如果满足以下条件怎么办?

  1. 线程1和线程2固定在不同的内核上
  2. 系统使用MESI协议实现缓存一致性

在这种情况下,仍然有可能被撕裂吗?还是在步骤3中将缓存行视为无效,从而防止读取被撕裂?

解决方法

是的,你可能会流泪。

在提交两个单独的32位存储之间可能要进行共享请求。如果它们是通过单独的指令完成的,那么写线程甚至可能在第一存储区和第二存储区之间进行了中断,从而破坏了存储缓冲区(into aligned 64-bit commits like some 32-bit RISC CPUs are documented to do)中的任何存储合并,这通常会使观察到撕裂变得困难在单独的32位存储之间进行练习。

另一种撕裂的方法是,如果读取的一侧在读取前半部分之后,在读取第二半部分之前无法访问高速缓存行。 (因为它从writer核心接收RFO(所有权读取)。)第一次读取可以看到旧值,第二次读取可以看到新值。

确保安全的唯一方法是,将存储和加载都作为对相应内核的L1d缓存的单个原子访问来完成。

(如果互连本身没有引起撕裂,请注意AMD K10 Opteron that tears on 8-byte boundaries between cores on separate sockets的情况,但似乎在同一插槽中的内核之间具有16字节对齐的原子性。x86手册仅保证8 -byte原子性,因此16字节原子性超出了实现所记录的保证范围。)

当然,某些32位ISA具有加载对或存储对指令,或者(如x86)通过FPU / SIMD单元对64位对齐的加载/存储保证原子性。


如果通常可以进行撕裂,那么这种微体系结构将如何实现64位原子操作?

通过延迟对MESI请求的响应,以共享或使一条线处于中间状态时执行一对负载或一对存储,并使用一条特殊指令完成该指令,从而在正常负载对或存储对不会出现时给出原子性t。另一个核心卡住了等待响应,因此必须严格限制您可以延迟响应的时间,否则饥饿/总吞吐速度会降低。

通常对负载对/存储对进行高速缓存的64位访问的微体系结构可以通过将一个高速缓存访​​问分为两个寄存器输出来获得免费的原子性。

但是低端实现可能没有这么宽的缓存访问硬件。也许只有LL/SC特殊指令具有2寄存器原子性。 (IIRC,某些ARM版本就是这样。)

进一步阅读:

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...