写在前面

欢迎大家关注Rocky的公众号:WeThinkIn 欢迎大家关注Rocky的知乎:Rocky Ding 《三年面试五年模拟》AIGC/LLM/AI Agent算法工程师/开发工程师求职面试秘籍独家资源:【三年面试五年模拟】WeThinkIn/AIGC-Interview-Book,欢迎大家Star~
Rocky最新撰写的10万字AI Agent(AI智能体)深入浅出全维度解析文章: 深入浅出完整解析AI Agent(AI智能体)的核心基础知识
AIGC/LLM/AI Agent算法岗/开发岗求职面试内推学习社群(涵盖AIGC、LLM大模型、AI Agent、传统深度学习、自动驾驶、机器学习、计算机视觉、自然语言处理、强化学习、大数据挖掘、具身智能、元宇宙、AGI等AI行业最新面试干货经验与核心知识)欢迎大家加入:https://t.zsxq.com/33pJ0
大家好,我是Rocky Ding。
核心导读
多模态大模型面试往往把算法目标、显存预算、系统吞吐和代码实现放在同一条追问链上:为什么采用 GRPO?省掉 Critic 后,计算去了哪里?8 张 A100 怎样分配训练与生成?最后,能否把注意力的张量形状和边界条件写对?
这组百度多模态大模型一面问题覆盖 9 道技术问答与 2 道手撕题。理解它们的主线是:先确定训练信号,再核算数据、计算与状态的成本,最后用任务质量与可执行代码检验方案。 同一个“加速”结论,只有说明硬件、序列长度、视觉 token、并行方式和评测口径,才有可比较的含义。
下面按问题顺序展开。算法公式使用典型定义;系统配置用于说明选型依据,不代表已经在百度业务或 8 卡 A100 环境中获得了实测结果。
项目表达:把业务目标连接到实验依据
1.项目深挖
回答:
项目深挖不能只按技术栈报菜名,应沿着“业务目标 -> 数据与任务定义 -> 模型方案 -> 训练/推理 -> 评测 -> 上线约束”形成一条可验证的主线。先说明系统为谁解决什么问题、原流程的瓶颈是什么,再说明为什么选择当前模型和训练方法,以及自己真正负责的模块。
一个完整的项目回答至少包含以下内容:
如果是 Agent 或多模态 Agent,建议把一次任务描述为:
Input
→
Perception
→
Plan
→
Tool/Model Action
→
Observation
→
Verification
→
Final Result
\\text{Input}\\rightarrow\\text{Perception}\\rightarrow\\text{Plan} \\rightarrow\\text{Tool/Model Action}\\rightarrow\\text{Observation} \\rightarrow\\text{Verification}\\rightarrow\\text{Final Result}
Input→Perception→Plan→Tool/Model Action→Observation→Verification→Final Result
重点讲清模型负责生成候选决策,代码负责权限、schema、状态、预算和副作用控制。面试官继续追问时,可以具体展开一个最难的 badcase:它发生在哪一层,如何定位,尝试过哪些方案,最终用什么对照实验证明修复有效。这样项目深挖回答的是设计判断和工程归因,而不是框架名称。
训练目标:理解反馈信号与能力更新
2.ppo和grpo的区别
回答:
PPO 和 GRPO 都属于基于策略优化的强化学习方法,但关键差异在于优势估计和是否需要独立的 Critic/Value Model。
在常见的 LLM RLHF 实现中,PPO 训练系统通常维护当前策略
π
θ
\\pi_\\theta
πθ、冻结参考策略
π
r
e
f
\\pi_{ref}
πref、奖励模型以及价值模型。对采样轨迹计算回报和优势
A
t
A_t
At,然后用裁剪目标限制策略更新幅度:
L
C
L
I
P
(
θ
)
=
E
t
[
min
(
r
t
(
θ
)
A
t
,
clip
(
r
t
(
θ
)
,
1
−
ϵ
,
1
+
ϵ
)
A
t
)
]
L^{CLIP}(\\theta)= \\mathbb{E}_t\\left[ \\min\\left(r_t(\\theta)A_t, \\operatorname{clip}(r_t(\\theta),1-\\epsilon,1+\\epsilon)A_t\\right) \\right]
LCLIP(θ)=Et[min(rt(θ)At,clip(rt(θ),1−ϵ,1+ϵ)At)]
其中
r
t
(
θ
)
=
π
θ
(
a
t
∣
s
t
)
π
o
l
d
(
a
t
∣
s
t
)
.
r_t(\\theta)=\\frac{\\pi_\\theta(a_t|s_t)}{\\pi_{old}(a_t|s_t)}.
rt(θ)=πold(at∣st)πθ(at∣st).
PPO 的优势是优势估计较细,可以利用 token 级或时间步级 value;代价是需要训练和维护 Critic,显存、通信和训练稳定性成本较高。对语言模型,常见做法是加入相对参考模型的 KL 约束,控制策略偏移;这不是 PPO 算法定义中的必选组件。奖励也可以来自可验证规则或环境,不一定来自学习得到的奖励模型。
这里要区分两个“旧模型”:
π
o
l
d
\\pi_{old}
πold 是生成当前训练数据的行为策略快照,用于重要性比率;
π
r
e
f
\\pi_{ref}
πref 是正则化参照,通常保持冻结。它们的用途不同,不能在实现中混用。PPO 的裁剪是代理目标中的更新约束,也不等于给真实 KL 设置了严格上界。
GRPO 的典型做法是对同一个 prompt 采样一组回答,得到组内奖励
r
i
,
1
,
…
,
r
i
,
G
r_{i,1},\\ldots,r_{i,G}
ri,1,…,ri,G,用组内均值和标准差构造相对优势:
A
i
,
j
=
r
i
,
j
−
mean
(
r
i
)
std
(
r
i
)
+
ϵ
.
A_{i,j}=\\frac{r_{i,j}-\\operatorname{mean}(r_i)} {\\operatorname{std}(r_i)+\\epsilon}.
Ai,j=std(ri)+ϵri,j−mean(ri).
它不依赖单独的 Critic,而是用同一问题的组内相对表现近似优势,因此降低了 value model 的显存与拟合成本,特别适合数学、代码、结构化工具调用等有可验证 reward 的任务。代价是每个 prompt 需要生成多个 response,Rollout 成本高;如果一组回答奖励几乎相同,优势信号接近 0;奖励模型或规则不可靠时,组内排序会把错误偏好放大。
两者都不是“天然稳定”或“只适合某种模型”。实际选择要看 reward 是否可验证、Rollout 吞吐、Critic 成本、轨迹长度和任务方差。工程上还要监控 KL、clip fraction、奖励分布、组内方差、长度偏置、熵、任务成功率和通用能力。对于工具调用或多模态任务,reward 最好拆成格式合法、工具正确、任务完成、事实一致和安全等信号,不能只用一个模糊的模型评分。
组内优势是一种相对信号。例如同题四个回答奖励为
[
0
,
0
,
1
,
1
]
[0,0,1,1]
[0,0,1,1],采用总体标准差并忽略数值稳定项时,优势为
[
−
1
,
−
1
,
1
,
1
]
[-1,-1,1,1]
[−1,−1,1,1];若奖励全为
1
1
1 或全为
0
0
0,该组的奖励优势均为
0
0
0。这时奖励驱动的策略梯度消失,但若目标含 KL 项,其梯度仍可能存在。“全答对”和“全答错”都没有区分度,背后的数据难度问题却完全不同。

