ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

面试-Packing训练的方

面试-Packing训练的方 Varlen‑Packing 完整技术文档背景:Transformer 训练/推理 Prefill 阶段,输入多条长度不等的序列。传统做法做 Padding 补零到统一长度;Varlen‑Packing 将多条不等长序列首尾拼接成一维连续张量,完全去除 Padding token。本文覆盖:硬件基础 → CUDA编程模型 → FlashAttention 三维Grid设计 → Padding Batch 方案 → Varlen‑Packing 完整执行流程 → 空Block成因、长尾同步、收益与缺陷 → 优化方向。重要名词区分(极易混淆)CUDA Thread‑Block(PPT中的Block):GPU Kernel调度任务单元,Grid由大量Thread‑Block组成,部署到SM执行。软件调度概念,不是显存内存块。KV‑Cache Block(vLLM/SGLang推理框架):显存HBM上固定大小内存页,存储K/V向量,纯内存管理概念,和CUDA Thread‑Block无关。Tile:FlashAttention算法分片逻辑;一个Q‑Tile的计算任务映射给一个CUDA Thread‑Block。1 前置基础1.1 GPU硬件层SM(流式多处理器):GPU真正的计算硬件(类似于 “车间”)。一个SM上可以同时驻留若干个CUDA Thread‑Block(类似 “车间里面的小组” );Block一旦调度上SM,就要分配寄存器、Shared Memory资源。HBM高带宽显存:存放Q/K/V输入张量、输出张量、cu_seqlens元数据。访问HBM带宽昂贵,希望尽量减少无效数据读写。1.2 CUDA编程模型CUDA Kernel 启动时需要指定Grid 三维网格(dimX, dimY, dimZ)Grid( dimX, dimY, dimZ ) └── Thread‑Block( blockIdx.x , blockIdx.y , blockIdx.z ) └── Thread(线程)Grid:本次kernel全部任务的总容器,三维只是给每一个Thread‑Block分配唯一坐标,不是张量的数据shape。Thread‑Block:调度最小单位。一个完整Block整体分配给某一个SM。Block内部包含上百个并行Thread。约束:Kernel启动瞬间Grid总大小必须完全确定,运行过程中不能动态增加、删除Thread‑Block。必须等待Grid内所有Thread‑Block全部执行完毕,Kernel才会返回Host CPU。1.3 FlashAttention Tiling 算法回顾受限于 SM 片上 Shared Memory 容量,无法把完整长序列 Q/K/V 全部放到片上。将Q沿着序列方向seqlen切分:Q‑Tile,每块大小Br(示例 Br=128)将K/V沿着序列方向切分:KV‑Tile,每块大小Bc算法逻辑:循环加载KV‑Tile到Shared Memory(SRAM),逐个计算每个Q‑Tile的Attention输出;中间的S、P矩阵全程不写回HBM,只保存在片上(SRAM),节省显存带宽。一个Q‑Tile的全部计算任务,交给一个独立CUDA Thread‑Block执行。2 FlashAttention Varlen Kernel:三维Grid设计Grid定义:grid = ( seq_count , n_head , ceil(max_seq_len / Br) )维度参数含义为什么要设置这个维度grid.xseq_count逻辑独立序列的条数不同样本之间Attention完全独立,天然并行。Varlen‑Packing后数据已经压扁成一维,不再有数据Batch维度;x保存逻辑样本计数。grid.yn_head注意力头数量MHA多头注意力,每个头Q/K/V投影完全独立,头与头之间没有数据依赖。每个注意力头分配一组Thread‑Block,充分释放GPU并行能力。如果放在Block内部循环,会串行执行多头,浪费SM算力。grid.zceil(max_seq_len / Br)Q‑Tile分片最大数量以整个批次最长序列max_seq_len,计算最多会产生多少个Q‑Tile;z维度对应Q方向Tile分片索引q_tile_idx。三元组(seq_idx, head_idx, q_tile_idx)唯一标记一个Thread‑Block的任务:当前Block负责:第seq_idx号逻辑样本、第head_idx注意力头、第q_tile_idx号Q‑Tile的Attention计算。总Thread‑Block数量 =seq_count × n_head × ceil(max_seq_len / Br)示例输入3条不等长样本真实token长度:[128, 128, 4096]seq_count=3,n_head=2,Br=128,max_seq_len=4096ceil(4096 / 128)=32总Block = 3 × 2 ×32 =192个CUDA Thread‑Block3 方案A:传统Padding Batch(对比基线)3.1 处理逻辑将全部样本补零padding对齐到批次最长序列4096。输入张量shape:[B=3, max_seq_len=4096, hidden_dim]总存储token:3 ×4096 =12288,真实token仅4352,其余全部是padding零token。Grid:grid=(B=3, n_head=2, ceil(4096/128)=32),总Block=192。3.2 执行流程CPU启动kernel,提交全部192个Thread‑Block。每个Block拿到坐标(b_idx, head_idx, q_tile_idx),直接访问张量Q[b_idx, ...]。所有192个Block全部执行完整Attention计算;短样本后面的
返回列表