Anthropic技术总监级拆解大模型 第16讲:GPU 与 CUDA 大模型计算到底是怎么跑起来的?

AI技术总监级拆解大模型|第16讲:GPU 与 CUDA------大模型计算到底是怎么跑起来的?

关键词: GPU、CPU、CUDA、Kernel、Thread、Block、Grid、Warp、SIMT、显存、并行计算、PyTorch、性能分析

前15讲,我们从 AI 基础一路讲到大模型推理。现在换个视角:模型里那么多矩阵乘法、注意力计算和梯度运算,究竟由什么硬件执行?为什么 GPU 能把这类任务做得很快?为什么同样把程序放到 GPU 上,有时却快不了多少?

这一讲不追求一上来就写复杂 CUDA,而是把硬件、编程模型和工程性能串起来。读完后,你应该能看懂 CUDA 的基本结构,理解一个最小 Kernel,知道 GPU 性能到底应该怎么测。


一、先讲结论:GPU 的优势是高吞吐并行计算,不是"什么都比 CPU 快"

先看一个简单任务:对一百万个元素逐个执行加法。

C_i=A_i+B_i,\\quad i=0,1,\\ldots,N-1

每个结果只依赖对应的 (A_i) 和 (B_i),各个元素之间几乎没有依赖关系。这类任务可以拆成许多独立的小任务并行执行,称为数据并行(Data Parallelism)。

GPU 的设计目标之一,就是高效处理大量这种相似工作。深度学习恰好有大量矩阵乘法、向量运算、卷积、注意力以及梯度计算,所以 GPU 成为主流 AI 计算设备之一。

但这里有个关键区别:

  • 延迟(Latency): 单个任务从开始到完成要多久。
  • 吞吐(Throughput): 一段时间总共完成多少工作。

GPU 往往有利于提升大规模任务的吞吐;小任务、复杂分支任务,或频繁在 CPU 和 GPU 之间搬运数据的任务,不一定更快。把 GPU 当作"通用加速按钮",是第一大误区。

二、CPU 和 GPU 的差别:执行目标不同

维度 CPU GPU
核心设计取向 强调低延迟、复杂控制和灵活调度 强调大规模并行与高吞吐
典型工作 操作系统、程序控制、I/O、复杂分支、任务调度 矩阵运算、图像处理、批量张量计算、深度学习算子
并行能力 能多核并行,但资源组织偏向复杂通用任务 用大量执行线程处理许多相似的数据任务
可能的瓶颈 指令依赖、分支、单线程延迟、内存等待 显存带宽、访问模式、计算单元利用率、同步与启动开销

不要把差别简化成"CPU 有几个核,GPU 有几千个核"。二者的核、调度方式和执行组织并不完全可比。GPU 也并非只有一种执行单元:除了通用算术执行资源,现代 GPU 还可能提供专用矩阵计算单元等硬件。

一个生活化例子

假设一家公司要处理 100 万张结构相似的小表格:

  • CPU 像一组擅长协调、判断和处理复杂例外的工作人员;
  • GPU 像一套可以把大量格式相似的计算任务拆开、批量推进的流水化作业系统。

这个比喻只是帮助建立直觉。真实 GPU 不是"成千上万个彼此完全独立的小 CPU",其执行和调度由具体硬件架构决定。

结论:GPU 的性能优势来自并行组织、执行吞吐、内存系统和软件配合,而不只是核心数量。

三、GPU 内部结构:先认识 SM、CUDA Core 和 Tensor Core

可以先记住这张简化图:

text 复制代码
GPU
├── 多个 SM(Streaming Multiprocessor,流式多处理器)
│   ├── 线程调度与执行资源
│   ├── CUDA Cores 等通用算术执行资源
│   ├── Registers(寄存器)
│   ├── Shared Memory / Cache 等片上存储资源
│   └── 某些架构包含 Tensor Cores 等专用计算单元
├── 缓存层次
└── 显存接口和其他系统单元

