# G.3 深入探讨向量存储系统
<!-- source: p1102 -->

要维持每时钟周期取出或存入一个字的启动速率，存储系统就必须能够以这一速率提供或接收数据。正如第 4 章所述，通常的做法是将访问分散到多个独立存储体。大量存储体有助于处理按行或按列访问数据的向量加载、存储。

所需访问速率与存储体访问时间，决定了需要多少个存储体才能避免停顿。下面的例子说明这些时序在向量处理器中如何配合。

**例题** 假设从字节地址 136 开始读取一个含 64 个元素的向量，一次存储器访问耗时 6 个时钟周期。要支持每周期读取一个元素，需要多少个存储体？各存储体收到哪些地址？不同元素何时到达 CPU？

**解答** 每次访问耗时 6 个周期，因此至少需要 6 个存储体；不过，我们希望存储体数为 2 的幂，故选择 8 个。图 G.7 给出一个具有 8 个存储体、访问延迟为 6 个时钟周期的系统中，最初几组访问的时序。

<!-- source: p1103 -->

| 周期编号 | 存储体 0 | 存储体 1 | 存储体 2 | 存储体 3 | 存储体 4 | 存储体 5 | 存储体 6 | 存储体 7 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| 0 | | 136 | | | | | | |
| 1 | | 忙 | 144 | | | | | |
| 2 | | 忙 | 忙 | 152 | | | | |
| 3 | | 忙 | 忙 | 忙 | 160 | | | |
| 4 | | 忙 | 忙 | 忙 | 忙 | 168 | | |
| 5 | | 忙 | 忙 | 忙 | 忙 | 忙 | 176 | |
| 6 | | | 忙 | 忙 | 忙 | 忙 | 忙 | 184 |
| 7 | 192 | | | 忙 | 忙 | 忙 | 忙 | 忙 |
| 8 | 忙 | 200 | | | 忙 | 忙 | 忙 | 忙 |
| 9 | 忙 | 忙 | 208 | | | 忙 | 忙 | 忙 |
| 10 | 忙 | 忙 | 忙 | 216 | | | 忙 | 忙 |
| 11 | 忙 | 忙 | 忙 | 忙 | 224 | | | 忙 |
| 12 | 忙 | 忙 | 忙 | 忙 | 忙 | 232 | | |
| 13 | | 忙 | 忙 | 忙 | 忙 | 忙 | 240 | |
| 14 | | | 忙 | 忙 | 忙 | 忙 | 忙 | 248 |
| 15 | 256 | | | 忙 | 忙 | 忙 | 忙 | 忙 |
| 16 | 忙 | 264 | | | 忙 | 忙 | 忙 | 忙 |
{#fig-G.7 .wide .expand num="G.7" caption="按存储体编号和访问开始时隙列出的存储器字节地址。每个存储体在访问开始时锁存元素地址，随后忙碌 6 个时钟周期，再把值返回 CPU。CPU 每周期只能提供一个新地址、接收一个数据项，因此无法使全部 8 个存储体始终忙碌。"}

<!-- source: p1102 -->

真实存储体的时序通常分为**访问延迟**和**存储体周期时间**（也称存储体忙时）两个部分。访问延迟，是地址到达存储体之后，直到存储体返回数据值的时间；忙时则是存储体被一个请求占用的时间。访问延迟会增加从存储器读取向量的启动开销。总存储器延迟还包括地址和数据在 CPU 与存储体之间穿过流水化互连网络的时间。存储体忙时决定存储系统的有效带宽，因为在该忙时结束之前，处理器不能向同一存储体发出第二个请求。

前例使用的简单非流水化 SRAM 存储体，访问延迟与忙时大致相同。对于流水化 SRAM 存储体，访问延迟大于忙时，因为每个元素的访问只占用存储体流水线的一个阶段。对于 DRAM 存储体，访问延迟通常短于忙时，因为 DRAM 在破坏性读取后，需要额外时间恢复读出的值。<!-- source: p1103 -->对于支持同时进行多次向量访问，或允许向量加载、存储采用非顺序访问的存储系统，存储体数应大于最低要求，否则就会发生存储体冲突。

如果步长与存储体数互质，并且存储体数量足以避免单位步长访问发生冲突，那么单条向量访存指令内部就不会发生存储体冲突。

在没有存储体冲突时，多字步长与单位步长的访问速率相同。如果存储体数超过避免步长为 1 时发生停顿所需的最低数量，就能降低某些其他步长下的停顿频率。例如，64 个存储体配合步长 32 时，每隔一次访问才停顿一次，而非每次访问都停顿。若原来步长为 8、存储体数为 16，则每隔一次访问停顿一次；改用 64 个存储体后，步长 8 每八次访问才停顿一次。多个存储器流水线和／或多个处理器共享同一存储系统时，也需要更多存储体来避免冲突。即使只有一条存储器流水线，<!-- source: p1104 -->前一条指令的最后几个元素与后一条指令的最初几个元素之间，也可能在单位步长访问中发生存储体冲突；增加存储体数可以降低此类指令间冲突的概率。2011 年，大多数向量超级计算机已将每个 CPU 的访问分散到数百个存储体。非单位步长访问仍可能出现存储体冲突，因此程序员通常尽量选择单位步长访问。

> **译注：** 上段给出的停顿频率还取决于存储体忙时，原文没有为这些步长示例另行说明忙时条件。例如，若继续采用前例的 6 周期忙时，64 个存储体、步长 8 会循环访问 8 个不同存储体，单条连续访存序列不必每八次停顿一次。

现代超级计算机可能有数十个 CPU，每个 CPU 又有多条存储器流水线，连接到数千个存储体。为每一条流水线与每一个存储体分别提供专用通路并不现实，因此通常采用多级交换网络将两者连接起来。当不同向量访问争用同一网络通路时，交换网络可能发生拥塞，使存储系统出现额外停顿。
