仓库源文

.. Kenneth Lee 版权所有 2025

:Authors: Kenneth Lee :Version: 0.1 :Date: 2025-04-11 :Status: Draft

中文标准写作总结


去年开始,我负责把我们一份开发中的标准改成中文的。这个工作体验给了我很多新的感 悟,这个工作做了一年了,我把一些感悟总结一下。

.. note:: 特别要说明的是,本文的内容不涉及任何真实的设计,都是经过变换后的类比 示例,和任何真正的商用秘密无关。

我们这个标准是一个芯片的构架接口,虽然主要是针对国内的开发者,但我们还是希望可 以在世界范围内合作的,所以一开始的时候我们都是直接用英文写。这个事情啊,看文档 的人难受,我们写的人其实也难受,甚至参与的英文文化背景的人也难受。所以,“直接 写成中文”这个决定一下,几乎没人反对,大家都觉得大快人心。

作为这个标准的“主编”,我最初是认为这是一个翻译工作。但随着工作的深入,我发现完 全不是:我看过不少国内翻译的计算机书籍,我真没有看过基本容易看懂的,甚至会出现 需要用中文去猜它原始的英文是什么,再用英文去思考这句话什么意思这种情况。因为这 是两种文化描述下的东西。就好比下面这个描述,你知道它什么意思吗?::

循环“入口”在范围(0, 100)中: 使“统计”等于“统计”加“入口”。

写过代码的人估计能猜到,一般人就没法搞了,因为这句话用中文说应该是这样的:::

对于(0, 100)范围中的每个成员i,执行“sum=sum+i”操作。

上面那个是“英文翻译”,下面这个才是中文。中文会需要一套新的断词和表达逻辑,各方 面都会不一样的。

所以,“中文编程”一直都发展不起来,你用中文去替换英文思考形式的代码,弄出来的就 不是“中文”,而是“用中文编码的另一种语言”。所以上面两个表达中,我们更容易接受 “sum=sum+i”,而不是“使‘统计’等于‘统计’加‘入口’”。因为即使在中文中,我们也习惯 了用英文表示变量,而用中文表示其他表述。这个道理和在数学上,英文语境的人喜欢用 罗马字母表示变量,而用英语字母表示其他表述一样的。

描述复杂的逻辑,需要增强的语言能力的。复合两种层次的语言也是这种增强的一部分。

曾经有人对比过英文和中文的区别,其中经常提到一点,就是英文喜欢发明新词,而中文 会用现有字重新组合新词。比如无人机,中文一眼就能看出特征,“无人”的“飞机”,而英 文这个词是Drone,仅凭这个词,只要你没学过,你完全不知道这是啥。

有人以此来说明中文的构词方法比英文先进,但如果你从另一个角度来说,这其实说明英 文比中文“精细”。因为英文也不是没有这样构词的东西,比如UAV:Unmaned Aerial Vehicle。但为什么要不断发明新词呢?这就是我前面说的那个分层语言的需要了。如果 你不用这种构词法,描述复杂的逻辑的时候,你就必须大量使用引号来高亮你的特定概念。 比如我们一开始的例子:

| 使“统计”等于“统计”加“入口”。

如果去掉这些引号,你能看得懂这句话吗?:

| 使统计等于统计加入口。

但如果在另一层上使用另一层的语言呢?:

| 使sum=sum+i

英文中创建Drone是因为在表述负责概念的时候,必须用这种方法来“高亮”这个概念啊。

我再给你一个例子,我在我写的标准中,把Memory Cache称为“内存缓冲”,那么Cache Coherent Domain名字就叫做“内存缓冲一致性域”。这个东西不加上引号,很多句子你都 不知道怎么断句:

| 同一台超级计算机可以由使用不同内存缓冲一致性协议的多个内存缓冲一致性域组成, | 每个计算功能可以同时属于不同的内存缓冲一致性域。

