Skip to content

Commit ff73a64

Browse files
committed
docs: 整改中文文档站,修正路径与计时器描述
- README 修正 benchmark 二进制名(aos_soa_bench -> aos_vs_soa_bench)。 - api.md 计时器说明改述为 steady_clock 及其单调性理由(配合代码改动)。 - 新增 binary-paths 回归测试,覆盖文档引用的可执行路径。
1 parent 2594db0 commit ff73a64

10 files changed

Lines changed: 516 additions & 48 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ cmake --build build/release
5757
运行一个 benchmark:
5858

5959
```bash
60-
./build/release/examples/02-memory-cache/aos_soa_bench
60+
./build/release/examples/02-memory-cache/aos_vs_soa_bench
6161
```
6262

6363
## 常用验证命令
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import test from 'node:test'
2+
import assert from 'node:assert/strict'
3+
import fs from 'node:fs'
4+
import path from 'node:path'
5+
import { fileURLToPath } from 'node:url'
6+
7+
// Ensures executable paths referenced in the docs and README (e.g.
8+
// `./build/release/examples/02-memory-cache/aos_vs_soa_bench`) correspond to
9+
// real CMake targets. Executables are emitted flat into
10+
// build/<preset>/examples/<module>/ (there is no src/ or bench/ output
11+
// subdirectory), and benchmark targets are named `<NAME>_bench`. Both facts
12+
// drifted in the docs before after the target-naming refactor; this test runs
13+
// as part of `npm test` (CI docs job) to keep them pinned.
14+
15+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
16+
const docsRoot = path.resolve(__dirname, '..', '..') // docs/
17+
const projectRoot = path.resolve(docsRoot, '..') // repo root
18+
19+
// --- Collect real targets from examples/*/CMakeLists.txt ---------------------
20+
21+
const targets = new Set()
22+
const examplesDir = path.join(projectRoot, 'examples')
23+
24+
for (const entry of fs.readdirSync(examplesDir, { withFileTypes: true })) {
25+
if (!entry.isDirectory() || !/^[0-9][0-9]-/.test(entry.name)) continue
26+
const cmakeFile = path.join(examplesDir, entry.name, 'CMakeLists.txt')
27+
if (!fs.existsSync(cmakeFile)) continue
28+
const content = fs.readFileSync(cmakeFile, 'utf8')
29+
// hpc_add_example(NAME foo ...) → `foo`, plus `foo_bench` when
30+
// BENCHMARK_SOURCES is given. hpc_add_benchmark(NAME foo ...) → `foo`.
31+
for (const call of content.matchAll(/hpc_add_(example|benchmark)\s*\(([^)]*)\)/g)) {
32+
const [, kind, body] = call
33+
const name = /NAME\s+([A-Za-z0-9_]+)/.exec(body)?.[1]
34+
if (!name) continue
35+
targets.add(name)
36+
if (kind === 'example' && /BENCHMARK_SOURCES/.test(body)) {
37+
targets.add(`${name}_bench`)
38+
}
39+
}
40+
}
41+
42+
// --- Collect referenced binaries from docs + README --------------------------
43+
44+
const mdFiles = [path.join(projectRoot, 'README.md')]
45+
function walk(dir) {
46+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
47+
const full = path.join(dir, entry.name)
48+
if (entry.isDirectory()) walk(full)
49+
else if (entry.name.endsWith('.md')) mdFiles.push(full)
50+
}
51+
}
52+
walk(path.join(docsRoot, 'zh'))
53+
54+
const problems = []
55+
const checked = new Set()
56+
57+
for (const file of mdFiles) {
58+
const content = fs.readFileSync(file, 'utf8')
59+
const where = path.relative(projectRoot, file)
60+
61+
// Binary references: build/<preset>/examples/<module>/<binary>. The binary
62+
// token stops at whitespace/backticks, so trailing flags are not captured.
63+
for (const match of content.matchAll(
64+
/build\/(?:release|debug)\/examples\/([0-9][0-9]-[a-z-]*)\/([A-Za-z0-9_.-]+)/g
65+
)) {
66+
const [, module, binary] = match
67+
const key = `${module}/${binary}`
68+
if (checked.has(key)) continue
69+
checked.add(key)
70+
if (!targets.has(binary)) {
71+
problems.push({ key, where, reason: '无此 CMake 目标(目标已重命名?)' })
72+
}
73+
}
74+
75+
// Binaries are emitted flat into the module directory; src/ and bench/ are
76+
// source-tree directories only and never appear in output paths.
77+
for (const match of content.matchAll(
78+
/build\/(?:release|debug)\/examples\/[0-9][0-9]-[a-z-]*\/(?:src|bench)\/[A-Za-z0-9_.-]+/g
79+
)) {
80+
problems.push({ key: match[0], where, reason: '二进制路径含 src/ 或 bench/ 前缀(输出目录无此层级)' })
81+
}
82+
}
83+
84+
test('markdown binary-path references resolve to real CMake targets', () => {
85+
assert.ok(targets.size > 0, '未能从 examples/*/CMakeLists.txt 解析出任何目标——解析器坏了吗?')
86+
assert.deepEqual(
87+
problems,
88+
[],
89+
`文档引用了不存在的可执行文件路径(目标重命名/移动后文档未同步):\n${problems
90+
.map((p) => ` ${p.key} (in ${p.where}) — ${p.reason}`)
91+
.join('\n')}`
92+
)
93+
})