这是一张便于学习的概念图,不是所有 GPU 架构的精确电路图。具体数量和实现因厂商、型号与架构而变化。

1. SM 是什么?

SM 是 NVIDIA GPU 组织和执行线程的重要硬件单元。CUDA 的 Block 会被调度到 SM 上执行。一个 SM 能同时驻留多少 Block,受寄存器、共享内存以及硬件资源限制影响。

程序员通常不需要,也不能在普通 CUDA Kernel 启动中简单指定"Block 0 必须运行在 SM 0"。CUDA 会依据硬件可用资源调度 Block。可扩展程序应尽量让不同 Block 相互独立,不假设它们的执行顺序。

2. CUDA Core 是什么?

CUDA Core 是 NVIDIA GPU 中执行常见算术指令的计算资源之一。但 CUDA Core 数量不等于实际速度,不能只看核心数量判断两张不同架构 GPU 的性能。频率、指令类型、数据精度、缓存、内存带宽、编译器和 Kernel 实现都会影响结果。

3. Tensor Core 又是什么?

Tensor Core 是 NVIDIA 某些 GPU 架构中面向矩阵运算的专用计算单元,对深度学习中的矩阵乘法十分重要。实际收益依赖于硬件、数据类型、矩阵尺寸和软件实现。

本讲只需要知道它的定位。Tensor Core、FP16/BF16、HBM/SRAM、数据复用和 FlashAttention 将在第17讲深入讨论。

四、CUDA 是什么?别把 GPU、CUDA、Kernel 混为一谈

三个概念先划清:

  • GPU: 执行计算的硬件。
  • CUDA: NVIDIA 的并行计算平台和编程生态,提供编程模型、编译/运行支持、库和开发工具。
  • Kernel: 编写给 GPU 并行执行的函数。

还会遇到这些名字:

概念 作用
CUDA C/C++ 在 C/C++ 基础上使用 CUDA 扩展编写 GPU 程序
CUDA Runtime / Driver 支持设备管理、内存操作、Kernel 启动等;二者处于不同软件层次
cuBLAS 常见的 GPU 线性代数库之一
cuDNN 深度学习相关的优化计算库之一
PyTorch 更高层的深度学习框架,组织张量、计算图、自动求导和算子调用

CUDA 是 NVIDIA 生态,不是 GPU 的通用同义词。其他厂商也有各自的 GPU 编程工具与软件栈,不能把所有 GPU 编程都叫 CUDA。

从 Python 到 GPU,大致经过哪些层?

text 复制代码
PyTorch 模型代码
      ↓
张量算子(矩阵乘法、卷积、Attention 等)
      ↓
框架调度 / 优化库 / CUDA Kernel
      ↓
CUDA Runtime 与 Driver 提交工作
      ↓
GPU 的 SM、执行单元、缓存和显存系统完成运算

当你在 PyTorch 里写 y = x @ w 时,通常是框架调用适合当前张量形状和硬件的矩阵乘法实现。你并没有在 Python 里手工为每个矩阵元素创建一个 Python 线程。

五、CUDA 编程模型:Thread → Block → Grid

CUDA 把并行工作组织成三个层次:

text 复制代码
Grid:一次 Kernel 启动中的所有线程块
  ├── Block 0
  │    ├── Thread 0
  │    ├── Thread 1
  │    └── ...
  ├── Block 1
  │    ├── Thread 0
  │    └── ...
  └── Block 2 ...
  • Thread(线程): 一个工作实例,通常负责一个或一部分数据。
  • Block(线程块): 一组线程,能共享指定的 Shared Memory,并进行 Block 内同步。
  • Grid(网格): 一次 Kernel 启动中的全部 Block。
  • Warp: NVIDIA CUDA 执行模型中的常见执行组,通常包含 32 个线程。

可以把这个结构理解为:Grid 负责把整体任务分成很多块;每个 Block 负责其中一部分;每个 Thread 再负责更细的工作。

1. 最常见的全局索引公式

一维任务经常会写:

cpp 复制代码
int i = blockIdx.x * blockDim.x + threadIdx.x;

符号逐个解释:

  • threadIdx.x:当前线程在 Block 内的索引;
  • blockIdx.x:当前 Block 在 Grid 中的索引;
  • blockDim.x:一个 Block 在 x 方向有多少线程;
  • i:当前线程对应的全局工作索引。

假设每个 Block 有 256 个线程:

text 复制代码
Block 0:i = 0 ... 255
Block 1:i = 256 ... 511
Block 2:i = 512 ... 767
...

这只是逻辑上的索引分工。具体 Block 在什么时间、由哪个 SM 执行,是运行时调度问题。

2. 为什么 Block 间不能随便假设执行顺序?

GPU 会根据硬件资源和调度情况执行 Block。不同 Block 可能并行执行,也可能分批先后执行;普通 Kernel 中不应依赖它们按 Block 编号执行。

Block 内有可用的共享内存与同步机制;跨 Block 协调则需要更谨慎的算法设计。__syncthreads() 只能作为 Block 内同步点,它不是让整个 Grid 的所有线程同时停下来等待的全局屏障。

这是很多初学 CUDA 程序出现死锁、数据竞争或结果不稳定的原因之一。

六、动手看懂一个 CUDA Kernel:向量加法

先看数学问题:

C_i=A_i+B_i,\\quad 0\\le i\

每一个输出元素都能独立计算,因此可以把每个元素分配给一个线程。

1. Kernel 代码

cpp 复制代码
#include <cuda_runtime.h>

__global__ void vector_add(const float* A,
                           const float* B,
                           float* C,
                           int N) {
    int i = blockIdx.x * blockDim.x + threadIdx.x;

    if (i < N) {
        C[i] = A[i] + B[i];
    }
}

解释:

  • __global__:声明一个可以从 Host 端启动、在 GPU 上执行的 Kernel;
  • A、B、C:指针参数;在典型离散 GPU 场景中,传给 Kernel 的这些指针应指向 GPU 可访问的内存;
  • i:每个线程通过自己的索引找到负责的数据;
  • if (i < N):保护最后一个 Block,避免数组越界。

2. 启动方式

cpp 复制代码
int threads = 256;
int blocks = (N + threads - 1) / threads;
vector_add<<<blocks, threads>>>(d_A, d_B, d_C, N);

<<<blocks, threads>>> 是 CUDA Kernel 的启动配置,表示启动多少个 Block,以及每个 Block 有多少线程。

Block 数量按向上取整计算:

\\text{blocks}=\\left\\lceil\\frac{N}{\\text{threads}}\\right\\rceil

举例:N=1000,每个 Block 256 个线程:

\\text{blocks}=\\lceil1000/256\\rceil=4

一共启动 4×256=1024 个逻辑线程,最后 24 个线程的索引大于等于 1000。若没有 if (i < N),这些线程可能越界访问内存。

注意:256 是一个常见的初始配置,不是任何 Kernel 都最优的数字。应该根据资源占用、访存方式和实测结果调整。

3. 完整程序还缺什么?

真实程序通常还需要:

  1. 在 Host 端准备输入;
  2. 为 Device 数据分配内存,例如 cudaMalloc;
  3. 将输入从 Host 复制到 Device,例如 cudaMemcpy;
  4. 启动 Kernel,并检查错误;
  5. 等待需要完成的工作;
  6. 把结果复制回 Host(若后续工作不在 GPU 上);
  7. 释放设备内存。

这里的代码重点展示 Kernel 结构,不是完整可独立编译的工程。生产代码还应对 CUDA API 和 Kernel 启动错误进行检查。

七、SIMT 与 Warp:为什么 GPU 适合做"同一类计算"?

SIMT 是 Single Instruction, Multiple Threads(单指令多线程)。通俗理解:一个 Warp 内的线程通常共同推进相同的指令流,但每个线程处理不同的数据、维护自己的状态。

例如:

text 复制代码
Thread 0:C[0] = A[0] + B[0]
Thread 1:C[1] = A[1] + B[1]
Thread 2:C[2] = A[2] + B[2]
...

所有线程执行同类加法,区别只是索引不同。这种规律性让硬件容易组织并行执行。

分支分化是什么?

考虑下面的代码:

cpp 复制代码
if (x > 0) {
    // 计算路径 A
} else {
    // 计算路径 B
}

如果同一个 Warp 中一部分线程满足条件、另一部分不满足,Warp 内线程就可能走不同路径。硬件需要处理各个分支路径,一部分执行通道可能暂时没有有效工作,这会影响效率,这就是分支分化(Branch Divergence)。

不是所有分支都很糟糕。影响大小取决于分支是否在 Warp 内分化、不同路径的计算量,以及编译器和硬件如何处理。不要为了消除每一个 if 盲目改写代码;应该先 Profiling。

为什么 Block 线程数常用 128 或 256?

因为 Warp 通常包含 32 个线程,128、256 等配置能够整除 32,方便形成完整 Warp。但最优值不是固定的。每线程寄存器数量、每 Block 的共享内存需求、可同时驻留的 Block 数量、Kernel 的指令结构都会影响最终表现。

另外,线程数不是实际并行度的全部:一个 Kernel 即使创建了很多线程,也不表示它们都能在同一时刻运行。硬件会依据资源限制安排实际执行。

八、Host、Device 和显存搬运:为什么"GPU 很快"仍然可能不快?

传统独立显卡系统中,CPU 主机内存与 GPU 设备内存通常是不同的内存空间:

text 复制代码
CPU / Host Memory
      │ 输入数据复制(H2D)
      ▼
GPU / Device Memory
      │ Kernel 读数据、计算、写结果
      ▼
GPU / Device Memory
      │ 结果复制(D2H,如有必要)
      ▼
CPU / Host Memory

H2D 是 Host-to-Device;D2H 是 Device-to-Host。数据传输通常会经过 PCIe 或系统提供的其他互连。

假设某个计算本身只用 0.1 毫秒,却要花 0.5 毫秒复制数据和启动相关任务,那么只盯着计算单元是没有意义的。你真正关心的往往是端到端总时间。

这也解释了为什么:

  • 只做少量计算就把数据送去 GPU,可能不划算;
  • 把许多相邻操作组织成更大的工作,可能减少频繁启动和往返;
  • 让数据留在 GPU 上连续完成多个算子,往往比每一步都取回 CPU 更合理;
  • 异步传输和多个执行流可以帮助重叠部分工作,但需要正确管理依赖和缓冲区生命周期。

现代 GPU 平台还可能提供 Unified Memory 或共享内存架构。它们能简化部分数据管理,却不意味着所有访问成本相同,也不代表数据移动变得免费。

九、GPU 内存先认识四层:寄存器、共享内存、缓存、全局内存

GPU 并不只是一排计算单元。内存层次是性能的另一半。

概念 谁使用 用途与直觉
Register(寄存器) 单个线程 存放线程计算中的临时值,访问非常快但资源有限
Shared Memory(共享内存) 同一 Block 内线程 让线程协作共享数据,常用于数据复用和减少重复访问
L1/L2 Cache 由硬件缓存机制管理,具体细节随架构变化 利用数据局部性,降低部分访存成本
Global Memory(全局内存) Kernel 线程可访问 容量较大,常对应 GPU 显存;访问代价比寄存器等片上资源更高

这里需要澄清:CUDA 术语里的 Local Memory 不一定是物理上很近、访问很快的存储;某些线程局部数据如果寄存器资源不足,可能被放到设备内存层次中。不要只凭名称判断速度。

为什么它与 AI 有关?矩阵乘法和 Attention 不仅要计算,还要不断读取输入、权重、中间结果并写出结果。如果重复加载同一份数据,或访问地址让硬件难以合并请求,就可能浪费大量内存带宽。

本讲建立"内存也会卡性能"的直觉即可。第17讲会进一步讨论 HBM、SRAM、Tensor Core、访存合并、数据复用、Kernel 融合以及 FlashAttention。