图 1 比较三种典型训练路线。GRPO 删除独立价值模型,却增加同题多回答采样需求;DPO 使用已有偏好对做离线优化。应比较完整训练闭环的成本,不能只比较常驻模型数量。
3.为什么要做dpo
回答:
DPO 的动机是:很多场景能够收集“同一个 prompt 下回答 A 比回答 B 好”的偏好数据,但直接做 PPO 需要在线 rollout、Reward Model、Value Model 和复杂的稳定性控制。DPO 从 KL 正则化 RLHF 的最优策略形式出发,消去显式奖励模型,直接用偏好对训练策略。
数据为
(
x
,
y
w
,
y
l
)
(x,y_w,y_l)
(x,yw,yl),其中
y
w
y_w
yw 是 chosen,
y
l
y_l
yl 是 rejected。DPO 的核心目标是:
L
D
P
O
(
θ
)
=
−
log
σ
(
β
[
log
π
θ
(
y
w
∣
x
)
π
r
e
f
(
y
w
∣
x
)
−
log
π
θ
(
y
l
∣
x
)
π
r
e
f
(
y
l
∣
x
)
]
)
.
\\mathcal{L}_{DPO}(\\theta)= -\\log\\sigma\\left(\\beta\\left[ \\log\\frac{\\pi_\\theta(y_w|x)}{\\pi_{ref}(y_w|x)} -\\log\\frac{\\pi_\\theta(y_l|x)}{\\pi_{ref}(y_l|x)} \\right]\\right).
LDPO(θ)=−logσ(β[logπref(yw∣x)πθ(yw∣x)−logπref(yl∣x)πθ(yl∣x)]).
训练时使用策略模型和冻结参考模型对 chosen/rejected 做 teacher forcing,只累计 completion token 的对数概率,不把 prompt、padding 或错误的 mask 算进回答概率。DPO 优化的是 chosen 与 rejected 相对参考模型的对数概率差距;它不保证每一步 chosen 的绝对概率都上升、rejected 的绝对概率都下降。在理论推导中,
β
\\beta
β 对应 KL 正则强度;在有限数据训练中,它也改变 sigmoid 的尺度和梯度,不能脱离学习率与训练时长单独解释。
做 DPO 的主要价值有三点:
但 DPO 不是免费午餐。它受偏好数据覆盖、标注一致性、chosen/rejected 质量和参考模型能力限制;如果数据存在长度偏好、位置偏好或标注者偏差,模型会学习这些伪相关;如果任务需要多步工具交互或环境反馈,静态回答偏好未必能教会正确的行动策略。实践中应同时评估偏好准确率、事实性、安全性、长度分布、KL 漂移、通用能力和真实任务成功率,并根据问题选择 DPO、IPO、KTO、ORPO 或在线 RL,而不是把 DPO 当作所有对齐问题的默认答案。
4.持续学习方法的分类
回答:
持续学习是让模型在数据分布、任务或知识不断变化时吸收新信息,同时尽量不破坏旧能力。它与简单地周期性重新训练不同,核心矛盾是“适应新分布”和“避免灾难性遗忘”。可以按记忆、参数更新和模型结构分为几类:
严格来说,回放、正则化、参数隔离与架构扩展是持续学习算法的主要分类;检索是系统层面的知识更新方案,周期性重训则是更新流程。它们可以组合,但 RAG 不直接解决参数更新造成的灾难性遗忘。评估时还需要说明任务边界是否可知、历史数据能否保留,以及测试时能否获得任务 ID。
选型要先判断变化的是知识、行为、任务还是输入分布:知识更新优先考虑检索;格式和行为变化可以考虑 SFT/Adapter/DPO;需要学习可验证长链路策略才考虑 RL;数据分布变化则要做回放、重加权和漂移监控。每次更新都要在新域、旧域、对抗集和安全集上做回归,使用旧能力保留率、增量收益、遗忘量、成本和延迟联合决策。
资源预算:把多模态GRPO拆成可测量的阶段
5.场景题:用8张a100的机器做7B vl模型的grpo训练如何训练加速,推理加速
回答:
这道题应先明确瓶颈。GRPO 对每个 prompt 需要生成一组回答,再计算 reward、优势和策略梯度;对 7B VL 模型,视觉编码、长图像 token、生成阶段 KV Cache 和训练阶段显存/通信都可能成为瓶颈。通常先用 profiler 测量 Rollout、视觉编码、训练 forward/backward、reward、All-Reduce/All-to-All 和 GPU 空闲时间,再决定优化顺序。
先给8卡场景一个可计算的基线
先问清 A100 是 40 GB 还是 80 GB,卡间是 NVLink/NVSwitch 还是主要经过 PCIe,7B 是否包含视觉塔,训练是全参数还是 LoRA,视觉塔是否冻结。8 卡总显存不等于任意单卡都能访问的统一显存池,状态能否放下取决于具体分片方式。
以
P
=
7
×
10
9
P=7\\times10^9
P=7×109 个可训练参数为例,若采用 BF16 权重与梯度、FP32 主权重和 Adam 两个 FP32 矩状态,持久训练状态约为
16
P
16P
16P 字节,即 112 GB(十进制)。这只是特定配置下的估算,未计激活、通信缓冲、参考策略、rollout 权重及 KV Cache;采用 FP32 梯度或不同优化器时必须重新核算。
同步训练的一轮耗时可先拆成:
T
s
t
e
p
=
T
r
o
l
l
o
u
t
+
T
r
e
w
a
r
d
+
T
l
o
g
p
r
o
b
+
T
u
p
d
a
t
e
+
T
s
y
n
c
+
T
o
t
h
e
r
.
T_{step}=T_{rollout}+T_{reward}+T_{logprob}+T_{update}+T_{sync}+T_{other}.
Tstep=Trollout+Treward+Tlogprob+Tupdate+Tsync+Tother.
若测得 rollout 占比为
f
f
f,只将它加速
k
k
k 倍,理想总加速比至多为
1
/
(
(
1
−
f
)
+
f
/
k
)
1/((1-f)+f/k)
1/((1−f)+f/k)。例如
f
=
0.7
,
k
=
2
f=0.7,k=2
f=0.7,k=2,总加速比约为
1.54
1.54
1.54,而不是
2
2
2。这是成本模型的示例计算,不是硬件实测。异步系统有阶段重叠,应进一步分析关键路径与队列积压,不能直接把各阶段时长相加。

