Skip to content

Commit d2f74f9

Browse files
committed
refactor(arch): deepen architecture for testability and clarity
Major changes: - Create CONTEXT.md domain glossary for AI navigability - Extract test utilities from .cpp to .hpp headers: - vector_reserve.hpp: CountingAllocator template - compile_time.hpp: constexpr/consteval utilities - ranges_utils.hpp: ranges vs loops comparison functions - Add simd_allocator alias for clearer SIMD-specific naming - Remove backward compatibility layer from core.hpp: - Delete using declarations in hpc::memory and hpc::concurrency - Update all references to use hpc::core::CACHE_LINE_SIZE Benefits: - Tests now include headers instead of source files - Single source of truth for platform constants - Clearer namespace boundaries - Improved AI-assisted development support All 65 tests pass in debug and ASAN builds.
1 parent 3277e4e commit d2f74f9

20 files changed

Lines changed: 734 additions & 425 deletions

File tree

CONTEXT.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Domain Glossary
2+
3+
本文档定义 C++ 高性能指南项目的核心领域术语,统一中英文表达。
4+
5+
## Memory Optimization / 内存优化
6+
7+
### cache-line alignment / 缓存行对齐
8+
数据对齐到 CPU 缓存行边界(通常 64 字节,某些 ARM 系统为 128 字节)。
9+
目的:避免跨缓存行访问导致的性能下降。
10+
11+
### false sharing / 伪共享
12+
多线程访问同一缓存行的不同变量时,由于缓存一致性协议导致的性能下降。
13+
解决方案:使用缓存行填充(padding)将变量隔离到不同缓存行。
14+
15+
### AOS/SOA / 结构数组 vs 数组结构
16+
- **AOS (Array of Structures)**: `struct { float x, y, z; } particles[N]`
17+
- **SOA (Structure of Arrays)**: `struct { float x[N], y[N], z[N]; } particles`
18+
19+
SOA 布局更利于 SIMD 向量化,AOS 布局更符合面向对象思维。
20+
21+
### memory alignment / 内存对齐
22+
数据地址是其大小的整数倍。对齐访问通常比非对齐访问更快。
23+
24+
### prefetch / 预取
25+
在数据实际使用前将其加载到缓存,隐藏内存延迟。
26+
27+
## Concurrency / 并发
28+
29+
### lock-free / 无锁
30+
不使用互斥锁的并发数据结构,通过原子操作实现线程安全。
31+
特点:即使某个线程被挂起,其他线程仍能继续执行。
32+
33+
### memory ordering / 内存序
34+
原子操作的内存可见性顺序:
35+
- `relaxed`: 无同步,仅保证原子性
36+
- `acquire/release`: 建立同步点
37+
- `seq_cst`: 顺序一致性(最强保证)
38+
39+
### SPSC / MPMC
40+
- **SPSC (Single Producer Single Consumer)**: 单生产者单消费者队列
41+
- **MPMC (Multiple Producer Multiple Consumer)**: 多生产者多消费者队列
42+
43+
SPSC 实现更简单,性能更高;MPMC 更通用但实现复杂。
44+
45+
### atomic / 原子操作
46+
不可分割的操作,要么完全执行,要么完全不执行。
47+
C++ 中通过 `std::atomic` 模板提供。
48+
49+
### spinlock / 自旋锁
50+
线程在获取锁失败时循环等待(忙等待),而不是让出 CPU。
51+
适用于短时间持锁场景。
52+
53+
## SIMD / 单指令多数据
54+
55+
### SIMD (Single Instruction Multiple Data)
56+
一条指令同时处理多个数据元素。
57+
x86 平台:SSE (128-bit), AVX (256-bit), AVX-512 (512-bit)
58+
ARM 平台:NEON (128-bit)
59+
60+
### vectorization / 向量化
61+
编译器自动或手动使用 SIMD 指令优化循环。
62+
- 自动向量化:编译器分析循环并生成 SIMD 代码
63+
- 手动向量化:使用 intrinsics 或 SIMD 包装库
64+
65+
### intrinsic
66+
编译器提供的底层函数,直接映射到特定 CPU 指令。
67+
例:`_mm_add_ps` 对应 SSE 的 addps 指令。
68+
69+
### SIMD width / 向量宽度
70+
一次 SIMD 操作处理的数据量:
71+
- SSE: 4 个 float (128-bit)
72+
- AVX: 8 个 float (256-bit)
73+
- AVX-512: 16 个 float (512-bit)
74+
75+
## Build System / 构建系统
76+
77+
### preset-driven build / 预设驱动构建
78+
使用 CMakePresets.json 统一构建配置,确保本地和 CI 环境一致。
79+
80+
### sanitizer / 消毒器
81+
运行时检测工具,发现未定义行为和内存错误:
82+
- **ASAN (AddressSanitizer)**: 检测内存错误(越界、释放后使用等)
83+
- **TSAN (ThreadSanitizer)**: 检测数据竞争
84+
- **UBSAN (UndefinedBehaviorSanitizer)**: 检测未定义行为
85+
- **MSAN (MemorySanitizer)**: 检测未初始化内存读取
86+
87+
### header-only library / 仅头文件库
88+
只需包含头文件即可使用的库,无需编译链接。
89+
优点:集成简单;缺点:可能增加编译时间。
90+
91+
## Performance Measurement / 性能测量
92+
93+
### benchmark / 基准测试
94+
测量代码执行时间的标准化方法。
95+
关键要素:预热、多次运行、统计中位数/百分位数。
96+
97+
### flame graph / 火焰图
98+
可视化程序执行时间分布的工具,显示调用栈和时间占比。
99+
100+
### cache miss / 缓存未命中
101+
CPU 在缓存中未找到需要的数据,必须从主内存加载。
102+
缓存未命中是性能瓶颈的常见原因。
103+
104+
### throughput / 吞吐量
105+
单位时间内处理的操作数或数据量。通常以 ops/sec、MB/s 表示。
106+
107+
### latency / 延迟
108+
单个操作从开始到完成的时间。通常以纳秒、微秒表示。