docs/zh/deep-dives/cmake-build-system.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
**编译优化标志。** `-O3` 启用激进优化(循环展开、向量化、内联);`-march=native` 允许编译器使用当前 CPU 的全部指令集(AVX2、FMA);`-ffast-math` 放松浮点语义以换取向量化机会。缺少这些标志的 Release 构建可能只有峰值性能的 20-30%。
88

9-
**链接时优化(LTO)。** 跨翻译单元内联、死代码消除、全局常量传播。没有 LTO,编译器只能在单个 `.cpp` 文件内优化。
9+
**链接时优化(LTO)。** 跨翻译单元内联、死代码消除、全局常量传播。没有 LTO,编译器只能在单个 `.cpp` 文件内优化。(注意:本仓库当前尚未集成 LTO,扩展方式见文末 preset 工作流一节。)
1010

1111
**调试信息与性能分析。** `-g` 生成调试符号,`RelWithDebInfo` 配置在保持 `-O2` 优化的同时保留符号信息,使 perf/VTune 等工具能将热点映射回源码行。
1212

@@ -190,7 +190,7 @@ cmake --build build/release
190190
ctest --preset=release
191191

192192
# 3. 运行 benchmark
193-
./build/release/examples/03-modern-cpp/bench/vector_reserve_bench
193+
./build/release/examples/03-modern-cpp/vector_reserve_bench
194194

195195
# 4. ASan 检测内存错误
196196
cmake --preset=asan
@@ -204,10 +204,11 @@ ctest --preset=tsan
204204

