源代码(.pc文件)
│
▼
┌──────────────┐
│ 词法分析器 │ Lexer: 识别parallel关键字、标准C tokens
│ (lexer.c) │
└──────┬───────┘
│ Token流
▼
┌──────────────┐
│ 语法分析器 │ Parser: 递归下降,构建AST
│ (parser.c) │
└──────┬───────┘
│ AST
▼
┌──────────────┐
│ 语义分析器 │ Semantic: 类型检查、作用域、依赖分析
│ (semantic.c)│
└──────┬───────┘
│ 标注AST
▼
┌──────────────┐
│ IR生成器 │ IR Builder: AST → 三地址码IR
│ (ir.c) │
└──────┬───────┘
│ IR
▼
┌──────────────────────────────────────────┐
│ 优 化 流 水 线 │
│ │
│ ┌────────────────────────────────────┐ │
│ │ Pass 1: 并行模式检测与分析 │ │
│ │ (parallel_detect.c) │ │
│ │ - 识别parallel_for/reduce/scan │ │
│ │ - 依赖距离向量分析 │ │
│ │ - 归约变量检测 │ │
│ └──────────┬─────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ Pass 2: 循环优化 │ │
│ │ (loop_opt.c) │ │
│ │ - 循环分块 (Tiling) │ │
│ │ - 循环融合 (Fusion) │ │
│ │ - 循环展开 (Unrolling) │ │
│ │ - 循环交换 (Interchange) │ │
│ │ - 循环分裂 (Fission) │ │
│ └──────────┬─────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ Pass 3: 自动SIMD向量化 │ │
│ │ (vectorize.c) │ │
│ │ - 向量化可行性分析 │ │
│ │ - 标量→SIMD提升 │ │
│ │ - 归约向量化 │ │
│ │ - 残余循环处理 │ │
│ └──────────┬─────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ Pass 4: 内存优化 │ │
│ │ (memory_opt.c) │ │
│ │ - AoS→SoA转换 │ │
│ │ - 数据对齐 (alignas) │ │
│ │ - 预取指令插入 │ │
│ │ - 缓存分块 │ │
│ └──────────┬─────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────┐ │
│ │ Pass 5: 标量优化 │ │
│ │ (scalar_opt.c) │ │
│ │ - 常量折叠/传播 │ │
│ │ - 死代码消除 │ │
│ │ - 强度削减 │ │
│ │ - 公共子表达式消除 │ │
│ └──────────┬─────────────────────────┘ │
└─────────────┼────────────────────────────┘
│ 优化后IR
▼
┌──────────────┐
│ 代码生成器 │ CodeGen: IR → 优化的C代码
│ (codegen.c) │ - SIMD intrinsics
└──────┬───────┘ - OpenMP hints (可选)
│ - restrict/aligned指针
▼
输出: 优化的C源文件(.c)
→ 可直接用gcc/clang编译
1#include <par2serial.h>
2
3// parallel_for: 并行循环
4parallel_for(i, 0, N) {
5 C[i] = A[i] + B[i];
6}
7
8// parallel_reduce: 并行归约
9float sum = 0;
10parallel_reduce(sum, +, i, 0, N) {
11 sum += A[i];
12}
13
14// parallel_scan: 并行前缀扫描
15parallel_scan(prefix_sum, +, i, 0, N) {
16 prefix_sum[i] = A[i];
17}
18
19// parallel_map: 对每个元素应用函数
20parallel_map(B, A, N, func) {
21 B[i] = func(A[i]);
22}
23
24// tile_hint: 分块提示
25tile_hint(TILE_SIZE, 32);
26
27// simd_hint: 向量化提示
28simd_hint(AVX2);
29
30// memory_layout: 内存布局提示
31memory_layout(particles, SOA); // AoS → SoA
1parallel_for(i, 0, M) {
2 parallel_for(j, 0, N) {
3 float sum = 0;
4 parallel_reduce(sum, +, k, 0, K) {
5 sum += A[i*K+k] * B[k*N+j];
6 }
7 C[i*N+j] = sum;
8 }
9}
1#include <immintrin.h>
2
3// 分块矩阵乘法 + AVX向量化
4for (int ii = 0; ii < M; ii += TILE_I) {
5 for (int jj = 0; jj < N; jj += TILE_J) {
6 for (int kk = 0; kk < K; kk += TILE_K) {
7 for (int i = ii; i < ii+TILE_I && i < M; i++) {
8 for (int j = jj; j < jj+TILE_J && j < N; j += 8) {
9 __m256 vsum = _mm256_loadu_ps(&C[i*N+j]);
10 for (int k = kk; k < kk+TILE_K && k < K; k++) {
11 __m256 va = _mm256_broadcast_ss(&A[i*K+k]);
12 __m256 vb = _mm256_loadu_ps(&B[k*N+j]);
13 vsum = _mm256_fmadd_ps(va, vb, vsum);
14 }
15 _mm256_storeu_ps(&C[i*N+j], vsum);
16 }
17 }
18 }
19 }
20}
1# 构建编译器
2make
3
4# 编译并行程序为优化串行代码
5./par2serial input.pc -o output.c
6
7# 指定优化级别
8./par2serial input.pc -o output.c -O2
9
10# 指定目标SIMD指令集
11./par2serial input.pc -o output.c --simd=avx2
12
13# 查看优化报告
14./par2serial input.pc -o output.c --report
15
16# 编译生成的代码
17gcc -O3 -mavx2 -mfma output.c -o program
par2serial-cc/
├── src/
│ ├── main.c # 编译器入口、命令行解析
│ ├── lexer.h / lexer.c # 词法分析器
│ ├── parser.h / parser.c # 语法分析器(递归下降)
│ ├── ast.h / ast.c # 抽象语法树定义
│ ├── semantic.h/.c # 语义分析
│ ├── ir.h / ir.c # 中间表示(三地址码)
│ ├── parallel_detect.h/.c # 并行模式检测
│ ├── loop_opt.h/.c # 循环优化
│ ├── vectorize.h/.c # SIMD自动向量化
│ ├── memory_opt.h/.c # 内存布局优化
│ ├── scalar_opt.h/.c # 标量优化
│ ├── codegen.h/.c # C代码生成
│ └── utils.h / utils.c # 工具函数
├── include/
│ └── par2serial.h # 用户头文件(并行原语定义)
├── tests/
│ ├── test_matmul.pc # 矩阵乘法测试
│ ├── test_reduce.pc # 归约测试
│ ├── test_stencil.pc # Stencil计算测试
│ ├── test_scan.pc # 前缀扫描测试
│ └── benchmark.sh # 性能测试脚本
├── examples/
│ ├── matmul.pc # 矩阵乘法示例
│ ├── nbody.pc # N-body模拟示例
│ └── convolution.pc # 卷积示例
├── Makefile
└── README.md
-
parallel_for → 串行循环 + SIMD
- 去除线程分配开销
- 检测数据依赖,决定向量化策略
- 无依赖循环直接SIMD化
-
parallel_reduce → 向量化归约
- 展开为SIMD宽度的部分和
- 最后做水平归约
- 比朴素串行循环快4-8倍(AVX2)
-
parallel_scan → Blelloch串行实现
-
barrier/同步 → 消除
-
共享内存 → 寄存器/栈提升