Skip to content

Commit 4b39e85

Browse files
authored
Merge pull request #3 from LessUp/fix/bugs-and-architecture-improvements
fix: critical bugs, architecture improvements, and test infrastructure
2 parents 01750b5 + f45adb0 commit 4b39e85

20 files changed

Lines changed: 1050 additions & 418 deletions

.github/workflows/ci.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Continuous Integration
2-
# Validates code formatting and CUDA compilation of all targets (benchmark + tests)
2+
# Validates code formatting, CUDA compilation, and CPU-only test execution
33
#
44
# Workflow separation:
5-
# - This workflow: formatting + CUDA compile-time checks (no GPU runtime)
5+
# - This workflow: formatting + CUDA compile-time checks + CPU tests (no GPU runtime)
66
# - pages.yml: docs tests/build and GitHub Pages buildability
77
name: CI
88

@@ -58,7 +58,11 @@ jobs:
5858
- name: Build
5959
run: cmake --build build -j2
6060

61+
- name: Run CPU tests
62+
run: ctest --test-dir build -L cpu --output-on-failure
63+
6164
- name: Info
6265
run: |
6366
echo "✅ CUDA compilation successful for all targets (benchmark + tests)"
67+
echo "✅ CPU-only tests passed"
6468
echo "ℹ️ GPU runtime tests require a CUDA-capable machine"

CMakeLists.txt

Lines changed: 54 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -96,91 +96,71 @@ if(BUILD_TESTS)
9696
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
9797
FetchContent_MakeAvailable(googletest)
9898