但如果换成英文的简称呢:

| 同一台SuperMachine可以由使用不同CC协议的多个CCD组成,每个Function可以同时 | 属于不同的CCD。

换一种语言来表达这个“专有名词”,表达起来就容易多了。这个问题,不是英文这个语言 本身的问题,这是你要表述复杂的逻辑时天然会遇到的。

在“翻译”这个标准的过程中,我还发现另一种通常在英文标准中的写法在中文中是不一样 的。我们这个标准支持一种“大指令”,就是每条指令都定义了一种复杂的逻辑。比如我们 要求CPU做如下三个动作:::

MEMCPY r1, r2, r3 ; 拷贝r2制定数据到r1的位置,长度在r3中 ZIP r1, r3 ; 压缩r1中指定的数据 MEMFILL r2, r1, r3 ; 把r1压缩好的数据填回r2

MEMCPY的时候我们通过r3传入了数据的长度,这个r3每次都要用。为了提高效率,我们允 许给MEMCPY提供一个属性,英文成为relay,表示MEMCPY内部记录的一些信息可以延伸到 ZIP和MEMFILL继续使用,让这个代码写成这样:::

MEMCPY.relay r1, r2, r3 ; 拷贝r2制定数据到r1的位置,长度在r3中,内部结果可以遗留给下一条指令 ZIP.relay r1 ; 压缩r1中指定的数据,内部结果可以继续遗留给下一条指令 MEMFILL r2, r1, r3 ; 把r1压缩好的数据填回r2

在英文表述中,我们把这个relay看作是一种属性,我们很自然可以说:::

