内存模型 和 缓存一致性

内存模型(memory model), 好有几个名字:consistency、memory consistency, memory consistency model。我统一使用“内存模型”来代指本书中的consistency。

缓存一致性(cache coherence), 也被简写为coherence。我统一使用“缓存一致性“来代指本书中的coherence。

如今,大多数计算机系统和多核芯片都支持共享内存,每个处理器核都可以对内存进行读写操作。这种设计带来的好处很多,更好的性能、低电量和低成本。

现在想象你是内存系统的设计者,你要为某款计算设备设计新的内存系统,你首先要考虑的是保证cpu执行指令时对内存读写没有错误同时得到程序员期望的程序运行结果。这就需要你设计一套内存读写规则,来保证只要cpu按照你的规则读写内存,程序结果就没问题。

共享内存正确性 分为两方面:内存模型和缓存一致性。

内存模型(consistency, memory consistency,memory consistency model, memory model) 的作用是定义共享内存的正确性。具体的做法就是内存模型提供了一些关于内存读写的规则。通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性。

我们希望内存模型越简单越好,实际上,这是一件很复杂的事情。单线程环境下,定义正确的读写行为很简单,所以能够轻易的确定正确的程序运行结果和错误结果。但是对于共享内存系统而言,由于多线程能够同时发起读写行为(并发执行),导致一个程序实际上可以有多个正确的运行结果!

和内存模型不同,缓存一致性(coherence, cache coherence)对程序(程序员)是透明的。但是由于缓存已经是计算机标配,所以内存系统要实现缓存一致性协议。缓存一致性的目标是使多线程环境下的缓存和单线程一样做到透明。如果程序员能够从指令读写执行的结果判断出系统存在缓存,那这个系统的缓存一致性协议就不合格!

大多数系统中,缓存一致性协议在整个内存模型中起到了重要作用。基于此,本书会在第二章先介绍缓存一致性协议。

1.1 内存模型

内存模型定义了正确的内存读写行为。注意,内存模型的定义并不涉及缓存的概念(有的计算机可以没有缓存,但是多核计算机都要有内存模型)。

为什么要有内存模型呢?举一个现实中的例子,某个大学会把课程信息放到学校网站上,计算机体系结构课程被安排在152教室,在上课前,教务处发现排课出现问题,英语课也被安排到了152,于是,教务处老师赶快给网站管理员发邮件,让他把体系结构安排到153教室,然后教务处老师给所有选课的学生发了信息,让他们上学校网站重新查看体系结构的上课教室。不巧的是,网站管理员手头有其他事情在做,它并没有立即更新教室的信息,于是,学生们上网查看,发现体系结构还是在152教室,于是他们就去152上课,悲剧的是,教室里站着一位英语老师。

虽然,最后网站上面的课程信息更新到了153,也就是,教务处老师对网站信息的“写操作”最终执行了,但是,学生们看到的确实旧信息,去了错误的教室。 本来,应该教务处老师先更新网站信息,然后学生再去网站查看最新信息,由于这两个操作的执行顺序颠倒了,导致了不正确的行为(虽然两个操作都执行了,但是执行顺序却不对,从而影响了程序的结果)。

同样地,由于指令的重排序(reordering)、写缓冲区(write buffer)、指令预取(prefetching)、multi cache bank,共享内存系统也往往会产生错误的结果。因此,我们需要引入内存模型来定义正确的内存读写操作。多线程对内存读写是要遵守规矩的。

但不同于单线程程序,多线程通常会有多个正确的读写操作行为,也就是可能有多个正确的程序运行结果。这就使得理解内存模型有了一定的难度。

第三章会正式介绍内存模型,和顺序一致性内存模型(sequential consistency)。这一章会介绍为什么需要内存模型,然后给内存模型下一个定义。然后介绍顺序一致性模型,它强调多线程程序的执行应该和多个线程在一个处理器核上交错执行的效果一样。

第四章,我们进入实践阶段,看看x86和SPARC系统实现的内存模型:total store order (TSO)。为什么会产生这种模型?最初的想法是使用FIFO写缓冲区来缓存要写入内存的结果。当然,这是不符合顺序一致性模型的,但是却能带来足够的性能提升。

最后,第五章介绍松弛内存模型(relaxted or weak memory model)。大家发现顺序一致性模型中要求的顺序性很多时候是没必要的,比如,一个线程先更新10个数据,然后更新一个Synchronized 标示变量,程序员其实根本不关心前面10个数据更新的顺序,只要能保证在更新Synchronized标示变量前,那10个数据得到更新就行了。松弛内存模型就是挖掘这些潜在的能提升性能的可允许的指令重排序。

1.2 缓存一致性

如果不加防范,假设多个处理器核的缓存都有一份来自内存同一地址的数据,现在,多个核要访问此缓存中的数据并且至少一个核进行写操作,这种情况就会产生缓存不一致的问题。

举一个类似内存模型的例子,一个学生前一天访问学校网站,查看了体系结构的上课教师是152,然后记载了手机里,第二天,教务处老师更新了教室信息,现在,学生手机里的上课信息就过时了,这就产生了缓存不一致的问题。

使用缓存一致性协议可以阻止访问过时的数据。缓存一致性协议也有好多种。我们在第6-9章会一一讲到。

1.3

1.4

本书不会讲到下面的内容:

  • 同步(synchronization)。缓存一致性协议使得缓存看起来不存在。内存模型使共享内存看起来像是只允许单线程访问的内存。但这只是硬件层面的东西,对于程序员来说,在编写并发编程程序时,他们仍然要使用锁、barrier和其他的同步技巧来保证程序的正确性。 商业版的松弛内存模型。本书不涉及ARM和PowerPC内存模型的方方面面,但也会提到他们提供的实现机制。 并行编程。

results matching ""

    No results matching ""