205205
# 6. 查看编译命令(IDE 集成 / 调试用)
206206
cat build/release/compile_commands.json | head -20
207-
208-
# 7. 验证 LTO 是否生效
209-
cmake --preset=release -DHPC_ENABLE_LTO=ON
210-
cmake --build build/release --verbose 2>&1 | grep -i "lto\|flto"
211207
```
212208

209+
> **关于 LTO:** 本仓库目前尚未集成链接时优化(没有 `HPC_ENABLE_LTO` 之类的开关)。
210+
> 如需启用,可在 `cmake/CompilerOptions.cmake` 中为 Release 配置添加 `-flto=auto`
211+
> (GCC/Clang)或设置 `CMAKE_INTERPROCEDURAL_OPTIMIZATION`,然后用
212+
> `cmake --build build/release --verbose 2>&1 | grep -i flto` 验证是否生效。
213+
213214
构建系统本身也是"可验证的性能工程"的一部分:相同的源码 + 相同的 preset = 相同的二进制行为,任何性能回归都可以定位到具体的代码变更而非构建配置漂移。

docs/zh/deep-dives/lock-free-queue.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ seq_cst 提供全局单一修改顺序。经典的 store buffering litmus test
8888
运行性能对比:
8989

9090
```bash
91-
./build/release/examples/05-concurrency/bench/atomic_bench
91+
./build/release/examples/05-concurrency/atomic_ordering_bench
9292
```
9393

9494
或直接运行 demo 观察三种 ordering 的计时:
@@ -237,7 +237,7 @@ OpenMP 为每个线程维护私有副本,循环结束后合并。无需手动
237237
### 线程扩展效率
238238

239239
```bash
240-
./build/release/examples/05-concurrency/bench/openmp_bench
240+
./build/release/examples/05-concurrency/openmp_basics_bench
241241
```
242242

243243
或运行 demo 观察不同线程数下的加速比:

docs/zh/deep-dives/memory-layout.md

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ inline void update_particles_soa(ParticleSOA& particles, float dt) {
8181
### 运行验证
8282
8383
```bash
84-
./build/release/examples/02-memory-cache/src/aos_vs_soa
85-
./build/release/examples/02-memory-cache/bench/aos_soa_bench
84+
./build/release/examples/02-memory-cache/aos_vs_soa
85+
./build/release/examples/02-memory-cache/aos_vs_soa_bench
8686
```
8787

8888
SOA 的优势在数据量超过 L2 缓存后尤为显著。
@@ -152,8 +152,8 @@ struct alignas(hpc::core::CACHE_LINE_SIZE) CacheLinePadded {
152152
### 运行验证
153153

154154
```bash
155-
./build/release/examples/02-memory-cache/src/alignment
156-
./build/release/examples/02-memory-cache/bench/alignment_bench
155+
./build/release/examples/02-memory-cache/alignment
156+
./build/release/examples/02-memory-cache/alignment_bench
157157
```
158158

159159
在现代 CPU(Skylake+)上对齐与非对齐差距已很小,但对齐仍是最佳实践——确保所有微架构上无性能回退。
@@ -210,8 +210,8 @@ False sharing 可以将多线程加速比从接近线性降到**负加速**。
210210
### 运行验证
211211

212212
```bash
213-
./build/release/examples/02-memory-cache/src/false_sharing
214-
./build/release/examples/02-memory-cache/bench/false_sharing_bench
213+
./build/release/examples/02-memory-cache/false_sharing
214+
./build/release/examples/02-memory-cache/false_sharing_bench
215215
```
216216

217217
在 4 线程、每线程 10M 次原子递增下,padded 版本通常比 packed 版本快数倍。
@@ -279,8 +279,8 @@ int64_t sum_list_with_prefetch(const Node* head) {
279279
### 运行验证
280280
281281
```bash
282-
./build/release/examples/02-memory-cache/src/prefetch
283-
./build/release/examples/02-memory-cache/bench/prefetch_bench
282+
./build/release/examples/02-memory-cache/prefetch
283+
./build/release/examples/02-memory-cache/prefetch_bench
284284
```
285285

286286
---
@@ -294,23 +294,23 @@ int64_t sum_list_with_prefetch(const Node* head) {
294294
cmake --preset=release && cmake --build --preset=release
295295

296296
# AOS vs SOA
297-
./build/release/examples/02-memory-cache/bench/aos_soa_bench
297+
./build/release/examples/02-memory-cache/aos_vs_soa_bench
298298

299299
# 内存对齐
300-
./build/release/examples/02-memory-cache/bench/alignment_bench
300+
./build/release/examples/02-memory-cache/alignment_bench
301301

302302
# False Sharing
303-
./build/release/examples/02-memory-cache/bench/false_sharing_bench
303+
./build/release/examples/02-memory-cache/false_sharing_bench
304304

305305
# 软件预取
306-
./build/release/examples/02-memory-cache/bench/prefetch_bench
306+
./build/release/examples/02-memory-cache/prefetch_bench
307307
```
308308

309309
支持 Google Benchmark 标准参数:
310310

311311
```bash
312-
./build/release/examples/02-memory-cache/bench/aos_soa_bench --benchmark_filter="SOA"
313-
./build/release/examples/02-memory-cache/bench/false_sharing_bench --benchmark_repetitions=5
312+
./build/release/examples/02-memory-cache/aos_vs_soa_bench --benchmark_filter="SOA"
313+
./build/release/examples/02-memory-cache/false_sharing_bench --benchmark_repetitions=5
314314
```
315315

316316
---

docs/zh/deep-dives/modern-cpp-perf.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ C++17 起,prvalue 返回保证 copy elision;NRVO(命名返回值优化)
144144
### 验证
145145

146146
```bash
147-
./build/release/examples/03-modern-cpp/bench/move_semantics_bench
147+
./build/release/examples/03-modern-cpp/move_semantics_bench
148148
```
149149

150150
Google Benchmark 输出中,move 和 emplace_back 的耗时应比 copy 低 1-2 个数量级(100 × 1MB 拷贝 ≈ 100MB memcpy)。
@@ -217,7 +217,7 @@ vec.resize(10); // capacity≥10, size=10 — 已值初始化,可下标访
217217
### 验证
218218

219219
```bash
220-
./build/release/examples/03-modern-cpp/bench/vector_reserve_bench
220+
./build/release/examples/03-modern-cpp/vector_reserve_bench
221221
```
222222

