Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← 系统与高性能 / Systems & Performance

计算系统 / Computing Systems

1. 计算系统:计算机如何执行与加速程序

2. 从 C++ 源码到 CPU 执行

3. CPU 流水线、乱序执行与分支预测

4. Cache、一致性、伪共享与 NUMA

5. GPU、SM、Warp 与显存

6. 计算执行模型:程序怎样映射到机器

7. SIMD 与编译器向量化

8. C++ 多线程与 OpenMP

9. CUDA 平台与编程模型

10. CUDA Kernel、内存与性能

11. CPU-GPU 异构流水线

12. MPI 与分布式并行

13. 并行算法模式

14. 性能模型与工具

15. 递进学习项目:从单线程到集群

历史完整正文 / Original Deep Dives

1. 历史完整正文:统一前文章逐篇保留

原体系结构与硬件 / Original Architecture

1. 硬件编程与高性能计算:一张可走通的学习地图 / A Practical Learning Map for Hardware Programming and HPC

2. 计算机体系结构:CPU、内存与 GPU / Computer Architecture: CPUs, Memory, and GPUs

3. 计算机架构基础——为什么 GPU 比 CPU 更快 / Computer Architecture Fundamentals: Why GPUs Outperform CPUs

4. 并行计算理论——30 天训练能优化到多快? / Parallel Computing Theory and the Limits of Training Acceleration

5. GPU 架构深入——上万个核心如何分工协作 / GPU Architecture and Massive Parallel Execution

6. CUDA 编程模型——把矩阵乘法映射到 GPU / The CUDA Programming Model for Mapping Matrix Multiplication to GPUs

7. CUDA 内存管理——百亿参数如何装进显存 / CUDA Memory Management for Large Models

8. CUDA 性能优化——从 30 天缩短到 10 天 / CUDA Performance Optimization

9. CPU 并行编程——OpenMP 与 SIMD 向量化 / CPU Parallel Programming with OpenMP and SIMD

10. HPC 集群与 MPI——多节点分布式训练 / HPC Clusters and MPI for Distributed Training

11. 异构计算——CPU 与 GPU 如何协同工作 / Heterogeneous Computing with CPUs and GPUs

12. 深度学习训练优化实战——从 30 天到 3 天 / Deep Learning Training Optimization from Thirty Days to Three

13. 性能分析工具——找到真正的瓶颈 / Performance Analysis Tools for Finding Real Bottlenecks

14. NPU 全景——昇腾/寒武纪/TPU/苹果生态 / The NPU Landscape: Ascend, Cambricon, TPU, and Apple

15. 未来趋势——2030 年的计算机会是什么形态 / Future Computing Trends Toward 2030

16. 硬件与高性能计算:从“程序为什么慢”开始 / Hardware and HPC Starting from Why Programs Are Slow

原并行计算 / Original Parallel Computing

1. 并行计算:从 SIMD 到 MPI / Parallel Computing from SIMD to MPI

2. 并行计算全景:从晶体管、CPU、GPU 到计算集群 / Parallel Computing from Transistors, CPUs, and GPUs to Clusters

3. 并行计算基础:任务分解、加速比与可扩展性 / Parallel Computing Fundamentals: Decomposition, Speedup, and Scalability

4. 处理器体系结构:从指令流水线到多核芯片 / Processor Architecture from Instruction Pipelines to Multicore Chips

5. CPU 并行:多线程、SIMD、Cache 一致性与 NUMA / CPU Parallelism with Threads, SIMD, Cache Coherence, and NUMA

6. 内存层次:Cache、带宽、局部性与一致性 / Memory Hierarchies, Bandwidth, Locality, and Coherence

7. GPU 体系结构:SIMT、Warp、SM 与吞吐优先设计 / GPU Architecture with SIMT, Warps, and Streaming Multiprocessors

8. CUDA 编程模型:Thread、Block、Grid 与内存协作 / CUDA Threads, Blocks, Grids, and Cooperative Memory Access

9. 并行算法模式:Map、Reduce、Scan、Stencil 与任务图 / Parallel Patterns: Map, Reduce, Scan, Stencil, and Task Graphs

10. 异构计算:CPU、GPU、NPU 如何协同工作 / Heterogeneous Computing with CPUs, GPUs, and NPUs

11. 分布式并行:MPI、集合通信、RDMA 与多机多卡 / Distributed Parallelism with MPI, Collective Communication, and RDMA

