.. Kenneth Lee 版权所有 2021
:Authors: Kenneth Lee :Version: 1.4
一个例子——逐句翻译是怎么掐断逻辑链的
最近分析一个问题的时候想详细看看MESI怎么定义的,图方便,我就去查了中文维基百科 的词条。基本上没看懂。
然后我又去看了一下英文版的wikipedia。我注意到前者基本上是后者的逐字翻译。而且说 起来呢,每句翻译起来也算不上错,但综合起来呢,前者你就搞不清楚它在说什么,后者 却相当清楚。
所以我想要剖析一下这个例子。
我们先看两者对MESI的总结,中文版是这样的:
| MESI协议是一个基于失效的一致性协议,是支持回写(write-back)
| 缓存的最常用协议。
基于“失效”的一致性协议?你能猜到这是什么东西吗?
英文版是这样的:
| The **MESI protocol** is an Invalidate-based
| *cache coherence protocol*, and is one of the most common
| protocols which support *write-back caches*.
你如果从字面来说呢,这句话翻译得一点问题没有。但后面这个我就能看懂,而前面这个 我就看不懂。为什么呢?我觉得原因是:
我们再看后面的进一步解释。这是中文版:
| 总有“脏”(dirty)状态表示缓存中的数据与主存不同。MESI协议要求在
| 缓存不命中(miss)且数据块在另一个缓存时,允许缓存到缓存的数据复制。
第一句和第二句之间用了一个句号,但从语气上还是可以看出第一句是第二句的某种“条件”。 但这两句话对于说明“MESI是什么”的作用到底是什么呢?我从这句话得到的信息是什么呢 ?谁有dirty状态,dirty状态又和miss有什么关系呢?
然后我们看英文版:
| There is always a dirty state present in write back caches which
| indicates that the data in the cache is different from that in
| main memory. Illinois Protocol requires cache to cache transfer
| on a miss if the block resides in another cache.
这个就可以看懂了。这里第一句话是个陈述句。先描述了一个事实:在write back caches 中,会有一个dirty状态表示cacheline的数据和主存的数据是否一致。然后第二句话说, MESI(这里用Illinois表示,这个在原文有解释,我前面跳过了,Illinois是MESI协议的 另一个叫法)协议需要通过cache到cache之间传输达成数据一致。如果对Cache同步协议的 基本用途有所认识,我很容易知道这在说什么:这是在描述MESI的关键特征。dirty的数据 不是靠和主存同步来实现的(这是一般人自然会做出的选择),而是靠和其他cache同步得 到最新的数据。
.. figure:: _static/MESI.svg
和前面一样,这里的中文翻译,从单句来说,其实没有多少瑕疵,但合在一起,你根本不 知道它在说什么。而英文版本,是个连续的逻辑链。
我们接着看正文。正文的第一章,叫State(状态)。题目要靠内容来解释,所以我们重点 看内容。
中文版第一句话是这样的:
| 缓冲行有四种不同的状态:
这里的上下文是什么?什么缓冲行就有四种不同的状态了?有四种不同的状态跟MESI有什 么关系?我应该怎么take(认知)这个信息?
对比一下英文版本:
| The letters in the acronym MESI represent four exclusive states
| that a cache line can be marked with (encoded using two
| additional bits):
你看,这个逻辑就是从根子上开始建的:你不是问我MESI是什么吗?我现在告诉你,MESI 是四个字母,表示四种不同的状态。而且我明确告诉你,这四个状态是“正交的”(互相不 相容)。可以用两个bit标记在Cacheline上。
注意一下区别啊:
这不是说cache line有四种状态,cache line状态可以有很多,但MESI是附加上去的一 个独立的状态。有点简单的集合论的认识,就能发现这是完全不同的。Cache的设计有 很多种,原文前面就已经提到了Write-back和Write-Through了,你这里说缓冲行有四 种状态,到底说的是MESI的cache,还是Write-back都有,还是只要是Cache设计都会有 呢?你让我猜吗?我猜回来的各种信息,我在多大程度上相信它呢?这个逻辑链整个软 绵绵的,碰哪里哪里不稳,这种文字就不包含有效信息了。
英文版本多了一个信息:MESI四个状态是正交的。而且明确加了一个例证:可以用两个 bit表示。如果这不是正交的,就需要超过2个bit才能表示了。
最后一个区别前面提到了,英文版本逻辑的根是不同的。这也制造了范围的不同。中文
版本说“缓冲区有四种不同的状态”,这个范围是无限大,而且你没法猜这范围是什么,
这句话说完了,你拿不到信息。英文版本说的是MESI的含义,它的范围是有限的。就是
你的Cache算法如果用MESI协议,你的cache上需要带上两个bit表示这个状态。至于缓
冲行有多少状态,这个事情“不知”(\ :doc:“知不知”如何影响决策的?
\ )——而我们
的逻辑不依赖这个信息。\ :doc:“病病”
\ 。
还可以看看第二章,操作(Operation)。中文版的开头是这样的:
| 有限状态自动机的状态转换结束两种场景:……
这就像自动翻译了,完全不知道在说啥。你得看英文版才知道这里要说什么:
| The state of the FSM transitions from one state to another based
| on 2 stimuli.
The state,指代前面的M,E,S,I四个状态,然后说把这四个状态作为有限状态的状态切 换的时候,他们被两个“有限状态自动机”的概念中的“激励”(Stimuli)所驱动。这个表述 很清楚,中文的翻译只说这一句还是没有太大的毛病,但你真要理解这个意思,中文版的 表述就好像在梦呓一样。
后面的例子就不看了,我这里也不是要做翻译,其他基本上都是类似的问题。
我对这个问题有兴趣,主要是因为,中文维基百科这个版本,实在太像我们不少工程师写 的设计文档了。我想从中深挖一下,为什么会出现这种情况的。
中文维基百科这些翻译者,我想不能说他们不努力。而且从单句来说,这些翻译也不能说 它差,但就整个文档来说,也只能说“非常差”。反正如果你不懂MESI,不要指望看这些文 字看懂到底什么是MESI。甚至你明明还懂一点,它会让你更加的懵逼。究其原因,主要就 是翻译者根本就不知道原文说的是个什么东西,没办法维系整个文字上下文一直维系的那 个逻辑关系,没有办法保证前一句描述的那个集合,和后一句从另一个角度描述的那个集 合是基本重合的。因为文字表达的集合在不同的语言上就是不同的。一个典型的例子就是 羊,英文就没有直接对应的集合,无论是goat,sheep,bushbuck,anteope,都不是中国 人说的羊那个集合,甚至没有包含关系和明确的边界。这是语言的特征。
但为什么我们懂行的工程师也会这样呢?我猜啊,是因为我们很多工程师就是读这样的“中 文翻译”入行的。也许他们已经习惯了看这种上不着天,下不着地的文字了,然后他们就不 会思考了,自己写的东西,除了代码(代码关键是一旦理解错了会导出错误的结果),其 他的文字抽象都是这样没有逻辑的。
如果这个判断没有错,这简直没救了。我以前有一个认知:英文背景的工程师明显比中文 背景的工程师在写文档的时候更有逻辑。我一直不知道自己是否太“崇洋媚外”了。现在看 来,这个认识可能是有道理的。实际情况就是,我们大部分工程师就是靠看这样的“翻译” 学术文章长大的。
但我也不认为是中文表达能力不强。过去确实也看过有人提出过“中文缺乏理性的表达能力 ”的说法。其实这个要看领域,中文原生的表达,都是逻辑性极强的,比如我最近看资治通 鉴记录的一些总结:
| (文侯问李克如何看人)
| 克曰:君弗察故也。居视其所亲,富视其所与,达视其所举,穷视其所不取,
| 贫视其所不为。五者足以定之矣。
这个用词精准,指代的范围非常清晰啊。富和达,被看做两个独立(非正交)的集合。富 看交往,达看结党,穷途末路看守着什么不去用作筹码,没钱看不赚什么明明可以赚的钱 ,分得清清楚楚。
再看逻辑链:
| (贾谊上汉景帝疏)
| 臣窃惟今之事势,可为痛哭者一,可为流涕者二,可为长太息者六……
| 使为治,劳志虑,苦身体,乏钟鼓之乐,勿为可也……
| 然天下少安,何也?大国之王幼弱未壮,上数爽其尤……
| ……可痛哭者,此病是也。
一环套一环,从一个最大的集合(为治)一步步收缩到当前形势,然后对问题排序,给出 解决方案。洋洋洒洒数千字,一直都不会离开逻辑链。
就不说这些古代精英的文字了,就说我前面简单的翻译,也同样能把那个问题说清楚。所 以事情不在于语言,而在于你有没有打算维持你的逻辑链。而逻辑链本身基本上不能靠文 字给你说清楚,它是文字背后的那个“意思”,那个“指向”。那个“无名”的,在背后萦绕着 的Pattern。
所以,到头来我也没有什么可以总结的了。如果读者实在看不懂本文的“道”,那么在“器” 上,我就只能说,计算机资料,还是尽量看英文的吧。而写文档,别顾着堆辞藻,注意一 下你想告诉别人什么吧。
从架构的角度深入考虑一下这个问题。为什么架构设计总是把概念空间建模放在很高的位 置上呢?因为不同的“说法”导向不同的细节。上面的很多例子,用英文说的东西,用中文 说就不能是一对一的翻译,因为中文的概念和英文的概念都指向不同的集合。就算你是直 译过去的,比如cache line,这可以说是直接对应缓冲行吧?但在英文的上下文中可能会 在特定上下文中把它简写为line,并索引和line相关的其他属性。但中文中的行,不一定 可以对应到line,英文你永远都不会把line和column对应,但中文的行,是可以和列对应 的。这样两者就走偏了。
同样,在软件上,你可以说线程这个概念,但Linux的线程,和VxWorks的线程你就不能认 为它们是一样的。我们可以建立高层的概念去表述“线程”有关的属性,但一旦我们向下约 束为Linux的线程,我们就必须接受它用户线程和内核线程的对应关系,我们就必须接受它 的中断线程化设计,接受它的非实时调度算法等等。所以,同样是一个“线程”的概念,在 架构上的含义,和在实现上的含义,就是不同的。
所以,在每层架构上,我们相同的名字都表达不同的范围,有不同的指向,我们不得不通 过概念空间(多个概念互相关系)来维持这个指向,如果你思考问题的时候总是把它针对 着代码去解释,这个自由度就都没有了,你就做不了架构设计了。