223223
---
@@ -290,7 +290,7 @@ inline auto chain_ranges_view(const std::vector<int>& input) {
290290
### 验证
291291

292292
```bash
293-
./build/release/examples/03-modern-cpp/bench/ranges_bench
293+
./build/release/examples/03-modern-cpp/ranges_vs_loops_bench
294294
```
295295

296296
观察 "Ranges (lazy sum)" 与 "Raw loop" 的耗时对比——对于纯求和场景,惰性 view 无需物化中间结果,性能应持平或略优。
@@ -310,18 +310,18 @@ cmake --build build/release
310310
./build/release/examples/03-modern-cpp/compile_time
311311

312312
# 移动语义 benchmark
313-
./build/release/examples/03-modern-cpp/bench/move_semantics_bench
313+
./build/release/examples/03-modern-cpp/move_semantics_bench
314314

315315
# 容器容量管理 benchmark
316-
./build/release/examples/03-modern-cpp/bench/vector_reserve_bench
316+
./build/release/examples/03-modern-cpp/vector_reserve_bench
317317

318318
# Ranges vs 裸循环 benchmark
319-
./build/release/examples/03-modern-cpp/bench/ranges_bench
319+
./build/release/examples/03-modern-cpp/ranges_vs_loops_bench
320320

321321
# 运行所有 benchmark(Google Benchmark 格式,可导出 JSON)
322-
./build/release/examples/03-modern-cpp/bench/move_semantics_bench --benchmark_format=json
323-
./build/release/examples/03-modern-cpp/bench/vector_reserve_bench --benchmark_format=json
324-
./build/release/examples/03-modern-cpp/bench/ranges_bench --benchmark_format=json
322+
./build/release/examples/03-modern-cpp/move_semantics_bench --benchmark_format=json
323+
./build/release/examples/03-modern-cpp/vector_reserve_bench --benchmark_format=json
324+
./build/release/examples/03-modern-cpp/ranges_vs_loops_bench --benchmark_format=json
325325
```
326326

327327
所有 benchmark 使用 Google Benchmark 框架,自动处理预热、迭代次数自适应和统计显著性。结果因硬件而异——本仓库的原则是提供可运行的验证手段,而非固定的性能数字。

docs/zh/deep-dives/simd-internals.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,19 +364,19 @@ int main() {
364364
cmake --preset=release && cmake --build --preset=release
365365

366366
# 自动向量化示例
367-
./build/release/examples/04-simd-vectorization/src/auto_vectorize
367+
./build/release/examples/04-simd-vectorization/auto_vectorize
368368

369369
# Intrinsics 示例(scalar/SSE/AVX2/AVX-512 对比)
370-
./build/release/examples/04-simd-vectorization/src/intrinsics_intro
370+
./build/release/examples/04-simd-vectorization/intrinsics_intro
371371

372372
# 运行时分发示例
373-
./build/release/examples/04-simd-vectorization/src/dispatch_example
373+
./build/release/examples/04-simd-vectorization/dispatch_example
374374

375375
# Google Benchmark 基准测试
376-
./build/release/examples/04-simd-vectorization/bench/simd_bench
376+
./build/release/examples/04-simd-vectorization/simd_bench
377377

378378
# 过滤特定测试
379-
./build/release/examples/04-simd-vectorization/bench/simd_bench --benchmark_filter="dot"
379+
./build/release/examples/04-simd-vectorization/simd_bench --benchmark_filter="dot"
380380
```
381381

382382
查看向量化报告:

docs/zh/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ ctest --preset=asan
5353
Release 构建包含所有基准测试可执行文件:
5454

5555
```bash
56-
./build/release/examples/02-memory-cache/bench/aos_soa_bench
56+
./build/release/examples/02-memory-cache/aos_vs_soa_bench
5757
```
5858

5959
输出类似:

docs/zh/guides/optimization-playbook.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ static void BM_Correct(benchmark::State& state) {
234234
```cpp
235235
namespace hpc::memory { /* 内存布局相关 */ }
236236
namespace hpc::simd { /* SIMD 相关 */ }
237-
namespace hpc::concurrent { /* 并发相关 */ }
237+
namespace hpc::concurrency { /* 并发相关 */ }
238238
namespace hpc::bench { /* benchmark 工具 */ }
239239
```
240240
@@ -261,11 +261,13 @@ namespace hpc::memory {
261261
examples/
262262
02-memory-cache/
263263
CMakeLists.txt # 调用 hpc_add_example()
264-
include/ # 公共头文件
265-
src/ # 示例源码
264+
src/ # 示例源码(依赖规范库 include/hpc/)
266265
bench/ # benchmark 源码
267266
```
268267

268+
公共头文件已提升为仓库根的规范库 `include/hpc/``hpc_headers` INTERFACE 目标),
269+
examples 只消费、不持有公共头文件,依赖方向单向。
270+
269271
benchmark 通过 `hpc_add_example()``BENCHMARK_SOURCES` 参数注册,自动链接 Google Benchmark 并注册为 CTest 测试。
270272

271273
### 格式化

0 commit comments

Comments
 (0)