12. 性能工程:测量、Roofline、瓶颈定位与优化闭环 / Performance Engineering with Measurement, Roofline, and Bottleneck Analysis

13. 并行计算实战:AI、CAE、图像与科学计算 / Parallel Computing for AI, CAE, Imaging, and Scientific Computing

14. 并行计算实践路线:从单核优化到多机多卡 / A Parallel Computing Project Path from Single-Core to Multi-Node GPUs

本页目录

CUDA 性能优化——从 30 天缩短到 10 天 / CUDA Performance Optimization ​

📅 创建时间:2026-06-02 🏷️ 标签:#CUDA #优化 #Occupancy #WarpDivergence #TensorCore #CUDAStream 📚 前置知识:[[05-cuda-kernel-and-memory]](内存管理) [[04-cuda-programming-model]](编程模型) 📚 相关知识:[[11-performance-analysis-tools]](性能分析工具) [[10-dl-training-optimization]](训练优化)


先抓住直觉 ​

性能优化不是把所有技巧都加上,而是先找到最窄的那段管道。算力没吃满可能是数据供不上、并发线程不够、分支浪费,也可能是 CPU 没有及时提交工作。

  • 必须理解:先测量再优化;计算瓶颈与带宽瓶颈;Occupancy 只是手段,不是最终目标。
  • 用到再查:具体 profiler 指标、Shuffle 写法和 Stream 优先级 API。
  • 建议顺序:先读第 11 章的测量流程,再回本章选择优化方法。

场景:你的 CUDA 代码跑得比预期慢 10 倍 ​

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  你写了一个矩阵乘法的 CUDA kernel,自测了一下:           │
│                                                             │
│  理论算力(A100):156 TFLOPS(Tensor Core FP16)         │
│  你的实际性能:15 GFLOPS                                   │
│                                                             │
│  差距:10,000 倍!                                         │
│                                                             │
│  问题出在哪里?                                            │
│  → 内存带宽瓶颈?                                         │
│  → Warp 分支分化?                                       │
│  → 共享内存 bank 冲突?                                   │
│  → occupancy 太低?                                       │
│                                                             │
│  本章就是来解决这些问题的。                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

第1节:性能分析——先定位瓶颈 ​

屋顶线模型(Roofline Model) ​

┌─────────────────────────────────────────────────────────────┐
│                    Roofline 分析                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  性能上限 = min(算力上限, 带宽上限 × 算术强度)           │
│                                                             │
│       GFLOPS                                              │
│  156k ┤                                          ★ GPU   │
│       │                                        /           │
│   20k ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─           │
│       │                              /│                  │
│    5k ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│       │                         /│                       │
│    1k ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│       │              /│                                   │
│  312G ┤─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─  │
│       │       /│                                          │
│       └───────┼─────────────────────────────→             │
│              500      1000    2000  算术强度(FLOP/Byte)   │
│                                                             │
│  你的 kernel:算术强度 = 5 FLOP / 8 Byte = 0.6             │
│  → 落在带宽受限区,性能上限 = 带宽 × 0.6                   │
│  → 不是 GPU 算力不够,是内存访问拖了后腿                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

CUDA 性能分析工具 ​

bash
# NVIDIA Nsight Compute(kernel 级别)
ncu --set full ./matrix_mul
# 输出:SM 利用率、内存带宽、warp 执行效率等

# NVIDIA Nsight Systems(系统级别)
nsys profile ./my_cuda_app
# 输出:CPU-GPU 传输时间、kernel 执行 timeline

# 简单计时
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);

cudaEventRecord(start);
my_kernel<<<blocks, threads>>>(...);
cudaEventRecord(stop);
cudaEventSynchronize(stop);

float ms;
cudaEventElapsedTime(&ms, start, stop);
printf("Kernel time: %f ms\n", ms);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

第2节:Occupancy——GPU 利用率的根本 ​

什么是 Occupancy? ​

┌─────────────────────────────────────────────────────────────┐
│                    Occupancy(占用率)                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Occupancy = 实际运行线程数 / 最大可运行线程数              │
│                                                             │
│  A100 每 SM 最大:2048 线程 = 64 Warp × 32 线程           │
│                                                             │
│  如果只运行了 1024 线程:Occupancy = 1024/2048 = 50%      │
│                                                             │
│  低 Occupancy 的后果:                                      │
│  → Warp Scheduler 选择的余地小                            │
│  → 等待内存时没有足够的 Warp 可切换                        │
│  → GPU 闲置                                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

