微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决如果系统是高速缓存连贯的,您是否可以在固定到不同处理器的两个线程之间破坏读取/写入操作? 如果通常可以进行撕裂,那么这种微体系结构将如何实现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版本就是这样。)

进一步阅读:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。