examples/02-memory-cache/include/memory_utils.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ namespace hpc::memory {
2828
// 使用核心头文件中的常量
2929
//------------------------------------------------------------------------------
3030

31-
// CACHE_LINE_SIZE 和 PAGE_SIZE 已通过 hpc/core.hpp 的 using 声明导入
31+
// CACHE_LINE_SIZE 和 PAGE_SIZE 来自 hpc::core 命名空间
3232

3333
//------------------------------------------------------------------------------
3434
// Aligned Memory Allocation
@@ -81,7 +81,7 @@ using aligned_unique_ptr = std::unique_ptr<T, AlignedDeleter>;
8181
* @brief Create aligned unique pointer
8282
*/
8383
template <typename T>
84-
aligned_unique_ptr<T> make_aligned(std::size_t count, std::size_t alignment = CACHE_LINE_SIZE) {
84+
aligned_unique_ptr<T> make_aligned(std::size_t count, std::size_t alignment = hpc::core::CACHE_LINE_SIZE) {
8585
void* ptr = aligned_alloc(count * sizeof(T), alignment);
8686
if (!ptr) {
8787
throw std::bad_alloc();
@@ -96,7 +96,7 @@ aligned_unique_ptr<T> make_aligned(std::size_t count, std::size_t alignment = CA
9696
/**
9797
* @brief STL-compatible allocator with custom alignment
9898
*/
99-
template <typename T, std::size_t Alignment = CACHE_LINE_SIZE>
99+
template <typename T, std::size_t Alignment = hpc::core::CACHE_LINE_SIZE>
100100
class AlignedAllocator {
101101
public:
102102
using value_type = T;
@@ -144,7 +144,7 @@ bool operator!=(const AlignedAllocator<T, A>&, const AlignedAllocator<U, A>&) no
144144
* @brief Vector with cache-line aligned storage
145145
*/
146146
template <typename T>
147-
using aligned_vector = std::vector<T, AlignedAllocator<T, CACHE_LINE_SIZE>>;
147+
using aligned_vector = std::vector<T, AlignedAllocator<T, hpc::core::CACHE_LINE_SIZE>>;
148148

149149
//------------------------------------------------------------------------------
150150
// Cache Line Padding
@@ -154,7 +154,7 @@ using aligned_vector = std::vector<T, AlignedAllocator<T, CACHE_LINE_SIZE>>;
154154
* @brief Pad a type to cache line size to prevent false sharing
155155
*/
156156
template <typename T>
157-
struct alignas(CACHE_LINE_SIZE) CacheLinePadded {
157+
struct alignas(hpc::core::CACHE_LINE_SIZE) CacheLinePadded {
158158
T value;
159159

160160
CacheLinePadded() = default;

examples/02-memory-cache/src/false_sharing.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ struct PackedCounters {
5555
* For a convenience wrapper with common operations, see
5656
* hpc::concurrency::AlignedCounter.
5757
*/
58-
struct alignas(CACHE_LINE_SIZE) PaddedCounter {
58+
struct alignas(hpc::core::CACHE_LINE_SIZE) PaddedCounter {
5959
std::atomic<int64_t> value{0};
6060
// Padding is implicit due to alignas
6161
};
@@ -170,7 +170,7 @@ int main() {
170170

171171
std::cout << "=== False Sharing Demonstration ===\n\n";
172172

173-
std::cout << "Cache line size: " << CACHE_LINE_SIZE << " bytes\n";
173+
std::cout << "Cache line size: " << hpc::core::CACHE_LINE_SIZE << " bytes\n";
174174
std::cout << "sizeof(PackedCounters): " << sizeof(PackedCounters) << " bytes\n";
175175
std::cout << "sizeof(PaddedCounters): " << sizeof(PaddedCounters) << " bytes\n\n";
176176

examples/03-modern-cpp/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ hpc_add_example(
1212
hpc_add_example(
1313
NAME compile_time
1414
SOURCES src/compile_time.cpp
15+
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
1516
)
1617

1718
# Vector reserve example
1819
hpc_add_example(
1920
NAME vector_reserve
2021
SOURCES src/vector_reserve.cpp
2122
BENCHMARK_SOURCES bench/vector_reserve_bench.cpp
23+
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
2224
)
2325

2426
# Ranges vs loops example
2527
hpc_add_example(
2628
NAME ranges_vs_loops
2729
SOURCES src/ranges_vs_loops.cpp
2830
BENCHMARK_SOURCES bench/ranges_bench.cpp
31+
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include
2932
)

examples/03-modern-cpp/include/buffer.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,26 @@ class Buffer {
9898
inline size_t Buffer::copy_count_ = 0;
9999
inline size_t Buffer::move_count_ = 0;
100100

101+
//------------------------------------------------------------------------------
102+
// Functions demonstrating copy vs move
103+
//------------------------------------------------------------------------------
104+
105+
/**
106+
* @brief Process buffer by copy (expensive)
107+
*/
108+
inline void process_by_copy(Buffer buf) {
109+
// Do something with buf
110+
volatile char c = buf.data()[0];
111+
(void)c;
112+
}
113+
114+
/**
115+
* @brief Process buffer by const reference (no copy)
116+
*/
117+
inline void process_by_ref(const Buffer& buf) {
118+
// Do something with buf
119+
volatile char c = buf.data()[0];
120+
(void)c;
121+
}
122+
101123
} // namespace hpc::move_semantics

0 commit comments

Comments
 (0)