计算 Occupancy ​

┌─────────────────────────────────────────────────────────────┐
│                    A100 Occupancy 计算                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  每 SM 资源:                                              │
│  - 最大线程数:2048                                        │
│  - 最大 Block 数:16                                       │
│  - 寄存器数:65536 × 32-bit = 256 KB                     │
│  - 共享内存:128 KB                                        │
│                                                             │
│  限制因素:                                                 │
│  1. 寄存器限制:每个线程用的寄存器越多,能开的线程越少      │
│     Max threads = min(2048, 65536 / registers_per_thread) │
│                                                             │
│  2. 共享内存限制:每 block 用的共享内存越多,能开的 block越少│
│     Max blocks = 128KB / shared_mem_per_block             │
│                                                             │
│  3. Block 数限制:最多 16 个 block/SM                      │
│                                                             │
│  示例:                                                    │
│  每线程用 32 个寄存器,每 block 16KB 共享内存              │
│  → 寄存器限制:65536/32 = 2048 线程 → 64 Warp            │
│  → 共享内存限制:128KB/16KB = 8 个 block                 │
│  → Block 数限制:min(8, 16) = 8                          │
│  → 实际线程:8 block × 256 threads/block = 2048          │
│  → Occupancy = 2048/2048 = 100%                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

提高 Occupancy ​

cpp
// ❌ 差:每线程寄存器太多,Occupancy 低
__global__
void heavy_register_kernel(float* data, int N) {
    float temp1, temp2, temp3, temp4, temp5;  // 5 个临时变量
    float temp6, temp7, temp8, temp9, temp10;
    float temp11, temp12, temp13, temp14, temp15;

    // 大量使用寄存器
    temp1 = data[threadIdx.x];
    temp2 = temp1 * 2.0f;
    // ...
    data[threadIdx.x] = temp15;
}

// ✅ 好:减少临时变量,使用共享内存
__global__
void light_register_kernel(float* data, int N) {
    __shared__ float temp[256];  // 共享内存代替寄存器

    temp[threadIdx.x] = data[threadIdx.x];
    temp[threadIdx.x] *= 2.0f;
    __syncthreads();

    data[threadIdx.x] = temp[threadIdx.x];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

第3节:向量化加载——充分利用内存带宽 ​

什么是向量化加载? ​

┌─────────────────────────────────────────────────────────────┐
│                    向量化加载原理                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  普通加载:                                                │
│  Thread 0: 读取 addr+0   (4 字节)                        │
│  Thread 1: 读取 addr+4   (4 字节)                        │
│  Thread 2: 读取 addr+8   (4 字节)                        │
│  Thread 3: 读取 addr+12  (4 字节)                        │
│  → 4 次内存事务                                          │
│                                                             │
│  向量化加载(float4):                                     │
│  Thread 0-3: 一次读取 addr+0~15  (16 字节)              │
│  → 1 次内存事务,效率提升 4 倍!                          │
│                                                             │
│  A100 支持的最大向量化:float4(128 位)                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

向量化代码示例 ​

cpp
// 普通版本
__global__
void vector_add_basic(float* a, float* b, float* c, int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < N) {
        c[i] = a[i] + b[i];  // 每个线程读取 3×4=12 字节
    }
}

// 向量化版本(效率提升 ~2-3 倍)
__global__
void vector_add_vectorized(float4* a, float4* b, float4* c, int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < N / 4) {  // 数据量变为 1/4(每次处理 4 个 float)
        float4 va = a[i];
        float4 vb = b[i];
        c[i] = make_float4(
            va.x + vb.x,
            va.y + vb.y,
            va.z + vb.z,
            va.w + vb.w
        );
    }
}

// 调用
int N_aligned = (N + 3) / 4;  // 对齐到 4
vector_add_vectorized<<<blocks, threads>>>(
    (float4*)d_a, (float4*)d_b, (float4*)d_c, N_aligned);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

第4节:Warp 级优化——分支和洗牌 ​

减少分支分化 ​

cpp
// ❌ 差:Warp 内分支分化
__global__
void update_if_else(float* data, float threshold, int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < N) {
        if (data[i] > threshold) {
            data[i] = sqrt(data[i]);
        } else {
            data[i] = data[i] * data[i];
        }
    }
}