99-
add_executable(test_sgemm tests/test_sgemm.cu)
100-
target_include_directories(test_sgemm PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
101-
target_compile_definitions(test_sgemm PRIVATE SGEMM_HAS_WMMA_TARGET=${SGEMM_HAS_WMMA_TARGET})
102-
target_link_options(test_sgemm PRIVATE -L${SGEMM_CUDA_LIBRARY_DIR})
103-
target_link_libraries(test_sgemm PRIVATE
104-
GTest::gtest_main
105-
CUDA::cudart
106-
CUDA::cublas
107-
CUDA::curand
108-
)
109-
target_compile_options(test_sgemm PRIVATE
110-
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
111-
)
99+
include(GoogleTest)
112100

113-
# 工具层测试
114-
add_executable(test_utils tests/test_utils.cu)
115-
target_include_directories(test_utils PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
116-
target_compile_definitions(test_utils PRIVATE SGEMM_HAS_WMMA_TARGET=${SGEMM_HAS_WMMA_TARGET})
117-
target_link_options(test_utils PRIVATE -L${SGEMM_CUDA_LIBRARY_DIR})
118-
target_link_libraries(test_utils PRIVATE
119-
GTest::gtest_main
120-
CUDA::cudart
121-
CUDA::cublas
122-
CUDA::curand
123-
)
124-
target_compile_options(test_utils PRIVATE
125-
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
126-
)
101+
# Include test helper functions
102+
include(cmake/SgemmTestHelpers.cmake)
127103

128-
# 性能回归测试
129-
add_executable(test_performance tests/test_performance.cu)
130-
target_include_directories(test_performance PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
131-
target_compile_definitions(test_performance PRIVATE SGEMM_HAS_WMMA_TARGET=${SGEMM_HAS_WMMA_TARGET})
132-
target_link_options(test_performance PRIVATE -L${SGEMM_CUDA_LIBRARY_DIR})
133-
target_link_libraries(test_performance PRIVATE
134-
GTest::gtest_main
135-
CUDA::cudart
136-
CUDA::cublas
137-
CUDA::curand
138-
)
139-
target_compile_options(test_performance PRIVATE
140-
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
104+
# ═══════════════════════════════════════════════════════════════
105+
# CPU-only Tests (no CUDA required)
106+
# ═══════════════════════════════════════════════════════════════
107+
108+
# Benchmark settings module test - pure C++, no CUDA dependencies
109+
sgemm_add_cpu_test(
110+
NAME test_benchmark_settings
111+
SOURCES tests/test_benchmark_settings.cpp
141112
)
142113

143-
# Benchmark 设置模块测试
144-
add_executable(test_benchmark_settings tests/test_benchmark_settings.cu)
145-
target_include_directories(test_benchmark_settings PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
146-
target_link_libraries(test_benchmark_settings PRIVATE
147-
GTest::gtest_main
148-
CUDA::cudart
149-
CUDA::cublas
114+
# Device info provider CPU tests - uses fake device properties
115+
# Compiled as .cu because it includes kernel headers with CUDA launch syntax
116+
sgemm_add_cpu_test(
117+
NAME test_device_info_cpu
118+
SOURCES tests/test_device_info_cpu.cu
150119
)
151-
target_compile_options(test_benchmark_settings PRIVATE
152-
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
120+
121+
# ═══════════════════════════════════════════════════════════════
122+
# CUDA Tests (requires CUDA device, skipped if unavailable)
123+
# ═══════════════════════════════════════════════════════════════
124+
125+
# Kernel correctness tests with property-based testing
126+
sgemm_add_cuda_test(
127+
NAME test_sgemm
128+
SOURCES tests/test_sgemm.cu
129+
CUDA_LIBRARIES CUDA::curand
130+
REQUIRES_WMMA
153131
)
154132

155-
# Kernel catalog module test
156-
add_executable(test_kernel_catalog tests/test_kernel_catalog.cu)
157-
target_include_directories(test_kernel_catalog PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
158-
target_link_libraries(test_kernel_catalog PRIVATE
159-
GTest::gtest_main
160-
CUDA::cudart
161-
CUDA::cublas
133+
# Utility layer tests (DeviceMemory, verifier RAII, etc.)
134+
sgemm_add_cuda_test(
135+
NAME test_utils
136+
SOURCES tests/test_utils.cu
137+
CUDA_LIBRARIES CUDA::curand
138+
REQUIRES_WMMA
162139
)
163-
target_compile_options(test_kernel_catalog PRIVATE
164-
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
140+
141+
# Kernel catalog module test - requires device memory and kernel launch
142+
sgemm_add_cuda_test(
143+
NAME test_kernel_catalog
144+
SOURCES tests/test_kernel_catalog.cu
145+
REQUIRES_WMMA
165146
)
166147

167-
# Device info seam test
168-
add_executable(test_device_info_seam tests/test_device_info_seam.cu)
169-
target_include_directories(test_device_info_seam PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
170-
target_link_libraries(test_device_info_seam PRIVATE
171-
GTest::gtest_main
172-
CUDA::cudart
173-
CUDA::cublas
148+
# Device info provider CUDA tests - requires real GPU for production adapter
149+
sgemm_add_cuda_test(
150+
NAME test_device_info_cuda
151+
SOURCES tests/test_device_info_cuda.cu
174152
)
175-
target_compile_options(test_device_info_seam PRIVATE
176-
$<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
153+
154+
# ═══════════════════════════════════════════════════════════════
155+
# Performance Tests (CUDA + performance label)
156+
# ═══════════════════════════════════════════════════════════════
157+
158+
# Performance regression tests
159+
sgemm_add_cuda_perf_test(
160+
NAME test_performance
161+
SOURCES tests/test_performance.cu
162+
CUDA_LIBRARIES CUDA::curand
163+
REQUIRES_WMMA
177164
)
178165

179-
include(GoogleTest)
180-
gtest_discover_tests(test_sgemm)
181-
gtest_discover_tests(test_utils)
182-
gtest_discover_tests(test_performance)
183-
gtest_discover_tests(test_benchmark_settings)
184-
gtest_discover_tests(test_kernel_catalog)
185-
gtest_discover_tests(test_device_info_seam)
186166
endif()

CONTEXT.md

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,28 @@
44

55
## 核心模块
66

7+
### Kernel Catalog 模块
8+
9+
**位置**: `src/kernels/kernel_catalog.cuh`
10+
11+
**权威元数据源** - 内核阶梯的唯一事实来源:
12+
13+
- **KernelCatalogEntry**: 完整的内核元数据
14+
- `name`: 显示名称
15+
- `type`: KernelType::Standard 或 KernelType::TensorCore
16+
- `launcher`: 启动适配器
17+
- `constraints`: 运行时约束(Tensor Core 要求、维度对齐)
18+
- **KernelConstraints**: 运行时约束描述
19+
- `requires_tensor_cores`: 是否需要 sm_70+
20+
- `dimension_alignment`: 维度对齐要求(0 = 无约束)
21+
- `requires_compute_only`: 是否使用特殊 benchmark 接口
22+
- **查询工具**: `countKernelsByType()`, `getKernelNames()`, `canRunTensorCoreKernels()`
23+
24+
**设计原则**
25+
- **单一事实源**: 新增内核只需添加一个 catalog 条目
26+
- **自描述约束**: 每个 entry 知道自己能否在给定条件下运行
27+
- **统一调度**: BenchmarkRunner 通过 catalog 迭代,无特殊分支
28+
729
### Tensor Core 模块
830

931
**位置**: `src/kernels/tensor_core_sgemm.cuh`
@@ -24,6 +46,7 @@
2446
**位置**: `src/kernels/tensor_core_benchmark.cuh`
2547

2648
Tensor Core 特有的 benchmark 功能,提供:
49+
- `canRunTensorCoreComputeOnly()` - 约束检查(与 KernelCatalog 语义一致)
2750
- `runTensorCoreComputeOnlyBenchmark()` - 纯计算路径性能测试
2851

2952
**接口设计**:只接受 `cublasHandle_t`,不依赖整个 `SGEMMBenchmark` 类,避免内核层对工具层的上穿依赖。
@@ -32,19 +55,42 @@ Tensor Core 特有的 benchmark 功能,提供:
3255

3356
**位置**: `src/utils/verify.cuh`
3457

35-
统一的验证逻辑:
36-
- `detail::compareMatricesImpl()` - 内部实现,供其他函数共享
37-
- `compareMatrices()` - 独立的矩阵比较函数
38-
- `SGEMMVerifier` - 带 cuBLAS 句柄的验证器类
58+
**统一的验证策略** - reference + comparison + tolerance policy:
59+
60+
- **VerifyResult**: 验证结果结构(pass/fail、错误指标)
61+
- **VerifyTolerance**: 容差规范(numpy-style allclose 语义)
62+
- `kStandardVerifyTolerance`: FP32 标准容差
63+
- `kTensorCoreVerifyTolerance`: Tensor Core 宽松容差
64+
- **比较函数**:
65+
- `compareMatrices()`: Host 指针比较
66+
- `compareDeviceMatrices()`: Device 指针比较
67+
- **SGEMMVerifier**: cuBLAS 参考计算适配器
68+
- `computeReference()`: 计算参考结果
69+
- `verify()`, `verifyDevice()`: 验证内核输出
70+
71+
**设计原则**
72+
- **单一验证政策**: 所有内核共享同一套容差语义
73+
- **分离关注点**: 参考计算 vs 比较逻辑
74+
- **可扩展**: 未来可添加其他参考适配器
3975

4076
## Benchmark 模块
4177

4278
项目将 Benchmark 功能拆分为三个深度模块,每个模块有独立的职责:
4379

80+
### Benchmark Settings
81+
**位置**: `src/utils/benchmark_settings.cuh**
82+
83+
配置集中化:
84+
- `RunSettings`: 预热次数、测量次数
85+
- `VerificationSettings`: 容差配置
86+
- `OutputSettings`: Roofline 导出选项
87+
- `BenchmarkSettings`: 聚合配置
88+
4489
### Benchmark Core
4590
**位置**: `src/utils/benchmark_core.cuh`
4691

4792
核心性能测量:
93+
- `BenchmarkResult`: 结果结构和报告生成
4894
- `CudaTimer` - RAII 包装的 CUDA 事件计时器
4995
- `measureGpuTime()` - 通用的 GPU 操作性能测量器
5096

@@ -62,14 +108,20 @@ Tensor Core 特有的 benchmark 功能,提供:
62108

63109
聚合模块并提供:
64110
- `SGEMMBenchmark` - 高级 benchmark 编排器
65-
- `BenchmarkResult` - 结果结构和报告生成
66111

67112
## 测试架构
68113

69114
### 测试分层
70115

71116
项目采用分层测试策略,确保每个层级都有独立的测试面:
72117

118+
#### CPU-only 测试
119+
**位置**: `tests/test_benchmark_settings.cpp`, `tests/test_device_info_cpu.cpp`
120+
121+
纯 CPU 测试,不需要 CUDA 设备:
122+
- 设置模块单元测试
123+
- 设备信息 Seam 测试(使用 fake provider)
124+
73125
#### 内核层测试
74126
**位置**: `tests/test_sgemm.cu`
75127

@@ -78,6 +130,14 @@ Tensor Core 特有的 benchmark 功能,提供:
78130
- Tensor Core 快速路径和 fallback 测试
79131
- 边界测试和维度不变性测试
80132

133+
#### Kernel Catalog 测试
134+
**位置**: `tests/test_kernel_catalog.cu`
135+
136+
测试内核目录的元数据和约束:
137+
- Catalog 包含预期的内核
138+
- 条目有有效的元数据(名称、启动器、约束)
139+
- 约束检查正确工作
140+
81141
#### 工具层测试
82142
**位置**: `tests/test_utils.cu`
83143

@@ -88,8 +148,6 @@ Tensor Core 特有的 benchmark 功能,提供:
88148
- `VerifyTolerance` - 容差配置和边界条件
89149
- NaN/Inf 处理、异常安全性
90150

91-
**设计原则**:工具层测试独立于内核测试,可以单独捕获工具类 bug。
92-
93151
#### 性能回归测试
94152
**位置**: `tests/test_performance.cu`
95153

@@ -105,7 +163,19 @@ Tensor Core 特有的 benchmark 功能,提供:
105163
- Double-Buffer: 35% 峰值
106164
- Tensor Core: 50% 峰值(当可用时)
107165

108-
**设计原则**:性能测试独立于正确性测试,可在 CI 中检测重大性能退化。
166+
### 测试分类标签
167+
168+
项目使用 CTest labels 区分测试类型:
169+
- `cpu`: CPU-only 测试,不需要 CUDA 设备
170+
- `cuda`: 需要 CUDA 设备的测试,无 GPU 时跳过
171+
- `performance`: 性能回归测试
172+
173+
**运行命令**:
174+
```bash
175+
ctest -L cpu # 只运行 CPU 测试
176+
ctest -L cuda # 只运行 CUDA 测试
177+
ctest -L performance # 只运行性能测试
178+
```
109179

110180
## 架构原则
111181

@@ -115,8 +185,8 @@ Tensor Core 特有的 benchmark 功能,提供:
115185
- `main.cu` - 入口点,仅负责组装
116186
- `cli_parser.cuh` - 命令行解析、配置构造
117187
- `benchmark_runner.cuh` - 内核调度、结果聚合
118-
2. **内核层** (`src/kernels/`) - 5 个内核实现 + Tensor Core 专用模块
119-
3. **工具层** (`src/utils/`) - RAII 内存管理、错误处理、验证辅助
188+
2. **内核层** (`src/kernels/`) - 5 个内核实现 + Kernel Catalog + Tensor Core 专用模块
189+
3. **工具层** (`src/utils/`) - RAII 内存管理、错误处理、验证辅助、设置模块
120190

121191
### 依赖方向
122192

0 commit comments

Comments
 (0)