图 2 中,同一个 prompt 生成
G
G
G 条回答,奖励通过组内比较转化为优势,再驱动训练更新。视觉缓存、KV Cache、行为策略版本和权重同步属于不同状态,各自都需要明确生命周期。
初始方案可以在 8 卡上采用训练与 rollout 分时复用:训练用 FSDP 或 ZeRO,生成阶段选择能容纳权重和目标 KV 容量的最小可行 TP,再利用剩余卡做副本并行。随后用实测吞吐决定是否拆分资源池;“4 卡生成、4 卡训练”只是待测候选,不能在未测瓶颈前当成最优配置。
推理与 Rollout 加速
训练加速
验收方式
优化前后至少记录:tokens/s、有效 response/s、端到端 step time、GPU 利用率、显存峰值、通信占比、reward 计算时间、训练吞吐、任务成功率、KL、组内 reward 方差和单样本成本。对于 8 张 A100,没有完整模型配置、图像尺寸、序列长度、并行策略和 group size 时,不能直接承诺某个固定加速倍数。正确的回答是先定位瓶颈,再做单变量消融,确认吞吐提升没有以视觉质量、训练稳定性或策略新鲜度为代价。
6.模型训练加速有什么方法
回答:
训练加速可以按“减少计算量、减少显存、减少通信、提高流水线利用率、减少无效数据”五个方向组织。
一个有说服力的优化闭环是:先建立固定 batch 和数据版本的基线,记录 step time 分解;每次只改一个变量;同时报告吞吐、峰值显存、数值稳定性和验证集效果;最后在目标硬件和真实数据分布上复测。不能只报单卡 FLOPS 或 GPU 利用率,因为无效 token 增多时 GPU 利用率可能上升,任务质量却下降。
7.deepspeed的三个阶段
回答:
这里通常指 DeepSpeed ZeRO 的三个阶段。它们都利用数据并行,但逐步减少每张 GPU 必须完整保存的训练状态:
| ZeRO-1 | 优化器状态 | 完整模型参数与完整梯度 |
| ZeRO-2 | 优化器状态、梯度 | 完整模型参数 |
| ZeRO-3 | 优化器状态、梯度、模型参数 | 当前计算所需的参数分片或临时聚合 |
设参数量为
P
P
P,混合精度训练还需保存参数、梯度和优化器状态,朴素数据并行中每卡都复制这些内容;ZeRO 通过在
D
D
D 张卡之间分片,使理想状态下每卡的持久化状态规模近似按
1
/
D
1/D
1/D 缩减,但实际还会有通信 buffer、临时 all-gather、激活和框架开销。
ZeRO-1 通信和实现风险较低,适合优化器状态占比很大的训练;ZeRO-2 进一步节省梯度显存;ZeRO-3 最省显存,可训练更大的模型,但参数在层计算前后需要聚合和释放,通信、配置复杂度和小 batch 性能代价更高。ZeRO-Infinity 还可以把部分状态卸载到 CPU/NVMe,但会受 PCIe、内存带宽和 I/O 影响。
需要区分 ZeRO 与 Tensor Parallel、Pipeline Parallel:ZeRO 主要分片数据并行中的训练状态,TP/PP 主要切分模型计算和层;它们可以组合。选择时要综合模型大小、序列长度、GPU 数量、互联带宽、checkpoint 需求和吞吐目标,而不是默认 ZeRO-3 一定最好。
在上述 16 字节/参数的假设下,数据并行度为
D
D
D 时,可以写出更精确的静态状态近似:
| 普通数据并行 |
16 P 16P 16P |
112 GB |
| ZeRO-1 |
4 P + 12 P / D 4P+12P/D 4P+12P/D |
38.5 GB |
| ZeRO-2 |
2 P + 14 P / D 2P+14P/D 2P+14P/D |
26.25 GB |
| ZeRO-3 |
16 P / D 16P/D 16P/D |
14 GB |
因此,只有 ZeRO-3 对这三类状态都实现了理想分片;ZeRO-1/2 每卡仍有不随卡数缩小的复制项。这张表是容量预算,不是运行峰值;不能据此判断 ZeRO-1 在 40 GB A100 上一定能跑,因为剩余空间还要承担激活和其他开销。
注意力与框架:理解缓存、调度与计算的分工
8.多头注意力的变体有什么
回答:
标准 Multi-Head Attention(MHA)为每个 Query 头配置独立的 Key/Value 头。设 Query 头数为
H
q
H_q
Hq,Key/Value 头数为
H
k
v
H_{kv}
Hkv:
- MHA:
H
q
=
H
k
v
H_q=H_{kv}
Hq=Hkv。表达能力完整,但自回归推理需要缓存最多的 K/V,显存和带宽开销大。 - MQA:
H
k
v
=
1
H_{kv}=1
Hkv=1。所有 Query 头共享一组 K/V,KV Cache 显著缩小,解码更快,但过度共享可能损失质量。 - GQA:
1
<
H
k
v
<
H
q
1<H_{kv}<H_q
1<Hkv<Hq。多个 Query 头分组共享一个 K/V 头,是质量、缓存和带宽之间常见的折中。每个 KV 头对应H
q
/
H
k
v
H_q/H_{kv}
Hq/Hkv 个 Query 头。 - MQA/GQA 的 KV 头扩展: 计算时把较少的 K/V 头按组广播给 Query 头,数学上仍是缩放点积注意力,主要变化在参数组织和缓存布局。
- MLA(Multi-head Latent Attention): 不直接缓存完整的每头 K/V,而是缓存低维 latent 表示,并在需要时结合 Query 投影重建注意力所需信息,从而在长上下文和高并发下进一步降低 KV Cache 压力。它不是简单把 GQA 的 KV 头数设为更小,具体结构还涉及低秩投影和位置编码设计。
- 局部/滑动窗口注意力: 每个 token 只关注局部窗口,降低长序列计算量,但会牺牲远距离直接交互,需要全局 token、稀疏连接或层间传播补足。
- 稀疏、块稀疏和线性注意力: 通过限制连接模式或改变计算形式减少
O
(
S
2
)
O(S^2)
O(S2) 成本,适合特定长度和任务分布,但需要硬件 kernel、质量和训练稳定性共同验证。
注意力变体的本质是同时改变三件事:表示能力、每 token 的 KV 状态大小和矩阵乘法/访存模式。自回归解码的主要瓶颈往往不是 QKV 投影本身,而是每一步读取历史 K/V 的显存带宽,因此降低 KV Cache 可以带来明显收益;但在短序列、大 batch 或 prefill 阶段,计算和并行度的权衡可能不同。回答时要区分 prefill 与 decode,不能笼统说“所有场景 GQA 都更快”。
对标准 MHA/GQA/MQA,自回归 KV Cache 可近似写成:
M
K
V
=
2
B
L
S
H
k
v
D
h
b
,
M_{KV}=2BLSH_{kv}D_hb,
MKV=2BLSHkvDhb,
其中
B
B
B 是并发序列数,
L
L
L 是注意力层数,
S
S
S 是已缓存长度,
b
b
b 是每个元素的字节数,系数
2
2
2 表示 K 和 V。它未计分页空洞、元数据和特定多模态架构的额外缓存。同样的
H
q
=
32
H_q=32
Hq=32,若将
H
k
v
H_{kv}
Hkv 从 32 降到 8,理想 KV 容量降为四分之一;这不等于总推理延迟也降为四分之一。