// ✅ 好:用 step 函数替代分支
__global__
void update_branchless(float* data, float threshold, int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < N) {
        float val = data[i];
        float greater = (val > threshold);  // 0.0 或 1.0

        // 选择:greater * sqrt + (1-greater) * square
        float res = greater * sqrtf(val) + (1.0f - greater) * val * val;
        data[i] = res;
    }
}

// ✅ 好:把相同分支的线程放到一起(Block 分组)
__global__
void update_grouped(float* data, float threshold, int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i < N) {
        // Block 0: 大于阈值,Block 1: 小于等于阈值
        if (blockIdx.x == 0) {
            if (data[i] > threshold)
                data[i] = sqrt(data[i]);
        } else {
            if (data[i] <= threshold)
                data[i] = data[i] * data[i];
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

Warp 洗牌(Shuffle)指令 ​

cpp
// Warp Shuffle:同 Warp 内线程直接交换数据,不需要共享内存!

// __shfl_sync:同一 Warp 内广播某个线程的值
__global__
void warp_reduce_sum(float* data, float* result, int N) {
    float val = data[threadIdx.x];
    
    // Warp 内归约
    for (int offset = 16; offset > 0; offset >>= 1) {
        // 把 offset 线程的值加到当前线程
        val += __shfl_down_sync(0xffffffff, val, offset);
    }
    
    // thread 0 保存结果
    if (threadIdx.x == 0) {
        *result = val;
    }
}

// __shfl_down_sync 的效果(8 线程示例):
// 初始:  [t0=1, t1=2, t2=3, t3=4, t4=5, t5=6, t6=7, t7=8]
// offset=4: [t0=5, t1=6, t2=7, t3=8, t4=5, t5=6, t6=7, t7=8]
//          当前线程从 thread+4 获取值并相加
//          t0 = 1+5=6, t1=2+6=8, ...

// 对比用共享内存的版本:
__global__
void shared_reduce_sum(float* data, float* result, int N) {
    __shared__ float sdata[32];
    sdata[threadIdx.x] = data[threadIdx.x];
    __syncthreads();
    
    for (int s = 16; s > 0; s >>= 1) {
        if (threadIdx.x < s) {
            sdata[threadIdx.x] += sdata[threadIdx.x + s];
        }
        __syncthreads();
    }
    
    if (threadIdx.x == 0) *result = sdata[0];
}

// Shuffle 版本不需要 __syncthreads(因为同一 Warp 同步执行)
// 速度更快!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

第5节:CUDA Stream——异步并行 ​

什么是 CUDA Stream? ​

┌─────────────────────────────────────────────────────────────┐
│                    CUDA Stream 概念                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  默认 Stream(NULL):                                      │
│  所有操作顺序执行                                           │
│  H2D ──→ Kernel ──→ D2H                                  │
│                                                             │
│  多 Stream:                                               │
│  Stream 0: H2D ──→ Kernel ──→ D2H                        │
│  Stream 1:      H2D ──→ Kernel ──→ D2H                   │
│  ↑ 不同 Stream 的操作可以重叠!                            │
│                                                             │
│  内存拷贝和 Kernel 执行可以同时进行                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Stream 使用示例 ​

cpp
// 单 Stream 版本(顺序执行)
cudaMemcpy(d_a, h_a, size, cudaMemcpyHostToDevice);
kernel<<<blocks, threads>>>(d_a, d_b, d_c);
cudaMemcpy(h_c, d_c, size, cudaMemcpyDeviceToHost);
// 总时间 = H2D + Kernel + D2H

// ================================================================
// 多 Stream 版本(重叠执行)
// ================================================================
cudaStream_t stream0, stream1;
cudaStreamCreate(&stream0);
cudaStreamCreate(&stream1);

const int chunk = size / 2;

// Stream 0: 前半部分
cudaMemcpyAsync(d_a, h_a, chunk, cudaMemcpyHostToDevice, stream0);
kernel<<<blocks, threads, 0, stream0>>>(d_a, d_b, d_c, chunk);
cudaMemcpyAsync(h_c, d_c, chunk, cudaMemcpyDeviceToHost, stream0);

// Stream 1: 后半部分(与 Stream 0 并行!)
cudaMemcpyAsync(d_a + chunk/4, h_a + chunk/4, chunk,
                 cudaMemcpyHostToDevice, stream1);
kernel<<<blocks, threads, 0, stream1>>>(d_a + chunk/4, d_b + chunk/4,
                                         d_c + chunk/4, chunk);
cudaMemcpyAsync(h_c + chunk/4, d_c + chunk/4, chunk,
                 cudaMemcpyDeviceToHost, stream1);

// 等待所有 Stream 完成
cudaDeviceSynchronize();

// 总时间 = max(H2D, Kernel) + max(Kernel, D2H) < H2D + Kernel + D2H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Stream 优先级 ​

cpp
// 设置 Stream 优先级
int priority_low, priority_high;
cudaDeviceGetStreamPriorityRange(&priority_low, &priority_high);
// priority_high > priority_low = 更高优先级

cudaStream_t stream_high, stream_low;
cudaStreamCreateWithPriority(&stream_high, cudaStreamNonBlocking, priority_high);
cudaStreamCreateWithPriority(&stream_low, cudaStreamNonBlocking, priority_low);

// 高优先级 Stream 的 kernel 更早被调度
1
2
3
4
5
6
7
8
9
10

第6节:Tensor Core 加速矩阵乘法 ​

使用 cuBLAS 库 ​

cpp
// 使用 cuBLAS 自动利用 Tensor Core
#include <cublas_v2.h>

cublasHandle_t cublas_handle;
cublasCreate(&cublas_handle);

// 使用 Tensor Core(FP16 矩阵乘法,自动选择最快实现)
cublasGemmEx(cublas_handle,
    CUBLAS_OP_N, CUBLAS_OP_N,  // 不转置
    N, M, K,                     // C[M×N] = A[M×K] × B[K×N]
    &alpha,                       // = 1.0
    d_A, CUDA_R_16F, K,          // A 矩阵
    d_B, CUDA_R_16F, N,          // B 矩阵
    &beta,                        // = 0.0(不累加)
    d_C, CUDA_R_16F, M,          // C 矩阵
    CUDA_R_16F,                   // 计算精度
    CUBLAS_GEMM_DEFAULT_TENSOR_OP  // 使用 Tensor Core
);

// cuBLAS 自动处理:
// 1. 选择最优的 kernel
// 2. 自动使用 Tensor Core(如果可用)
// 3. 内存布局优化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

第7节:优化检查清单 ​

┌─────────────────────────────────────────────────────────────┐
│                    CUDA 优化检查清单                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  [ ] 1. 内存访问                                           │
│      [ ] 合并访问:连续线程访问连续内存                      │
│      [ ] 共享内存复用:减少全局内存访问                     │
│      [ ] 向量化加载:float4/float2 一次读多个值             │
│      [ ] 避免 Bank 冲突                                    │
│                                                             │
│  [ ] 2. 计算优化                                           │
│      [ ] 使用 Tensor Core(cuBLAS/cuDNN)                  │
│      [ ] 减少分支分化(Warp 内 if-else)                   │
│      [ ] 使用 Warp Shuffle 代替共享内存做归约               │
│                                                             │
│  [ ] 3. 调度优化                                           │
│      [ ] Occupancy >= 50%(通常足够好)                   │
│      [ ] Block 维度 32 的倍数                              │
│      [ ] 使用 CUDA Stream 重叠数据传输和计算                │
│                                                             │
│  [ ] 4. 测量验证                                           │
│      [ ] 用 Nsight Compute/Nsight Systems profiling        │
│      [ ] 对比优化前后的实际 FLOPS                          │
│      [ ] 确认达到了 Roofline 上限                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

"AI 可查 vs 必须理解"清单 ​

AI 可查:
✅ Tensor Core 的具体 API(cuBLAS/cuDNN 参数)
✅ CUDA Stream 的具体函数
✅ Nsight Compute 的具体命令选项

必须理解:
🔴 Roofline 模型:带宽受限 vs 算力受限
🔴 Occupancy = 实际线程数 / 最大线程数,影响延迟隐藏能力
🔴 合并访问:连续线程访问连续内存
🔴 Warp 分支分化导致 50% 效率损失
🔴 Warp Shuffle:同 Warp 内直接交换数据,无需共享内存
🔴 CUDA Stream:不同 Stream 的操作可以重叠(H2D 和 Kernel 并行)
1
2
3
4
5
6
7
8
9
10
11
12

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇7. CUDA 内存管理——百亿参数如何装进显存 / CUDA Memory Management for Large Models
下一篇9. CPU 并行编程——OpenMP 与 SIMD 向量化 / CPU Parallel Programming with OpenMP and SIMD

持续记录,持续成长

Copyright © Tidenflow