Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<mxfile host="app.diagrams.net">
<diagram name="AoS Layout" id="aos-layout">
<mxGraphModel dx="1000" dy="600" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />

<mxCell id="title" value="AoS 布局:每个元素的 x,y,z,r,g,b 紧挨在一起(24 字节)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;fontSize=16;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="80" y="30" width="500" height="30" as="geometry" />
</mxCell>

<!-- Vertex 0 -->
<mxCell id="v0x" value="x₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="80" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v0y" value="y₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="130" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v0z" value="z₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="180" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v0r" value="r₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="230" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v0g" value="g₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="280" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v0b" value="b₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="330" y="80" width="50" height="40" as="geometry" />
</mxCell>

<!-- Vertex 1 -->
<mxCell id="v1x" value="x₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="380" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v1y" value="y₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="430" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v1z" value="z₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="480" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v1r" value="r₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="530" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v1g" value="g₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="580" y="80" width="50" height="40" as="geometry" />
</mxCell>
<mxCell id="v1b" value="b₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="630" y="80" width="50" height="40" as="geometry" />
</mxCell>

<!-- Legend -->
<mxCell id="legend_g" value="坐标数据(热路径)" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=11;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="200" y="145" width="130" height="28" as="geometry" />
</mxCell>
<mxCell id="legend_r" value="颜色数据(冷路径)" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=1;fillColor=#FFCDD2;fontSize=11;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="370" y="145" width="130" height="28" as="geometry" />
</mxCell>

</root>
</mxGraphModel>
</diagram>
</mxfile>
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,7 @@ Python 和 Java 这类语言把内存管理彻底抽象掉了,程序员基本

这个金字塔结构的核心设计思想叫做**局部性原理**(Principle of Locality)。局部性分两种:**时间局部性**指的是如果一个数据刚被访问过,那它很可能会在不久之后再次被访问;**空间局部性**指的是如果一个数据被访问了,那它附近地址的数据很可能也会被访问。Cache 的所有设计决策——缓存行的大小、预取策略、替换策略——全都是围绕这两个局部性来的。我们可以用一张简图来直观感受这个金字塔:

```mermaid
graph TD
subgraph "越往上越快、越小、越贵;越往下越慢、越大、越便宜"
Reg["<b>寄存器</b><br/>~1 周期 | 容量: ~数百字节"]
L1["<b>L1 Cache</b><br/>~3-4 周期 | 容量: 32-64 KB"]
L2["<b>L2 Cache</b><br/>~10-14 周期 | 容量: 256 KB-1 MB"]
L3["<b>L3 Cache</b><br/>~30-50 周期 | 容量: 数 MB-数十 MB"]
DRAM["<b>主存 DRAM</b><br/>~100-300 周期 | 容量: GB 级"]
Disk["<b>SSD/HDD</b><br/>~微秒/毫秒 | 容量: TB 级"]
end
Reg ~~~ L1 ~~~ L2 ~~~ L3 ~~~ DRAM ~~~ Disk
```
![存储器层次结构金字塔示意](./02-memory-hierarchy.drawio)

你可以在 Linux 上用 `lscpu` 命令查看自己机器的 Cache 配置,输出的 `L1d cache`、`L2 cache`、`L3 cache` 那几行就是你的 CPU 实际情况。接下来我们一层一层往下拆。