图 3 固定四个 Query 头,只改变 K/V 头的共享关系。FlashAttention 则通过分块与在线 softmax 减少注意力中间结果的显存读写,通常保留精确稠密注意力计算;它与改变头共享关系的 GQA、管理缓存分页的 PagedAttention 可以协同使用,不能互相替代。GQA 的头广播也不意味着必须物理复制 K/V 缓存。
9.verl等框架都如何进行加速的
回答:
以 verl 这类 LLM/Agent 强化学习框架为例,加速重点不是一个神奇算子,而是把 Rollout、Reward、训练更新和数据调度组织成高吞吐系统。不同版本和配置的实现会变化,因此应按公开能力和实际配置说明,不应随意承诺固定版本或倍数。
主要机制包括:
对 8 张 A100 的小规模集群,常见优先级是先确认 rollout 是否主导耗时,再选择 colocate 或 disaggregate;随后按模型大小和序列长度选择 FSDP/Megatron、TP/DP 和 checkpoint;最后优化 kernel、packing 和通信。任何“减少 group size”“训练推理解耦”都需要与 reward 方差、样本新鲜度、最终任务质量一起验证。
手撕题
手撕:MHA
回答:
设输入 query、key、value 的形状分别为 [B, Lq, D]、[B, Lk, D]、[B, Lv, D],在标准注意力中要求 Lk == Lv。头数为 H,每头维度为 Dh = D / H。计算过程为:
Q
=
X
q
W
Q
,
K
=
X
k
W
K
,
V
=
X
v
W
V
.
Q=X_qW_Q,\\quad K=X_kW_K,\\quad V=X_vW_V.
Q=XqWQ,K=XkWK,V=XvWV.
Attention
(
Q
,
K
,
V
)
=
softmax
(
Q
K
T
D
h
+
M
)
V
.
\\operatorname{Attention}(Q,K,V)= \\operatorname{softmax}\\left(\\frac{QK^{\\mathsf T}}{\\sqrt{D_h}}+M\\right)V.
Attention(Q,K,V)=softmax(Dh
QKT+M)V.
下面实现支持 Self-Attention 和 Cross-Attention,mask=True 表示允许关注,只接收布尔 mask。二维 [Lq,Lk] mask 可直接广播;每个样本的 padding mask 应扩展为 [B,1,1,Lk],每个样本的完整 mask 应扩展为 [B,1,Lq,Lk]。causal=True 仅用于 query/key 使用相同位置起点的等长自注意力,不支持带缓存偏移的增量解码。全屏蔽 query 的注意力聚合定义为零,最终输出可能仍含输出层 bias。
import math
from typing import Optional
import torch
from torch import Tensor, nn
class MultiHeadAttention(nn.Module):
def __init__(self, d_model: int, num_heads: int, dropout: float = 0.0):
super().__init__()
if num_heads <= 0 or d_model <= 0 or d_model % num_heads != 0:
raise ValueError("d_model must be divisible by num_heads")
self.d_model = d_model
self.num_heads = num_heads
self.head_dim = d_model // num_heads
self.q_proj = nn.Linear(d_model, d_model)
self.k_proj = nn.Linear(d_model, d_model)
self.v_proj = nn.Linear(d_model, d_model)
self.out_proj = nn.Linear(d_model, d_model)
self.dropout = nn.Dropout(dropout)
def forward(
self,
query: Tensor,
key: Tensor,
value: Tensor,
mask: Optional[Tensor] = None,
causal: bool = False,
) –> Tensor:
if any(x.ndim != 3 or x.shape[–1] != self.d_model
for x in (query, key, value)):
raise ValueError("inputs must have shape [B, L, d_model]")
if key.shape[0] != query.shape[0] or value.shape[0] != query.shape[0]:
raise ValueError("query, key and value batch sizes must match")
if key.shape[1] == 0:
raise ValueError("key sequence must be non-empty")
batch, query_len, _ = query.shape
_, key_len, _ = key.shape
if value.shape[:2] != (batch, key_len):
raise ValueError("key and value must have the same batch and length")
q = self.q_proj(query).view(batch, query_len, self.num_heads, self.head_dim)
k = self.k_proj(key).view(batch, key_len, self.num_heads, self.head_dim)
v = self.v_proj(value).view(batch, key_len, self.num_heads, self.head_dim)
q = q.transpose(1, 2) # [B, H, Lq, Dh]
k = k.transpose(1, 2) # [B, H, Lk, Dh]
v = v.transpose(1, 2) # [B, H, Lk, Dh]
# Accumulate low-precision score products in FP32 for this teaching version.
calc_dtype = torch.float32 if q.dtype in (torch.float16, torch.bfloat16) else q.dtype
scores = torch.matmul(q.to(calc_dtype), k.to(calc_dtype).transpose(–2, –1))
scores = scores / math.sqrt(self.head_dim)
allowed = torch.ones_like(scores, dtype=torch.bool)
if causal:
if query_len != key_len:
raise ValueError("causal=True requires aligned equal-length sequences")
allowed = allowed & torch.ones(
query_len, key_len, dtype=torch.bool, device=query.device
).tril()
if mask is not None:
if mask.dtype != torch.bool:
raise ValueError("mask must be boolean, True means allowed")
allowed = allowed & torch.broadcast_to(mask.to(query.device), scores.shape)
has_key = allowed.any(dim=–1, keepdim=True)
scores = scores.masked_fill(~allowed, float("-inf"))
# Avoid softmax(-inf, …, -inf), which produces NaN.
scores = torch.where(has_key, scores, torch.zeros_like(scores))
weights = torch.softmax(scores, dim=–1).masked_fill(~allowed, 0).to(v.dtype)
weights = self.dropout(weights)
output = torch.matmul(weights, v)
output = output.transpose(1, 2).contiguous().view(batch, query_len, self.d_model)
return self.out_proj(output)
复杂度为
O
(
B
H
L
q
L
k
D
h
)
O(BHL_qL_kD_h)
O(BHLqLkDh),即
O
(
B
L
q
L
k
D
)
O(BL_qL_kD)
O(BLqLkD) 的注意力矩阵计算,注意力权重额外占用
O
(
B
H
L
q
L
k
)
O(BHL_qL_k)
O(BHLqLk) 空间。面试中还要主动指出:缩放因子应使用 sqrt(head_dim) 而不是 sqrt(d_model);转置后合并维度前要 contiguous();mask 的语义、dtype 和广播形状要明确;现代实现可用 torch.nn.functional.scaled_dot_product_attention 或 FlashAttention,但不能因此省略数学和张量形状。
实现边界也属于正确性:如果用最小有限数屏蔽整行,softmax 会输出均匀概率,错误聚合本应全部屏蔽的 Value;若整行直接填负无穷,softmax 则可能产生 NaN。上面的实现先识别全屏蔽行,再将其注意力权重显式归零,保留有限的前向值和梯度。这里采用 FP32 计算低精度的分数矩阵是教学上的稳定性选择,会增加临时显存;生产中应优先评估融合 SDPA 内核。
查找两个正序数组的中位数
回答:
设两个正序数组分别为 A 和 B,长度为 m、n。目标是在不真正合并数组的情况下找到第 (m+n+1)//2 小和第 (m+n+2)//2 小的元素(按 1 开始计数)。最优方法是在较短数组上二分切分位置。
选择切分 i 个元素来自 A,则需要 j = half – i 个元素来自 B。合法切分要求:
A
[
i
−
1
]
≤
B
[
j
]
且
B
[
j
−
1
]
≤
A
[
i
]
.
A[i-1]\\le B[j]\\quad\\text{且}\\quad B[j-1]\\le A[i].
A[i−1]≤B[j]且B[j−1]≤A[i].
其中越界左值视为
−
∞
-\\infty
−∞,越界右值视为
+
∞
+\\infty
+∞。找到合法切分后,左半部分最大值为
max
(
A
[
i
−
1
]
,
B
[
j
−
1
]
)
\\max(A[i-1],B[j-1])
max(A[i−1],B[j−1]),右半部分最小值为
min
(
A
[
i
]
,
B
[
j
]
)
\\min(A[i],B[j])
min(A[i],B[j])。总长度为奇数时取左最大值,为偶数时取左右平均值。
from typing import List
def find_median_sorted_arrays(a: List[int], b: List[int]) –> float:
if len(a) > len(b):
a, b = b, a
m, n = len(a), len(b)
if m + n == 0:
raise ValueError("both arrays cannot be empty")
left, right = 0, m
half = (m + n + 1) // 2
neg_inf = float("-inf")
pos_inf = float("inf")
while left <= right:
i = (left + right) // 2
j = half – i
a_left = neg_inf if i == 0 else a[i – 1]
a_right = pos_inf if i == m else a[i]
b_left = neg_inf if j == 0 else b[j – 1]
b_right = pos_inf if j == n else b[j]
if a_left > b_right:
right = i – 1
elif b_left > a_right:
left = i + 1
else:
left_max = max(a_left, b_left)
if (m + n) % 2 == 1:
return float(left_max)
right_min = min(a_right, b_right)
return (left_max + right_min) / 2.0
raise ValueError("no valid partition; check input preconditions")
二分发生在较短数组上,因此时间复杂度为
O
(
log
(
min
(
m
,
n
)
+
1
)
)
O(\\log(\\min(m,n)+1))
O(log(min(m,n)+1)),额外空间复杂度为
O
(
1
)
O(1)
O(1)。边界包括一个数组为空、两个数组都为空、重复元素、负数和总长度为偶数。不能只用双指针合并到中点后宣称最优,那样时间复杂度是
O
(
m
+
n
)
O(m+n)
O(m+n);如果面试官只要求普通实现,双指针可接受,但应说明这是线性方案。
这里“正序”理解为非递减有序。函数以输入有序为前提,末尾异常不构成完整排序校验;有些无序输入也会碰巧找到一个局部合法切分。若要检测所有无序情况,需要额外
O
(
m
+
n
)
O(m+n)
O(m+n) 扫描。对极大 Python 整数,返回 float 还可能丢失精度,精确数值业务应改用整数或有理数返回约定。
二分为什么安全?当
A
[
i
−
1
]
>
B
[
j
]
A[i-1]>B[j]
A[i−1]>B[j] 时,从 A 取入左半边的元素太多,应左移;当
B
[
j
−
1
]
>
A
[
i
]
B[j-1]>A[i]
B[j−1]>A[i] 时,从 A 取入的元素太少,应右移。由于总在较短数组上搜索,
j
=
h
a
l
f
−
i
j=half-i
j=half−i 始终落在 B 的合法切分区间。算法是在维护左右半边的有序不变量,而不是对中位数数值本身做猜测。
复习收束:让每个结论都能接受追问
这组问题最终检验的是三个能力:能否解释优化目标如何得到学习信号,能否说明计算和模型状态如何占用硬件,能否在实现中维护数学定义与边界条件。PPO、GRPO 与 DPO 解决不同的反馈组织问题;ZeRO、GQA、FlashAttention 与推理调度分别作用于不同的资源开销。把它们放回同一个多模态训练闭环,才能解释为什么某个配置适用、在哪个阶段有效,以及什么证据会推翻当前选择。
面试准备可以从一份小而可复现的实验记录开始:固定数据和模型版本,测量 rollout、reward、log-prob 与 update 的耗时,再做一次单变量优化,同时报告任务成功率、KL、显存峰值和总耗时。对手撕题,除了正常例子,还要主动验证全屏蔽注意力、不同 Q/K 长度、空数组与重复元素。能够给出反例、适用条件和验收标准,比背出更多框架名称更有说服力。
推荐阅读
Rocky一直在运营技术交流群(WeThinkIn-技术交流群),这个群的初心主要聚焦于技术话题的讨论与学习,包括但不限于算法、开发、竞赛、科研以及工作求职等。群里有很多人工智能行业的大牛,欢迎大家入群一起学习交流~(请添加小助手微信Jarvis8866,拉你进群~)
1. 深入浅出完整解析AI Agent(AI智能体)的核心基础知识
2025年可以说是AI Agent全面落地应用的元年,因此Rocky在持续撰写对AI Agent的全维度解析文章:
深入浅出完整解析AI Agent(AI智能体)的核心基础知识
2. 深入浅出完整解析扩散模型DDPM、DDIM、Score-Based、SDE、LDM、Classifier/Classifier-Free Guidance、Rectified Flow核心基础知识
Rocky对扩散模型的本质原理与和核心基础知识进行了全面系统的深入浅出分析讲解,同时不断跟进补充扩散模型的最新技术发展,希望能给大家带来帮助:
深入浅出完整解析扩散模型DDPM、DDIM、Score-Based、SDE、LDM、Classifier/Classifier-Free Guidance、Rectified Flow核心基础知识
3. 入浅出完整解析FLUX.2、Seedream(即梦)、Z-image、GLM-Image核心基础知识
Rocky对AIGC时代“中场时刻”之后的主流AIGC创作大模型的核心基础知识进行了全面系统的深入浅出分析讲解,力求让大家通俗易懂理解AIGC时代的技术浪潮的本质价值:
入浅出完整解析FLUX.2、Seedream(即梦)、Z-image、GLM-Image核心基础知识
4. 深入浅出完整解析FLUX.1 Kontext和FLUX.1 Krea核心基础知识
Rocky对FLUX.1 Kontext和FLUX.1 Krea的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析FLUX.1 Kontext和FLUX.1 Krea核心基础知识
5. 深入浅出完整解析DeepSeek系列核心基础知识
Rocky对DeepSeek系列模型的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析DeepSeek系列核心基础知识
6. 深入浅出完整解析Stable Diffusion 3(SD 3)和FLUX.1系列核心基础知识
Rocky对Stable Diffusion 3和FLUX.1的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析Stable Diffusion 3(SD 3)和FLUX.1系列核心基础知识
7. 深入浅出完整解析Stable Diffusion XL(SDXL)核心基础知识
Rocky对Stable Diffusion XL的核心基础知识作了全面系统的梳理与解析:
深入浅出完整解析Stable Diffusion XL(SDXL)核心基础知识
8. 深入浅出完整解析Stable Diffusion(SD)核心基础知识
Rocky对Stable Diffusion 1.x-2.x系列模型的核心基础知识做了全面系统的梳理与解析:
深入浅出完整解析Stable Diffusion(SD)核心基础知识
9. 深入浅出完整解析Stable Diffusion中U-Net的前世今生与核心知识
Rocky对Stable Diffusion中最为关键的U-Net结构进行了深入浅出的全面解析,包括其在传统深度学习中的价值和在AIGC中的价值:
深入浅出完整解析Stable Diffusion中U-Net的前世今生与核心知识
10. 深入浅出完整解析LoRA(Low-Rank Adaptation)模型核心基础知识
对于AIGC时代中的“ResNet”——LoRA模型,Rocky进行了深入浅出的全面讲解:
深入浅出完整解析LoRA(Low-Rank Adaptation)模型核心基础知识
11. 深入浅出完整解析ControlNet核心基础知识
AIGC图像创作开源社区已经形成以Stable Difffusion/FLUX为核心,ConrtolNet和LoRA作为首要AI辅助工具的变化万千的AIGC图像创作工作流。
ControlNet正是让AI图像创作社区无比繁荣的关键一环,它让AIGC图像创作过程更加的可控,更有助于广泛地将AIGC算法解决方案应用到各行各业中:
深入浅出完整解析ControlNet核心基础知识
12. 深入浅出完整解析Sora、Seedance、keling等AI视频大模型核心基础知识
AI绘画和AI视频是两个互相促进、相互交融的领域,2024年无疑是AI视频领域的爆发之年,Rocky对AI视频领域核心的Sora、Seedance、Keling等大模型进行了全面系统的梳理与解析:
深入浅出完整解析Sora、Seedance、keling等AI视频大模型核心基础知识
13. 深入浅出完整解析AIGC时代Transformer核心基础知识
在AIGC时代中,Transformer为AI行业带来了深刻的变革。Transformer架构正在一步一步重构所有的AI技术方向,成为AI技术架构大一统与多模态整合的关键核心基座,大有一统“AI江湖”之势。Rocky也对Transformer模型进行持续的深入浅出梳理与解析:
深入浅出完整解析AIGC时代Transformer核心基础知识
14. 深入浅出完整解析ComfyUI、Diffusers、Stable Diffusion WebUI等主流AIGC创作框架核心基础知识
AIGC创作框架正是AIGC算法工作流的运行载体,目前主流的AIGC创作框架有ComfyUI、Diffusers、Stable Diffusion WebUI等。在传统深度学习时代,PyTorch、TensorFlow以及Caffe是传统深度学习模型的基础运行框架,到了AIGC时代,Rocky相信ComfyUI就是AIGC时代的“PyTorch”、Stable Diffusion WebUI就是AIGC时代的“TensorFlow”、Diffusers就是AIGC时代的“Caffe”:
深入浅出完整解析ComfyUI、Diffusers、Stable Diffusion WebUI等主流AIGC创作框架核心基础知识
15. 深入浅出完整解析ComfyUI、Diffusers、Stable Diffusion WebUI等主流AIGC创作框架核心基础知识
在AIGC时代中,如何快速转身,入局AIGC产业?如何成为AIGC/LLM/AI Agent算法/开发工程师?如何在学校中系统性学习AIGC/LLM/AI Agent知识,斩获心仪的AIGC/LLM/AI Agent算法/开发offer?
Don‘t worry,Rocky为大家总结整理了全面的AIGC/LLM/AI Agent算法/开发工程师成长秘籍,为大家答疑解惑,希望能给大家带来帮助:
手把手教你成为AIGC/LLM/AI Agent算法/开发工程师,斩获AIGC/LLM/AI Agent算法/开发offer!
16. AIGC产业的深度思考与分析
2023年3月21日,微软创始人比尔·盖茨在其博客文章《The Age of AI has begun》中表示,自从1980年首次看到图形用户界面(graphical user interface)以来,以OpenAI为代表的科技公司发布的AIGC模型是他所见过的最具革命性的技术进步。
Rocky也认为,AIGC及其生态,会成为AI行业重大变革的主导力量。AIGC会带来一个全新的红利期,未来随着AIGC的全面落地和深度商用,会深刻改变我们的工作、生活、学习以及交流方式,各行各业都将被重新定义,过程会非常有趣。
那么,在此基础上,我们该如何更好的审视AIGC的未来?我们该如何更好地拥抱AIGC引领的革新?Rocky准备从技术、产品、商业模式、长期主义等维度持续分享一些个人的核心思考与观点,希望能帮助各位读者对AIGC有一个全面的了解:
深入浅出全面解析AIGC时代核心价值与发展趋势(2025年版)
17. AI算法工程师的独孤九剑秘籍
为了方便大家实习、校招以及社招的面试准备,同时帮助大家提升扩展技术基本面,Rocky将符合大厂和AI独角兽价值的算法高频面试知识点撰写总结成《三年面试五年模拟》之独孤九剑秘籍:
【三年面试五年模拟】AIGC时代的算法工程师的求职面试秘籍(持续更新中)
18. 深入浅出完整解析AIGC时代中GAN(Generative Adversarial Network)系列模型核心基础知识
GAN系列模型作为传统深度学习时代的最热门生成式Al模型,在AIGC时代继续繁荣,作为Stable Diffusion/FLUX系列大模型的“得力助手”,广泛活跃于AlGC图像创作的产品与工作流中:
深入浅出完整解析AIGC时代中GAN(Generative Adversarial Network)系列模型核心基础知识
网硕互联帮助中心






评论前必须登录!
注册