仓库源文

.. Kenneth Lee 版权所有 2024

:Authors: Kenneth Lee :Version: 0.1 :Date: 2024-04-08 :Status: Draft

关于语义的辨识


今天和人讨论了一个关于“内存语义”的问题,发现有些基本的,对于“语义”的,理解,没 有对齐,我这里建一个模型来描述这个问题。

所谓语义,是我们说一句话和我们对这句话的预期的一个对应关系。这又是一个所谓“道 可道”的问题。我们在这里交流,本身就依靠语言,说一句话是语言,对这句话的预期也 是语言。哪个语言在描述说话,哪个语言在描述语义呢?

所以,作为初步理解,我们先这样定义:语言是总结,语义是对总结的进一步解释。

比如我们说“内存语义”,就包含一组语言和对这组语言的深入解释。比如这是一种定义:

这个定义背后其实有很多子定义去支撑的,比如这里隐含了内存的编址空间的语义,内存 访问者的语义,内存序的语义,字长的语义等等。我们可以一路解释下去,直到我们达成 某种程度的共识,在那些共识上,我们天然有互相认可的语义(所谓“Must Be Passed Over In Silence”)。

即使我们在基本的定义上已经有了“Passed Over In Silence”的共识了,这个事情真正麻 烦的问题在于,这个期望的边界到哪里。语言通讯是双方的,所以这个期望被粗糙理解的 时候通常就是是通讯双方的,但从效率来说,双方的期望不是一致的,所以,语义到底是 谁的期望?

就内存这个语义来说,粗糙理解是Store的时候把数据保存到内存中,而Load的时候把当 初保存过的在这个地址上的数据读出来。但其实内存使用者大部分时候不关心数据有没有 保存在内存上,他关心的是“我曾经纯进去过的数据,是不是可以原封不断读回来”,至于 数据有没有进入内存,他不关心。

所以,实际上,现在的内存系统在做Store的时候,不会保证一定真的把数据保存到内存 中,而只是保证你写进去过的,一定能同样读出来。所以Store和Load的语义其实不是把 数据保存到内存上,而是保证从某个地址Store进去的数据,一定能被原封不动地从同一 个地址上读回来。

所以这个语义只是从内存访问者一方面感受到的语义,而不是内存实现方的语义,我们只 是让内存实现方去逼近内存访问者的期望。

从这个角度说,语义有主从之别,一组语义,常常是为其中一方的观察服务的,观察一方 是这个语义的\ 主方\ ,另一方(或者多方)满足这个观察上的期望,是这个语义的 从方\ 。

这并不是这个问题的全部,语义只是主方的观察期望,但这个范围其实是动态的,比如, 我们不关心性能的时候,我们不在乎从方使用了Cache这个概念去解决问题,我们看不见 Cache,但当主方关心:

  1. 性能:什么时候数据是就近取的,什么时候数据必须真正到内存中取?
  2. 多观察者的数据传播:在本地Cache中的数据,什么时候,按什么顺序传播到其他CPU 上?

这些时候,语义仍是观察者的期望,但范围被扩大了。这说明,语义是会被升级的,当我 们关心的问题多了,我们对它的期望就是会变多的。你可以说,“这不是原来的语义了”, 没有问题。关键在于,你还是把它称为“内存语义”。所以,我们必须意识到,同一个名字 的语义,是有版本和分支的区别在其中的。

总结一下,当我们讨论“语义”的时候,我们在讨论一些总结包含了哪些子信息,这些子信 息的作为一个整体,它们具有两个关键属性:

  1. 通讯双方的定义和主从关系的定义
  2. 版本和分支