A big instruction with `relay' attribute can relay its internal state to next big instruction.

但在中文表述中,我们应该如何翻译relay这个概念呢?直译的话,我们可以把它称为“接 力”,但我们从来不认为“可以接力”是一种属性。如果我们仅仅在这个描述上下文中,我 们确实可以这样说:::

一条具有“接力”属性的大指令可以把它的内部状态传递给下一条大指令。

这不会有分歧。但中文不习惯说“具有X属性的Y”,而很自然会把两者组合起来,直接说XY。 这样我们在其他上下文中就可能会这样说话:::

接力指令会把它的内部状态传递给下一条大指令。

这就很奇怪了,这条指令明明是把自己的状态传递给下一个指令,怎么变成描述自己在 “接力”了呢?

但中文这种用法总会让这些属性的及物属性的主动和被动对象发生反转。所以,这种地方 我们基本上就要对这个进行调整。比如relay指令我们都是称为“遗产块”,而不是“接力 块”,因为只有我们称它为“遗产块”了,我们才觉得这代表了它的语义了:这个块会留下 一些什么东西给下一个块。

这些微妙的差别在一个长度有限的上下文中好像都问题不大,但写成一个复杂标准,影响 就很大了。

这些问题让我们意识到,我们不是简单在写一个标准,而是在定义中文在我们这个领域的 一个扩展。我们不是在定义我们自己的标准,而是为未来如何在这个领域定义中文表述惯 例在确定标准。我们开始把CC称为“内存缓冲一致性”,这个专有名词未来就可能成为CC的 表达惯例。

在我的实践中,我会先定义内存缓冲一致性的概念,然后同时定义它的英文名是Cache Coherent,然后在一定的范围中用CC来表示它。我现在的感觉这样是最优的。

有人可能会想:为什么不直接翻译Cache Coherent的英文定义呢?

这是另一个值得讨论的问题了:因为这个东西其实并没有严格的定义。在精细的定义领域, 概念其实一直是在发展的。所以我前面才说英文发明了很多新词是因为他们这些领域确实 研究得更精细了。就以这个CC的概念来说,当初没有Cache的时候,访问内存就是读内存 的内容,根本没有Cache这个概念,后来有了Cache,也就是Cache的概念,也不需要CC。 总线其实一直在骗CPU:你要的这个内存地址的内容就是我给你的这个。CPU又不能亲自去 找内存确认,所以总线把拿过的数据临时存到Cache中,到时把Cache的数据给CPU,CPU根 本就不知道。

CC这个概念提出来,就是因为这个慌扯不下去了,当你有两个CPU一起去找内存要数据的 时候,这两个CPU可以互相校验总线有没有扯谎。为了保证这个谎能圆起来:总线让所有 的Cache形成一个协议(口供):如果CPU来问,你们得互相通个气,说一样的话,这样才 能保证CPU互相不会发现这是在扯谎。

这套协议取决于CPU只能问什么问题,如果CPU能问出不一样的问题,这个谎是扯不下去的。 但不同CPU架构有不同的提问方法,所以,粗糙的CC概念好像都差不多,但精细的定义每 家都是不一样的。

中文的技术世界中常常把x86当做标准,说到CC就直接用x86的实现当作CC的标准,这在进 行粗糙交流的时候是可以的,但如果要定义这个标准,就需要另一套方法了。

我说我们写一片中文的标准定义,会影响整个领域的中文发展,本质就是这个意思。当有 人开始这样用的,其他人会“借”它的粗糙和描述惯例去定义他们自己的细节,这个东西就 会成为一种标准。我认为中国的技术要独立自主,要发展,最终就是各行各业都必须发展 出自己这个领域的领域语言,否则你都是借用别人的语义空间,坚实不了自己的基础,你 就只能模模糊糊地跟着别人的语义空间前进,是“独立”不起来的。

再说一个体会。我有一个类似这样的表达需要:::

如果本CPU实现为一般CPU模式,它必须实现特权级0,1,其他特权级是否实现根据所支 持的扩展决定。

如果本CPU实现为加速器模式,它具体什么特权级实现相关,本标准无特别要求。

注:本标准的设计者认为一般情况下,加速器模式一般会仅模拟某个单一的特定特权行 为。

在我看过的大部分标准中,很少会写这样的“注”,因为这句话不说其实也没啥。但在实际 工作过程中,我发现加上这个注很有用。它其实表达的意思是:设计这个标准的人在校验 这个标准的涉及逻辑的时候,仅仅用单一特权阶级的加速器模式对所有的逻辑进行过校验, 所以,实现单一特权级的风险会比实现多个特权级的风险高得多。

很多人应该都了解过信息熵的概念。信息熵是一个“可能性”空间。如果我能收缩你的可能 性范围,就给你提供了更多的信息了。比如我告诉你丢一个硬币可能结果是正面的,也可 能是反面的。这个信息熵就基本熵可以认为没有。但如果我收缩一下,我告诉你,正面的 可能性是90%,这里就包含了比较高的信息熵了。

我们定义标准,其实定义的是一个很大的自由度空间,我们限制了一部分空间,保证使用 这个标准的人只需要遵循这里的限制,其他部分都是自由的。但自由就意味着风险,但说 明这种风险,就收窄了使用者的使用范围,这就提高了给他提供的信息的信息熵。

但上面这个表述并没有明确指出这一点。这也是我的一个体验:你永远都无法彻底严格地 定义一个东西,所以维特根斯坦永远都要说“The that cannot be said must be passed over in silence”。我们好像能在数学上严格定义某个东西,那是因为数学是一个虚拟世 界,我们先定义了一个收缩的逻辑空间,我们只认那个空间中的有限概念。但标准是一个 现实世界,做CPU的人用3nm还是7nm来做这个CPU可能都影响某种行为需要被定义成不同的 样子,这种东西你无法无限细化下去。就算你不在物理世界、信息输入、共识等方面没有 受到限制,信息量本身就可以把你压垮。读者也不可能向看你从沙子开始定义芯片是怎么 构成的。

这种不同的“pass over in silence”,在不同的基础语言(比如中文),不同的技术发展 阶段,会形成不同的领域语言。