十、GPU 在大模型训练与推理中的位置

1. 训练:前向、损失、反向和参数更新

一个简化的训练循环是:

text 复制代码
输入一个 Batch
     ↓
前向传播:计算预测
     ↓
计算 Loss
     ↓
反向传播:计算梯度
     ↓
优化器更新参数
     ↓
进入下一个 Batch

这些步骤包含大量张量计算;特别是矩阵乘法和反向传播,通常有较强的数据并行结构。GPU 可以承担核心数值计算,但训练性能还受显存容量、激活保存、梯度与优化器状态、数据加载、分布式通信和同步等影响。

2. 推理:同样使用 GPU,但目标与瓶颈不同

推理时,模型用已训练好的权重生成结果。矩阵乘法、Attention、归一化等算子依然可能在 GPU 执行。对自回归大模型,提示词处理(Prefill)与逐 Token 生成(Decode)的计算形态并不相同,瓶颈也可能不同。这个主题会在第20讲展开。

要记住:GPU 不知道什么是"语言理解"。它只执行数值计算。模型结构与权重由软件定义,框架把模型操作映射成底层算子,再由 GPU 执行。

十一、用 PyTorch 检查 GPU:把抽象概念落到代码

1. 检查环境

python 复制代码
import torch

print("PyTorch version:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())

if torch.cuda.is_available():
    print("GPU name:", torch.cuda.get_device_name(0))

如果 torch.cuda.is_available() 为 False,常见原因包括安装的 PyTorch 构建不支持当前 CUDA 设备、驱动问题、运行环境没有暴露 GPU,或环境配置不匹配。不要仅凭电脑有 NVIDIA 显卡,就断定 Python 环境一定可使用 GPU。

2. 在 GPU 上做矩阵乘法

python 复制代码
import torch

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
x = torch.randn(2048, 2048, device=device)
w = torch.randn(2048, 2048, device=device)
y = x @ w

print("input device:", x.device)
print("output device:", y.device)

这段程序把张量放到选定设备上,再执行矩阵乘法。@ 是矩阵乘法运算符;实际底层会由 PyTorch 依据设备、形状和可用实现调度对应算子。

常见错误是一个张量在 GPU、另一个在 CPU:

python 复制代码
x = torch.randn(100, device="cuda")
w = torch.randn(100)  # 默认通常在 CPU
z = x + w             # 设备不匹配,通常会报错

排查时检查输入、权重、标签以及中间张量的 .device。

3. 为什么直接用 time.time() 测 GPU 经常不准?

GPU 操作常常是异步提交的。CPU 发出命令后可能继续执行后面的 Python 代码,而 GPU 此时还在计算。如果计时没有包含 GPU 真正完成工作的时间,就会把提交开销当成计算耗时。

python 复制代码
import time
import torch

if torch.cuda.is_available():
    a = torch.randn(4096, 4096, device="cuda")
    b = torch.randn(4096, 4096, device="cuda")

    torch.cuda.synchronize()
    start = time.perf_counter()
    c = a @ b
    torch.cuda.synchronize()
    elapsed = time.perf_counter() - start
    print(f"elapsed: {elapsed:.4f} seconds")

同步是为了让计时边界包含本次 GPU 计算完成的时间。这个例子只演示基本原则,不能直接当作严谨的性能基准:正式 benchmark 应预热、重复测试、控制后台负载和显存状态,报告中位数或分布;更精细的测量可用 CUDA Events 或 Profiler。

十二、性能优化应该从哪里下手?先找瓶颈,不要先调参数

现象 可能原因 第一轮排查方向
小任务用 GPU 更慢 启动和数据传输占比太高 测端到端耗时,减少碎片化操作
GPU 利用率不高 工作量不足、CPU 供数慢、同步或依赖阻塞 检查数据加载、Batch、算子调用链和同步点
显存不足 / OOM 权重、激活、梯度、优化器状态或缓存占用过大 调整 Batch、精度、梯度累积和内存生命周期
计算核心没跑满 访存低效、Kernel 太碎、工作分布不均或资源占用受限 用 Profiler 定位,检查访问模式、融合和并行配置
增大线程数反而变慢 寄存器/共享内存消耗增加,驻留 Block 变少,或配置不匹配 对多个配置做可重复测量
第一次运行明显慢 初始化、上下文创建、Kernel 加载或缓存预热 分开统计冷启动与稳态性能

实际优化闭环建议这样做:

  1. 先有正确的基线: 测当前代码的端到端耗时和结果正确性。
  2. 再找时间花在哪里: 区分 CPU、数据传输、Kernel、同步和后处理。
  3. 一次只调整一类因素: 不要同时改 Batch、精度和多个算子,否则难以判断效果来源。
  4. 同样的环境重复测量: 记录硬件、驱动、CUDA/PyTorch 版本、输入形状、数据类型与测量方法。
  5. 比较收益和成本: 性能提升是否显著?是否影响精度、稳定性、显存或维护成本?

常用工具各管什么?

  • PyTorch Profiler: 观察模型算子耗时、调用关系和内存活动。
  • Nsight Systems: 看 CPU/GPU 工作、Kernel、传输和同步的时间线。
  • Nsight Compute: 进一步分析单个 CUDA Kernel 的执行与硬件利用指标。

不要只盯 GPU 利用率百分比。利用率高不自动意味着实现高效;利用率低也不一定意味着存在问题------一个很短、延迟受限的请求可能就无法填满整张卡。

十三、初学 CUDA 最容易踩的 10 个坑

  1. GPU 不等于 CUDA: 一个是硬件,一个是编程平台与生态。
  2. 把 GPU 线程当作操作系统线程: 两者的调度模型和执行方式不同。
  3. 认为所有逻辑线程都同时运行: 实际并发受硬件资源限制。
  4. 假设 Block 按编号顺序执行: 普通 Kernel 不保证这种顺序。
  5. 把 __syncthreads() 当全局屏障: 它是 Block 内同步机制。
  6. 忘记边界判断: 向上取整启动 Block 后,最后一组线程可能越界。
  7. 把共享内存当作无限资源: 它容量有限,过量使用可能降低并发驻留能力。
  8. 忽略 CPU-GPU 传输: 只比较 Kernel 时间容易误判端到端收益。
  9. 不做同步就计时: 异步提交可能让结果严重失真。
  10. 没做 Profiling 就写自定义 Kernel: 已经高度优化的库可能比手写实现更好,维护成本也更低。

十四、如何判断一个任务是否值得放到 GPU?

可以用这几个问题做初筛:

  • 是否有大量相似的数值操作?
  • 数据规模是否足够大,能够摊薄启动和传输成本?
  • 数据是否可以在 GPU 上连续完成多步操作,避免反复来回搬运?
  • 任务是否有大量依赖关系或高度不规则分支?
  • 是否有成熟库已经优化了该类算子?
  • 是否测量过 CPU 基线、GPU 端到端时间和正确性?

如果是大型矩阵运算,GPU 通常值得优先评估;如果只是少量简单元素操作,CPU 可能足够好。最终答案要靠真实工作负载测量,而不是只靠硬件宣传参数。

十五、本讲总结:把整个系统串起来

text 复制代码
算法/模型:定义要进行哪些数值计算
        ↓
框架:把操作组织成张量算子和计算图
        ↓
CUDA 与优化库:提供并行计算、内存和 Kernel 执行机制
        ↓
GPU:由 SM 和计算执行资源处理大量线程
        ↓
显存/缓存/共享内存:提供数据存放与访问路径
        ↓
Profiling:找出计算、内存、传输或同步瓶颈
        ↓
优化:调整算子、数据布局、批量方式与并行配置

本讲必须掌握的结论:

  1. CPU 偏向复杂控制和低延迟任务;GPU 偏向大量相似工作的高吞吐处理。
  2. CUDA 是 NVIDIA 的 GPU 编程生态;Kernel 是在 GPU 上并行执行的函数。
  3. CUDA 的逻辑结构是 Thread、Block、Grid;Warp 是理解 SIMT 执行的重要概念。
  4. 全局索引常写作 blockIdx.x * blockDim.x + threadIdx.x,并要做边界检查。
  5. GPU 的实际性能既取决于计算单元,也取决于显存、缓存、访问模式、数据传输、Kernel 启动、同步和软件实现。
  6. GPU 操作可能异步执行,测量时间前要保证计时边界正确。
  7. 优化的标准不是代码看起来更底层,也不是利用率数字更大,而是同一任务在正确性不变的情况下得到可重复的性能收益。

自测题

1. 为什么大模型适合 GPU?

因为神经网络包含大量矩阵和张量运算,具有可并行处理的结构;但能否加速仍取决于任务规模、内存访问和软件实现。

2. Thread、Block、Grid 各指什么?

Thread 是工作实例,Block 是可协作的一组线程,Grid 是一次 Kernel 启动中的所有 Block。

3. 为什么 blocks = (N + threads - 1) / threads 后,还需要 if (i < N)?

因为 Block 数量向上取整后,启动的逻辑线程可能多于实际元素数;边界检查用于避免越界读写。

4. 为什么 GPU Kernel 很快,但整个程序没快多少?

因为总时间还包含数据准备、CPU-GPU 传输、Kernel 启动、同步和后处理;这些开销可能占较大比例。

5. 为什么要先 Profiling 再优化?

因为瓶颈可能在 CPU、内存、数据传输、同步或某个算子,盲目调整线程数或手写 Kernel 未必解决实际问题。

6. __syncthreads() 能否让整个 Grid 的所有 Block 同时等待?

不能,它用于当前 Block 内线程同步,不能作为普通 Kernel 的全 Grid 全局屏障。

参考资料

  1. NVIDIA 官方文档:CUDA Programming Model
  2. NVIDIA 官方文档:Writing CUDA Kernels
  3. NVIDIA 官方文档:CUDA Toolkit Documentation
  4. PyTorch 官方文档:CUDA semantics

下一讲预告:第17讲|Tensor Core、HBM、SRAM、Kernel 优化与 FlashAttention。

第16讲回答"GPU 如何组织并行计算",第17讲将继续回答"为什么某些 GPU 算子能跑满硬件、某些却被内存访问和数据搬运卡住"。


《AI技术总监级拆解大模型》系列第16讲。内容按原理、执行模型、代码、性能分析与工程实践展开;硬件细节以对应 GPU 架构和软件版本的官方文档为准。

相关推荐
nap-joker1 小时前
多维整合分析揭示了遗传结构、风险因素及脑部衰老的健康后果
人工智能·生物年龄·dense-net·人口统计学·生活方式·常见与罕见遗传变异
一只废狗狗狗狗狗狗狗狗狗1 小时前
深度学习为什么好?
人工智能·深度学习
guslegend1 小时前
工程地基、Provider 与 ReAct 循环:Agent 核心能力的设计、实现与验收
人工智能·agent·react·架构设计·spring ai
桃西西呀1 小时前
Spring AI Alibaba 之九:我让 Agent 接着上一轮往下聊,它却只还给我一条消息,多轮记忆到底藏在哪
人工智能·spring·llm
10年前端老司机1 小时前
一次业务迭代:聊聊知识库多版本可追溯审核流程怎么做
人工智能·后端·agent
呆萌很1 小时前
长尾分类(Long-tailed Classification)方法汇总
人工智能·分类
for_ever_love__1 小时前
LangChain Agentic RAG:让 Agent 自己决定要不要检索、检索几次
人工智能·golang·langchain·rag·langgraph·agentic·自适应检索
Fxrain1 小时前
[Paper-Reading] CUAs 安全与隐私威胁综述
人工智能·安全·agent·智能体
乱世军军1 小时前
安装最新版本
人工智能