详细描述
A.例子
本方法的某些方面可通过考虑某些例子来更好地理解。在例1中,考虑句子“the cat ate the dog”的区块表示。表1示出在第一处理器(称其为处理器A)的存储器中针对例1句子的一种可行区块配置。
P1 |
“the” |
|
P2 |
“cat” |
|
P3 |
“ate” |
|
P4 |
“dog” |
|
P5 |
P1、P2 |
“the cat” |
P6 |
P5、P3 |
“the cat ate” |
P7 |
P1、P4 |
“the dog” |
P8 |
P6、P7 |
“the cat ate the dog” |
表1:“the cat ate the dog”的表达
这里,标为“PID”的列给出物理区块ID(在下面的说明书中经常简写为PBlockId),标为“区块内容”的列给出区块内容,而标为“表达”的列给出对包含指针的区块由区块代表的句子。区块不变具有若干涵意。一个是无法直接改变区块的内容(即区块P1中的“the”无法改变为“a”)。另一个是pBlockId与区块内容的关联无法变化(例如“cat”区块的pBlockId无法从P2改变为P10)。
在本例中,区块组织成二进制有向无环图(DAG)。在示例句子中,由于两区块指向区块P1以说明对“the”区块的再次使用,因此本例的数据结构不是树。尽管使用树形DAG是效率优选的,然而也可作为不变区块来表示和传输许多其它数据结构。在一些情形下,可通过将2个以上区块ID装入这些区块而采用可变的扇出DAG,如果合适的话。
该区块表示的句子从处理器A至另一处理器(被称为处理器B)的传输可用包含下列消息(消息自变量在消息名称后的()中)的协议实现,每个消息是依照接收处理器基于消息接收做什么而描述的。
(1)reqBlock(pBlockId)——接收方查找PBlockId并返回具有PBlockId和关联内容的defBlock消息。
(2)defBlock(pBlockId,内容)——接收方查找其存储器中的内容以得到本地pBlockId,如果必要则分配和初始化本地区块。如果本地pBlockId不同于由发送方提供的pBlockId,则接收方保持跟踪发送方pBlockId至本地pBlockId的映射。该消息中的显式pBlockId允许将其用来推数据,与仅对查询作出响应相反。
在该例中,将指出的句子从处理器A传输至处理器B的消息业务可如表2所示,假设当传输开始时在处理器B尚未定义区块“the”、“cat”、“dog”或“ate”
1 |
A至B |
defBlock P8是P6、P7 |
2 |
B至A |
reqBlock P6 |
3 |
A至B |
defBlock P6是P5、P3 |
4 |
B至A |
reqBlock P3 |
5 |
A至B |
defBlock P3是“ate” |
6 |
B至A |
reqBlock P5 |
7 |
A至B |
defBlock P5是P1、P2 |
8 |
B至A |
reqBlock P1 |
9 |
A至B |
defBlock P1是“the” |
10 |
B至A |
reqBlock P2 |
11 |
A至B |
defBlock P2是“cat” |
12 |
B至A |
reqBlock P7 |
13 |
A至B |
defBlock P7是P1、P4 |
14 |
B至A |
reqBlock P4 |
15 |
A至B |
defBlock P4是“dog” |
表2:例1的消息步骤
注意在步骤13中,在处理器B被告知区块P7引用区块P1和P4的情形下,区块P1因步骤9已在处理器B作出了定义。因此,在步骤13之后,无需再次传输P1的区块内容。
在例2中,考虑例1中从“the cat ate the dog”变至“the mouse atethe dog”的结果。
PID |
区块内容 |
表达 |
P1 |
“the” |
|
P2 |
“cat” |
|
P3 |
“ate” |
|
P4 |
“dog” |
|
P5 |
P1、P2 |
“the cat” |
P6 |
P5、P3 |
“the cat ate” |
P7 |
P1、P4 |
“the dog” |
P8 |
P6、P7 |
“the cat ate the dog” |
P9 |
“mouse” |
|
P10 |
P1、P9 |
“the mouse” |
P11 |
P10、P3 |
“the mouse ate” |
P12 |
P11、P7 |
“the mouse ate the dog” |
表3:“the mouse ate the dog”的表达
表3示出新句子在处理器A的区块表达。除了新的“mouse”区块(P9),需要新的区块P10、P11和P12以说明改变后的区块指针。
将这种改变传输至处理器B可通过表4所示消息步骤来完成。
步骤 |
方向 |
消息 |
1 |
A至B |
defBlock P12是P11、P7 |
2 |
B至A |
reqBlock P11 |
3 |
A至B |
defBlock P11是P10、P3 |
4 |
B至A |
reqBlock P10 |
5 |
A至B |
defBlock P10是P1、P9 |
6 |
B至A |
reqBlock P9 |
7 |
A至B |
defBlock P9是“mouse” |
表4:例2的消息步骤
在将该更新传至处理器B时,区块P12、P11、P10和P9需要新的定义。区块P1、P3和P7已在处理器B定义,因此在表4的步骤中不将它们的内容从A发送至B,即使表4的defBlock引用区块P1、P3和P7。
PID |
区块内容 |
表达 |
P1 |
“the” |
|
P2 |
“cat” |
|
P3 |
“ate” |
|
P4 |
“dog” |
|
P5 |
P1、P2 |
“the cat” |
P6 |
P5、P3 |
“the cat ate” |
P7 |
P1、P4 |
“the dog” |
P8 |
P6、P7 |
“the cat ate the dog” |
P9 |
“up” |
|
P10 |
P5、P11 |
“the cat ate up” |
P11 |
P3、P9 |
“ate up” |
P12 |
P10、P7 |
“the cat ate up the dog” |
表5:“the cat ate up the dog”的表达
在例3中,考虑例1中将“the cat ate the dog”改变至“the cat ateup the dog”的结果。表5示出新句子在处理器A的区块表达。除了新的“up”区块(P9),需要新的区块P10、P11和P12来说明改变后的区块指针。将这种改变传至处理器B可用表6所示的消息步骤来完成。
步骤 |
方向 |
消息 |
1 |
A至B |
defBlock P12是P10、P7 |
2 |
B至A |
reqBlock P10 |
3 |
A至B |
defBlock P10是P5、P11 |
4 |
B至A |
reqBlock P11 |
5 |
A至B |
defBlock P11是P3、P9 |
6 |
B至A |
reqBlock P9 |
7 |
A至B |
defBlock P9是“up” |
表6:例3的消息步骤
在将该更新传至处理器B时,需要对区块P12、P11、P10和P9作出新的定义。区块P31、P5和P7已在处理器B定义,因此在表6的步骤中不将它们的内容从A发送至B,即使表6的defBlock引用区块P3、P5和P7。
在前例中,通过避免在接收方已定义的区块的区块内容重传而提高数据传输效率。这种效率增加较佳地通过引入虚拟区块ID(vBlockId)至pBlockId映射而得以进一步增进。这种映射是可变的,因此映射至特定pBlockId的vBlockId可变。每个接收方可每入站连接保存被称为VPBCM(虚拟-物理区块连接图)的这一映射。如从下面的例子所能观察到的那样,这提供了有用的灵活度而不会牺牲使用不变区块的关键优点。
为了适应vBlockId的使用,上述示例性协议可新增如下两个额外的消息。
(3)reqRef(vBlockId)——接收方查找vBlockId以确定其关联的pBlockId并送回具有这些值的defRef。
(4)defRef(vBlockId,pBlockId)——接收方检查vBlockId是否已在接收方的VPBCM中予以定义,如有必要就分配和映射本地vBlockId。如果本地vBlockId与发送方提供的vBlockId不同,接收方保持跟踪发送方vBlockId至本地vBlockId的映射。本地vBlockId被映射至与消息中指定的pBlockId对应的本地pBlockId。如有必要,(经由reqBlock消息)从发送方请求消息中指定的pBlockId的定义。
例4-6分别对应于例1-3中vBlockId的使用。在例4中,考虑例1中使用vBlockId的句子表达。
VID |
PID |
区块内容 |
表达 |
V1V5 |
P1 |
“the” |
|
V2 |
P2 |
“cat” |
|
V3 |
P3 |
“ate” |
|
V4 |
P4 |
“dog” |
|
|
P5 |
V1、V2 |
“the cat” |
|
P6 |
P5、V3 |
“the cat ate” |
|
P7 |
V5、V4 |
“the dog” |
V0 |
P8 |
P6、P7 |
“the cat ate the dog” |
表7:“the cat ate the dog”的表达
这里,标为VID的列示出映射至本例的一些pBlockId的vBlockId。如这里所示,仅将vBlockId映射至顶层区块(即P8)的pBlockId和映射到底层区块(即P1、P2、P3、P4)的pBlockId通常是较佳的。然而,无需遵循这种惯例。
注意vBlockId至pBlockId的映射可将多个vBlockId映射至单个pBlockId(例如在本例中的V1和V5)。这允许能够通过重映射V1和/或V5独立地改变样本句子中的“the”的任一或两个实例。
在本例中,将指定的句子从处理器A发送至处理器B的消息业务可如表8所示,假设当传输开始时在处理器B尚未定义“the”、“cat”、“dog”或“ate”的区块。
步骤 |
方向 |
消息 |
1 |
A至B |
defRef V0 P8 |
2 |
B至A |
reqBlock P8 |
3 |
A至B |
defBlock P8是P6、P7 |
4 |
B至A |
reqBlock P6 |
5 |
A至B |
defBlock P6是P5、V3 |
6 |
B至A |
reqRef V3 |
7 |
A至B |
defRef V3 P3 |
8 |
B至A |
reqBlock P3 |
9 |
A至B |
defBlock P3是“ate” |
10 |
B至A |
reqBlock P5 |
11 |
A至B |
defBlock P5是V1、V2 |
12 |
B至A |
reqRef V1 |
13 |
A至B |
defRef V1 P1 |
14 |
B至A |
reqBlock P1 |
15 |
A至B |
defBlock P1是“the” |
16 |
B至A |
reqRef V2 |
17 |
A至B |
defRef V2 P2 |
18 |
B至A |
reqBlock P2 |
19 |
A至B |
defBlock P2是“cat” |
20 |
B至A |
reqBlock P7 |
21 |
A至B |
defBlock P7是V5、V4 |
22 |
B至A |
reqRef V5 |
23 |
A至B |
defRef V5 P1 |
24 |
B至A |
reqRef V4 |
25 |
A至B |
defRef V4 P4 |
26 |
B至A |
reqBlock P4 |
27 |
A至B |
defBlock P4是“dog” |
表8:例4的消息步骤
注意在步骤23,在处理器B被告知vBlockId V5引用区块P1的情形下,区块P1因步骤14-15已在处理器B作出了定义。因此,在步骤23后,不需要再次发送关联于P1的区块内容,并且一旦处理了vBlockId V4,传输结束。
在例5中,考虑例4中将“the cat ate the dog”改变至“the mouse atethe dog”的结果。
VID |
PID |
区块内容 |
表达 |
V1V5 |
P1 |
“the” |
|
|
P2 |
“cat” |
|
V3 |
P3 |
“ate” |
|
V4 |
P4 |
“dog” |
|
|
P5 |
V1、V2 |
“the mouse” |
|
P6 |
P5、V3 |
“the mouse ate” |
|
P7 |
V5、V4 |
“the dog” |
V0 |
P8 |
P6、P7 |
“the mouse ate the dog” |
V2 |
P9 |
“mouse” |
|
表9:“the mouse ate the dog”的表达
表9示出新句子在处理器A中的区块表达。这里添加新的“mouse”区块(P9),并将vBlockId V2的映射从pBlockId P2改变至pBlockId P9。注意区块P5的内容在表7和表9上相同,但区块P5因改变的V2映射而在表7和表9上代表两个不同的句子。将这种变化传至处理器B可通过表10所示的消息步骤来完成。
步骤 |
方向 |
消息 |
1 |
A至B |
defRef V2P9 |
2 |
B至A |
reqBlock P9 |
3 |
A至B |
defBlock P9是“mouse” |
表10:例5的消息步骤
由于所传输的信息仅仅是新的“mouse”区块以及哪个vBlockId应当映射至新的“mouse”区块的pBlockId的指示,因此这里传输是非常高效的。不需要如同例2那样传播“数据结构上”的区块指针的变化。
在例6中,讨论例4中将“the cat ate the dog”改变至“the cat ate up the dog”的结果。
VID |
PID |
区块内容 |
表达 |
V1V5 |
P1 |
“the” |
|
V2 |
P2 |
“cat” |
|
V3 |
P3 |
“ate” |
|
V4 |
P4 |
“dog” |
|
|
P5 |
V1、V2 |
“the cat” |
|
P6 |
P5、V3 |
“the cat ate” |
|
P7 |
V5、V4 |
“the dog” |
|
P8 |
P6、P7 |
“the cat ate the dog” |
V5 |
P9 |
“up” |
|
|
P10 |
P5、P11 |
“the cat ate up” |
|
P11 |
V3、V5 |
“ate up” |
V0 |
P12 |
P10、P7 |
“the cat ate up the dog” |
表11:“the cat ate up the dog”的表达
表11示出新句子在处理器A的区块表达。这里为“up”增加新区块P9,并针对改变的区块指针增加新区块P10、P11和P12。将这种变化发送至处理器B可通过如下所示消息步骤来完成。
步骤 |
方向 |
消息 |
1 |
A至B |
defRef V0 P12 |
2 |
B至A |
reqBlock P12 |
3 |
A至B |
defBlock P12是P10、P7 |
4 |
B至A |
reqBlock P10 |
5 |
A至B |
defBlock P10是P5、P11 |
6 |
B至A |
reqBlock P11 |
7 |
A至B |
defBlock P11是V3、V5 |
8 |
B至A |
reqRef V5 |
9 |
A至B |
defRef V5 P9 |
10 |
B至A |
reqBlock P9 |
11 |
A至B |
defBlock P9是“up” |
表12:例6的消息步骤
如前面的例子,接收方仅请求尚未定义的区块的区块定义。
B.示例性协议
将前述消息定义如下地结合在一起是很方便的。
(1)reqBlock(pBlockId)——接收方查找pBlockId并发送回具有pBlockId和关联内容的defBlock消息。
(2)defBlock(pBlockId,内容)——接收方查找其存储器中的内容以获得本地pBlockId,如有必要则分配和初始化本地区块。如果本地pBlockId不同于发送方提供的pBlockId,则接收方保持跟踪发送方pBlockId至本地pBlockId的映射。该消息中的显式pBlockId允许将其用于推数据,与仅对查询作出响应相反。
(3)reqRef(vBlockId)——接收方查找vBlockId以确定其关联的pBlockId并发送回具有这些值的defRef。
(4)defRef(vBlockId、pBlockId)——接收方检查是否已在接收方的VPBCM中定义了vBlockId,如有必要则分配和映射本地vBlockId。如果本地vBlockId不同于由发送方提供的vBlockId,则接收方保持跟踪发送方vBlockId至本地vBlockId的映射。本地vBlockId被映射至与消息中指定的pBlockId对应的本地pBlockId。如果需要,(经由reqBlock消息)从发送方请求该pBlockId的定义。
在一个实施例中,增加下列进一步的消息:
(5)deleteBlock(pBlockId)——接收方移除与指定pBlockId对应的VPBCM表项并将对与该映射关联的区块的引用计数减1,如果该引用计数已到达零,则将其释放。这确保发送节点自由地将该pBlockId重分配给具有不同内容的区块。
C.示例性协议操作
在发送方侧,当指针字段改变时,通过将该指针字段映射至相应vBlockId、确定与新指针值对应的pBlockId并随后发送指定新的vBlockId-pBlockId映射的defRef消息来进行网络更新。
例如,如果对象包含其值由指向含字符串值的字符串缓冲器的指针规定的“名称”字段,则改变该名称对应于为该字段指定新的指针值,即指向包含新名称的字符串缓冲器的指针(一般无法仅改变原始字符串缓冲器的内容,因为其内容可能与该字符串值的其它用途共享,如同现代字符串应用中经常出现的那样)。
为了传输这种改变,发送方将该字段映射至相应vBlockId,确定与新字符串值对应的pBlockId,并将具有这些值的defRef消息发送至接收方。一旦接收到该消息,接收方修改其针对该连接的VPBCM以将指定vBlockId映射至指定的pBlockId。如果不存在这样的表项,则分配VPBCM中的表项并以零为引用计数以这种形式进行初始化。如果在接收方VPBCM中具有该vBlockId的先前存在的表项,则作为改变该表项的一部分,它将与旧有pBlockId对应的接收方VPBCM表项中的引用计数减1。如果接收方没有对该pBlockId作出定义,则它可使用reqBlock消息来请求与pBlockId对应的区块的定义。
在一个实施例中,该定义由defRef消息的始发方提供。在另一实施例中,网络基础结构/交换机保持pBlockId至数据的数据库并能对该reqBlock消息作出响应。同样,发送方可对每个连接保持本地映射,其指示接收方已知的pBlockId。在这种情形下,一旦形成defRef消息,如果在接收方没有定义指定的pBlockId,则在发送defRef消息前首先将defBlock消息发送给接收方。defBlock消息指定pBlockId和该区块关联的内容。
一旦接收到defBlock消息,接收方创建与defBlock消息中指定的值对应的该pBlockId定义。在一些情形下,接收方可实现对由发送方提供的pBlockId和/或vBlockId的本地重映射。这可能必需发布一个或多个reqBlock消息以确定这些消息中pBlockId的定义。如果本地表达取决于这些表项,则接收方将对该pBlockId表项的引用增1,作为这项操作的一部分。
如果defBlock包含对未本地定义的vBlockId的引用,则它可使用reqRef消息请求vBlockId的定义,该reqRef消息同样是发送节点或网络交换基础结构能作出响应的,这与reqBlock消息处理相似。
对于在发送方也使用每次连接映射的实施例,一旦形成defBlock消息,发送方可检测包含未在接收方定义的引用的区块数据。在这种情形下,对每个这样的vBlock引用发送defRef消息并对每个这样的pBlockId引用将defBlock消息发送至接收方,这发生在发送第一defBlock消息之前。
总的来说,逻辑相邻的数据单元可表示为由pBlockId标识的区块的分层结构,退化至短数据单元的单个数据区块。结构化数据实例可通过并入实际充当指针的vBlockId来表示。这些数据实例的传输依赖于该结构化在发送方和接收方两处的一致理解。如此,接收方能重构与pBlockId对应的数据,即便它对应的是结构化数据。
当这失败时,累积误差可通过用该状态下的CRC相互核对的稽核来解决,从而使用再同步或重引导以进行恢复。另外,发送较少量的数据,由此减小未检测出比特差错的概率。
这些方法的实践不严格地取决于处理器至处理器通信的细节。处理器可在专用链路上通信,或它们可连接于还向其它处理器提供通信的网络或系统。可采用串行网络连接或并行总线连接(例如用于紧耦合的处理器)以供通信。
D.变例
在一个实施例中,接收方重构数据并遵循消息层通信的常规模型将其作为消息“值”提供给系统的其余部分。
在另一实施例中,接收方在接收方存储器中维持pBlockId至相应数据结构的映射并相应地更新存储器。例如,在之前使用例子中更新vBlockId映射以改变对象名称可通过vBlockId映射至接收方存储器中的对象中的字段,使其更新以具有与新pBlockId对应的值,即直接改变该接收方对象的名称。在这种情形下,该接收方对象典型为发送方相应对象的代理,反之亦然。在本实施例的变例中,接收方依照不变区块从内部维持其存储器状态,如在2008年1月25日提交的本发明人的题为“分层不变内容可寻址存储器处理器(HierarchicalImmutable Content-Addressable Memory Processor)”的美国专利申请12/011,311中描述的那样,该文献全篇地援引包含于此。在这种情况下,在网络上接收到的改变和对接收方存储器状态作出的改变之间映射是直接的。
同样,在发送方,网络控制器可通过将数据转换成如上所述的区块和区块Id来支持结构化消息的传输,从而提供与常规网络控制器相似但支持结构化数据的服务接口。在这种情形下,需要发送方目录将区块单元映射至区块Id。尤其,在基本数据情形下,要通信的数据元位于要在其上发送数据的连接的发送方目录中,也就是定位与该数据元对应的表项。该表项指定区块ID以用于发送。随后取代数据发送区块Id。如果数据包含指针,则该目录中的映射映射至与数据对应的表项,其中每个指针字段由指针的相应区块Id代替。如果没有表项对应于该区块,则产生和发送指示所分配的区块Id及其关联内容的区块定义消息。该过程递归地进行。也就是说,如果原始区块包含指针,则必须在目录中确定与每个指针对应的区块Id,因此在传输原始区块定义前首先传输该指针的定义及其关联区块Id(以避免接收方使用reqBlock的回调(callback)行为)。
例如,下表13示出为避免接收方回调而使用上述方法对例1句子的传输步骤的顺序。
步骤 |
方向 |
消息 |
1 |
A至B |
defBlock P1是“the” |
2 |
A至B |
defBlock P2是“cat” |
3 |
A至B |
defBlock P5是P1、P2 |
4 |
A至B |
defBlock P3是“ate” |
5 |
A至B |
defBlock P6是P5、P3 |
6 |
A至B |
defBlock P4是“dog” |
7 |
A至B |
defBlock P7是P1、P4 |
8 |
A至B |
defBlock P8是P6、P7 |
表13:例1的消息步骤,避免了回调
这里,通过以使区块中的任意指针指向之前发送的区块的顺序将区块从A发送至B而避免接收方回调。
在另一实施例中,网络控制器可被告知存储器对象的改变并自动将这种改变转换成对应的消息。例如,可确定对象名称的变化对应于改变vBlockId-pBlockId映射,并用适宜值自动产生该消息。同样,如果同一对象的几何描述被更新,则发送方尝试将该更新发送给接收方,可能产生一个defBlock消息(或若干个),因为下游没有定义该修正的区块Id。(可能是因为例如另一代理包含该描述)。
在本实施例的变例中,主系统在不变区块结构中表示处于其内部状态下的对象,如在2008年1月25日提交的本发明人的题为“分层不变内容可寻址存储器处理器(Hierarchical Immutable Content-Addressable MemoryProcessor)(HICAMP)”的美国专利申请12/011,311中描述的那样。这允许从内部状态变化直接映射至vBlockId和pBlockId。在这种情形下,连接VPBCM实质为远端节点VPBIM的本地代理(它是对远端节点存储器的虚拟-物理区块ID映射)。通过每个节点都实现HICAMP存储器架构,如上所述的通信提供了在不同节点的多个存储器控制器之间进行协调的手段以提供HICAMP节点的高效成簇操作。
接收方可保持与连接关联的零个或多个根vBlockId,通常在建立连接时指定。这些vBlockId在该连接的VPBCM映射中具有相应表项。由连接维持的所有其它对象从这些根直接或间接地引用。在映射至网络控制器中的对象状态的情形下,根vBlockId对应于作为在两通信节点之间建立连接的一部分创建的顶层代理对象。
可对输入处理器指定依照数据大小的限额,限制由其创建的数据量,防止远端节点使用接收节点中过度的存储器量。这种限制可依照新的区块或依照逻辑区块,即发送中的值的逻辑大小。也可基于数据类型限制任意值的大小。
E.引用计数和区块解除分配
较佳地,采用引用计数来判断那些不变区块正在使用(即具有一个或多个引用)以及那些区块不被使用(即没有引用)。
每连接VPBCM中的每个表项的引用计数反映了被VPBCM中的其它表项引用的次数,如果它不是根表项的话。因此,VPBCM表项不被释放,直到它不被引用为止,并且只要它出现在作为该连接的一部分的对象中,它就被引用。
如果区块被释放,关联的VPBCM表项被无效的并在上游发送deleteBlock(删除块)消息,致使上游节点从其映射清空该表项。典型地,区块至少由其一个字段中包含该值的代理对象引用,因此只要如此该区块就不被释放。此外,由于网络输入处理器创建对其正在接收的当前区块的引用,所接收的区块被引用直到其被写至某一对象为止。在非根区块的情形下,引用所接收的该区块的后续区块被接收,本地区块也是如此。
如果连接被重置,代理的再同步致使区块状态的自动再同步。具体地说,对该连接上使用的每个区块发送defBlock操作。
F.带宽分析
思考需要发送多少字节以改变数据结构中的一个字节,就能理解由这些方法提供的显著优点。在常规方法中,发送数据结构的单字节更新所需的数据量常常是无限制的。根据上述方法,传输要求可以B的数量级,其中B是区块大小,因为能通过将修正后的区块与相关vBlockId的重映射一起发送而传输更新(如同例5)。
对于N区块数据结构,假设数据结构是树形组织(如例2),即使在不采用vBlockId至pBlockId映射的情形下,传输要求也将是B*log(N)的数量级。这里log(N)因数来自数据结构的深度,由于在这种情况下一个指针变化(以及关联区块变化)将发生在数据结构的每个层上。
G.临时块ID
在存在中央(主)节点和外围(从)节点的情况下,区块Id空间可选择地分成正常区块Id和暂时区块Id。中央节点在分配时仅使用正常区块Id。外围处理器分配具有暂时区块Id的新区块(并使用暂时虚拟区块Id)。当外围处理器创建新状态或修改已有状态从而必须分配新区块时,它对每个这样的区块使用暂时区块Id。当在某些状态下实例化新指针实例时,外围处理器也可使用暂时vBlockId。外围处理器随后将该更新发送给中央处理器,中央处理器随后依照正常区块Id将更新反射回每个外围处理器。更新发起外围处理器则通过这些区块和由中央处理器指定的V-P映射更新其状态。结果,外围处理器结束于与由中央处理器分配的那些相同的pBlockId,因此不需要pBlockId的本地映射。
此外,一旦接收到更新/将其反射回外围处理器,就更新该外围处理器的本地状态,以使其不再引用暂时区块Id,致使其引用计数为零因此自动释放之。因此,外围处理器可使其状态立即更新并随后并发/异步地执行与中央节点的这种相互作用以转换区块Id分配,从而与中央节点同步。此外,所需暂时区块的数目取决于每个外围处理器的可处于以这种形式更新的进程中的区块数目,其相对于整个存储器状态通常处于小的百分比。正常和暂时区块Id之间的区块Id比较的任何使用可在硬件中检测到,因此在等同于区块内容比较的情形下,它可以决定不依赖于区块Id比较。
通过这种中央区块Id分配,可使成簇的处理器共享由区块Id索引的共同的系统存储器,其中每个处理器潜在地高速缓冲区块以快速响应。在这种情形下,在该系统存储器中具有逐处理器区域,用于该处理器分配的暂时区块。在这种配置中,系统分布在控制和数据高速缓冲层,但使用共同的主存储器,避免处理器之间状态的完全复制。此外,可仅通过暂时区块Id将更新从外围处理器传至中央处理器,假设内容是中央处理器可从其系统存储器中的位置获得的。这种配置也适用于内核数目超出在常规共享存储器层实现同步的多核处理器芯片。
作为上述内容的一个变形,外围处理器也可替代地通过一些独立表达方式产生更新,其不必将区块发送至中央处理器,而中央处理器随后以区块形式和如上所述的协议返回。然而,该变形意味着区块Id无法用来减小从外围处理器向中央处理器发送更新的通信量。
系统层区块ID可应用于共享的处理器存储器或独立的处理器存储器。共享的处理器存储器的使用(与本地高速缓存结合以提高速度)能提供对存储器资源更为高效的使用。独立处理器存储器的使用可提高带宽和故障容限。
H.多存储器栈
多处理器系统的系统存储器可选择地分割成k个栈,每个栈具有一个存储器控制器。映射至k个栈其中一个的区块内容存在散列函数。当处理器需要创建新区块时,其创建如集中式方案中所提及的暂时区块,但其随后与第i个存储器控制器通信,如需要的区块内容的散列所指定的那样。每个存储器控制器被分配予pBlockId空间的不相交区划以使其能不与其它存储器控制器冲突地对区块分配一pBlockId。这种分割也允许处理器将pBlockId映射至关联的存储器控制器以读出该区块。这种方案允许多存储器栈/控制器按比例缩放该系统并保留所需的区块重复抑制,而不需要在一般方案的处理器之间进行pBlockId的转换映射。
I.多区块数据的重复抑制和规范表示
区块重复抑制提高了数据存储和传输的效率。因此,制定避免区块重复的惯例是优选的。回到前面的例子,假设处理器A将“cat”区块发送给已定义“cat”区块的处理器B。在这种情况下,处理器B使用在数据结构中已有的“cat”区块的ID,它是处理器B响应A的传输而构造的。处理器B也保持跟踪处理器A对“cat”使用的ID,因此能避免对该ID的定义超过一次的请求。在这种情况下,将区块视为内容标识的(即由内容标识而不是由ID标识)是有帮助的。从这个观点来看,例如保持跟踪给予“cat”区块的各个全局和/或局部ID。由于区块的唯一性,不会因为用其内容来标识区块而引入岐义。
为了向多区块数据结构提供重复抑制的优点,较佳地定义确保唯一表达的多区块数据的规范形式。例如,在具有3字符区块的系统中,“abcde”可使用区块“abc”和“de”或使用区块“ab”和“cde”来表示。为了消除这种岐义,可强加规范形式。例如,有向无环图中的每个层可能需要在向下的一层(即离根部更远的一层)添加任何东西前从左向右完全填充。此外,可能要求数据区块尽量被数据完全占据,因此最多存在一个部分填满的数据区块。该部分填满的数据区块(如果有的话)要求处于其数据结构的结尾处。也可采用强制多区块数据的唯一表达的任意其它方式。