Expand Down Expand Up @@ -294,24 +283,9 @@ typedef struct {

对比一下两者在内存中的布局差异:

```mermaid
graph LR
subgraph "AoS 布局:每个元素的 x,y,z,r,g,b 紧挨在一起(24 字节)"
A0["x0 y0 z0 r0 g0 b0"]
A1["x1 y1 z1 r1 g1 b1"]
A2["x2 y2 z2 r2 g2 b2"]
A0 --> A1 --> A2
end
```
![AoS 内存布局](./02-aos-layout.drawio)

```mermaid
graph LR
subgraph "SoA 布局:所有 x 连续,所有 y 连续,以此类推"
SX["连续的 x<br/>x0 x1 x2 x3 x4 ..."]
SY["连续的 y<br/>y0 y1 y2 y3 y4 ..."]
SZ["连续的 z<br/>z0 z1 z2 z3 z4 ..."]
end
```
![SoA 内存布局](./02-soa-layout.drawio)

如果你的热路径只处理坐标 `x`、`y`、`z`,而不碰颜色 `r`、`g`、`b`,那 SoA 的优势就非常明显了——你连续遍历 `x[0]`、`x[1]`、`x[2]`……数据在内存里完全连续,Cache 命中率接近 100%。而 AoS 的情况下,每访问一个 `x` 都会顺带把同一结构体里的 `y`、`z`、`r`、`g`、`b` 也拉进 Cache(因为它们在同一条缓存行上),但我们暂时用不到颜色数据,这些空间就浪费了。

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<mxfile host="app.diagrams.net">
<diagram name="Memory Hierarchy" id="memory-hierarchy">
<mxGraphModel dx="1200" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />

<!-- Title -->
<mxCell id="title" value="内存层次结构金字塔" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;fontSize=20;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="200" y="20" width="300" height="35" as="geometry" />
</mxCell>

<!-- Registers -->
<mxCell id="reg" value="&lt;b&gt;寄存器&lt;/b&gt;&lt;br&gt;~1 周期 | ~数百字节" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#B71C1C;strokeWidth=2;fillColor=#FFCDD2;fontSize=14;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="300" y="70" width="180" height="50" as="geometry" />
</mxCell>

<!-- L1 -->
<mxCell id="l1" value="&lt;b&gt;L1 Cache&lt;/b&gt;&lt;br&gt;~3-4 周期 | 32-64 KB" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#C62828;strokeWidth=2;fillColor=#EF9A9A;fontSize=14;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="270" y="135" width="240" height="50" as="geometry" />
</mxCell>

<!-- L2 -->
<mxCell id="l2" value="&lt;b&gt;L2 Cache&lt;/b&gt;&lt;br&gt;~10-14 周期 | 256 KB - 1 MB" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#E65100;strokeWidth=2;fillColor=#FFCC80;fontSize=14;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="230" y="200" width="320" height="50" as="geometry" />
</mxCell>

<!-- L3 -->
<mxCell id="l3" value="&lt;b&gt;L3 Cache&lt;/b&gt;&lt;br&gt;~30-50 周期 | 数 MB - 数十 MB" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#F9A825;strokeWidth=2;fillColor=#FFF59D;fontSize=14;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="190" y="265" width="400" height="50" as="geometry" />
</mxCell>

<!-- DRAM -->
<mxCell id="dram" value="&lt;b&gt;主存 DRAM&lt;/b&gt;&lt;br&gt;~100-300 周期 | GB 级" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=2;fillColor=#A5D6A7;fontSize=14;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="150" y="330" width="480" height="50" as="geometry" />
</mxCell>

<!-- Disk -->
<mxCell id="disk" value="&lt;b&gt;SSD / HDD&lt;/b&gt;&lt;br&gt;~微秒 / 毫秒 | TB 级" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#1565C0;strokeWidth=2;fillColor=#90CAF9;fontSize=14;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="110" y="395" width="560" height="50" as="geometry" />
</mxCell>

<!-- Left annotation: faster/smaller -->
<mxCell id="left_label" value="快&lt;br&gt;↑&lt;br&gt;小&lt;br&gt;↑&lt;br&gt;贵" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;fontSize=13;fontStyle=1;fontColor=#B71C1C;rotation=0;" vertex="1" parent="1">
<mxGeometry x="30" y="130" width="50" height="250" as="geometry" />
</mxCell>

<!-- Right annotation: slower/larger -->
<mxCell id="right_label" value="慢&lt;br&gt;↓&lt;br&gt;大&lt;br&gt;↓&lt;br&gt;便宜" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;fontSize=13;fontStyle=1;fontColor=#1565C0;" vertex="1" parent="1">
<mxGeometry x="700" y="130" width="50" height="250" as="geometry" />
</mxCell>

</root>
</mxGraphModel>
</diagram>
</mxfile>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<mxfile host="app.diagrams.net">
<diagram name="SoA Layout" id="soa-layout">
<mxGraphModel dx="1000" dy="600" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />

<mxCell id="title" value="SoA 布局:所有 x 连续,所有 y 连续,以此类推" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;fontSize=16;fontStyle=1;" vertex="1" parent="1">
<mxGeometry x="100" y="20" width="460" height="30" as="geometry" />
</mxCell>

<!-- x array -->
<mxCell id="xl" value="x[]" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=2;fillColor=#E8F5E9;fontSize=14;fontStyle=1;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="80" y="70" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="x0" value="x₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="130" y="70" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="x1" value="x₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="180" y="70" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="x2" value="x₂" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="230" y="70" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="xd" value="x₃ x₄ ..." style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=12;align=center;verticalAlign=middle;dashed=1;" vertex="1" parent="1">
<mxGeometry x="280" y="70" width="100" height="35" as="geometry" />
</mxCell>

<!-- y array -->
<mxCell id="yl" value="y[]" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=2;fillColor=#E8F5E9;fontSize=14;fontStyle=1;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="80" y="115" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="y0" value="y₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="130" y="115" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="y1" value="y₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="180" y="115" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="y2" value="y₂" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="230" y="115" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="yd" value="y₃ y₄ ..." style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=12;align=center;verticalAlign=middle;dashed=1;" vertex="1" parent="1">
<mxGeometry x="280" y="115" width="100" height="35" as="geometry" />
</mxCell>

<!-- z array -->
<mxCell id="zl" value="z[]" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=2;fillColor=#E8F5E9;fontSize=14;fontStyle=1;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="80" y="160" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="z0" value="z₀" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="130" y="160" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="z1" value="z₁" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="180" y="160" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="z2" value="z₂" style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=13;align=center;verticalAlign=middle;" vertex="1" parent="1">
<mxGeometry x="230" y="160" width="50" height="35" as="geometry" />
</mxCell>
<mxCell id="zd" value="z₃ z₄ ..." style="rounded=0;whiteSpace=wrap;html=1;strokeColor=#2E7D32;strokeWidth=1;fillColor=#C8E6C9;fontSize=12;align=center;verticalAlign=middle;dashed=1;" vertex="1" parent="1">
<mxGeometry x="280" y="160" width="100" height="35" as="geometry" />
</mxCell>

</root>
</mxGraphModel>
</diagram>
</mxfile>
Loading
Loading