面灵AI→

华为 AI 方向机考 9 月 18 日:10 道选择加全局位注意力编程题

轮次
笔试
时间
2026-09
来源
牛客网

《面试题目》

第 1 题:选择题

  1. 旋转位置编码(RoPE)把位置信息注入注意力的方式,正确的是? A. RoPE 把绝对位置向量直接加到 token 嵌入上;B. RoPE 只能用在编码器,自回归解码器不能用;C. RoPE 对查询和键做旋转变换,使点积携带相对位置;D. RoPE 无法外推到预训练长度以外的序列
  2. 矩阵 P 为 4×3,Q 为 3×5,乘积 PQ 的维数是? A. 3×5;B. 4×3;C. 4×5;D. 3×3
  3. 两个非零向量 a、b 均已单位化。内积 aᵀb 在数值上等于? A. a 与 b 的欧氏距离;B. a 与 b 的余弦相似度;C. a+b 的模长;D. abᵀ 的行列式
  4. 评测「只有一个标准答案」的选择题时,最常用的指标是? A. Accuracy;B. BLEU;C. ROUGE-L;D. Perplexity
  5. CUDA Kernel 里关于线程块与共享内存,正确的是? A. 同一 thread block 内可用共享内存通信,不同 block 不能靠它直接通信;B. 共享内存对整张 GPU 上全部线程全局可见;C. 把 thread block 开得越大,Kernel 一定更快;D. 共享内存的访问延迟与寄存器相同
  6. 高维函数逼近中,稀疏格点(sparse grids)用来缓解维数灾难。正确的是? A. 仍铺全张量积网格以保证精度;B. 只能用于低维问题;C. 一定能彻底消除维数灾难;D. 组合若干低维张量积空间,用更少节点保持较好逼近能力
  7. 标准正态分布中,随机变量落在区间 [-2, 2] 内的概率大约是? A. 68%;B. 50%;C. 95%;D. 99%
  8. Transformer 推理引入 KV Cache,主要是为了? A. 减少模型参数量;B. 缓存已生成 token 的 K、V,避免逐步重算;C. 在训练阶段加快收敛;D. 专门增强长序列建模能力
  9. 机器学习出现过拟合时,偏差和方差通常是? A. 高偏差、低方差;B. 高偏差、高方差;C. 低偏差、低方差;D. 低偏差、高方差
  10. 连续做两次逐元素运算:X = A∘B,再 Y = X + C。各张量形状相同,均含 2×10⁶ 个 FP16 元素(每元素 2 字节)。忽略缓存,所有数据都走 HBM 读写。未融合时总流量是多少?融成一个 Kernel 能省多少? A. 未融合 16MB,融合节省 8MB;B. 未融合 20MB,融合节省 4MB;C. 未融合 24MB,融合节省 8MB;D. 未融合 24MB,融合节省 16MB

第 2 题:全局位与窗口注意力(150 分)

给定三个整数矩阵 Q、K、V,尺寸均为 L × D,以及 G 个全局位置构成的集合 P。对位置 i,先确定可参与注意力的下标集合 C_i:

  • 当 i ∈ P 时,C_i = {0, 1, …, L-1}(全集);
  • 当 i ∉ P 时,C_i = {j | max(0, i-W) ≤ j ≤ min(L-1, i+W)} ∪ P(局部窗口再并上全局位置集合),集合内同一位置只计一次。

注意力分数 score(i, j) = Σ_{0≤x<D} Q[i][x] · K[j][x]。只保留 score(i, j) > 0 的位置,再从中选出至多 T 个分数最大的候选得到 A_i(分数相同时下标 j 较小者优先;正分数候选不超过 T 个则全部保留)。输出矩阵 O:A_i 非空时 O[i][x] = Σ_{j∈A_i} score(i, j) · V[j][x],A_i 为空时该行全 0。

  • 数据范围:L ≤ 10^4、D ≤ 64、T ≤ 16,全局位最多 32 个,非全局位 |C_i| ≤ G + 2W + 1 ≤ 289。
  • 输入:第一行五个整数 L D G W T;第二行 G 个整数表示全局位置集合 P(G = 0 时该行不存在);随后依次是 Q、K、V 三个 L × D 矩阵,每行 D 个整数。
  • 输出:L 行,每行 D 个整数,行内用空格分隔。
  • 样例输入:
5 2 2 1 2
0 3
1 0
1 0
2 0
0 1
1 1
2 0
1 0
3 0
0 2
-1 1
1 1
2 2
3 3
4 4
5 5
  • 样例输出:
11 11
11 11
22 22
13 13
10 10

《参考解析》

RoPE:靠旋转让点积带上相对位置

RoPE 不改变模型结构,而是在每个位置对 Q、K 施加一组按位置索引的旋转矩阵(把 head_dim 两两配对看成二维平面,旋转角与位置成正比)。这样 ⟨R_m q, R_n k⟩ 只依赖相对距离 m - n,注意力点积天然携带相对位置信息,所以选项 C 正确:它不是把绝对位置向量加到词嵌入上(那是可学习/正弦位置编码的做法),编码器和解码器都能用,也不是「无法外推」——恰恰相反,RoPE 的相对形式加上 NTK/线性插值、YaRN 这类频率缩放策略,是目前长度外推的主流手段之一。

选择题考点串讲:几个高频易混点

矩阵乘法只看首尾:(4×3)·(3×5) → 4×5,中间维度必须相等。单位化向量的内积就是余弦相似度(cos = a·b / (‖a‖‖b‖))。评测指标按任务类型选:单选/分类用 Accuracy,BLEU、ROUGE 用于生成式文本评测,Perplexity 衡量语言模型建模概率。正态分布要记住三个数:±1σ 约 68.3%、±2σ 约 95.4%、±3σ 约 99.7%。过拟合对应低偏差、高方差(训练集拟合得很好,换数据就抖)。稀疏格点是把若干低维张量积空间组合起来,用远少于全网格的节点数保住逼近能力,是缓解而不是彻底消除维数灾难。

CUDA 共享内存:作用域是单个 thread block

__shared__ 内存只对同一个 block 内的线程可见,是 block 内线程协作(如 tile 化的矩阵乘、归约)的通信媒介;跨 block 通信必须走全局内存并配合额外的同步(如 grid sync 或 kernel 拆分)。共享内存延迟远低于全局内存,但高于寄存器,且容量有限(每 SM 通常几十到上百 KB),开得过大反而会压低 occupancy。所以「block 开得越大越快」是错的——block 大小要匹配硬件 warp 数、寄存器用量和共享内存占用。

KV Cache:省的是重算,不是参数

自回归解码每步只产生一个新 token,但没有缓存就得把整段历史重新算一遍 K、V。KV Cache 把历史 token 的 K、V 存下来,每步只需算新 token 的 K、V 并与缓存拼接,把每步复杂度从 O(L²) 降到 O(L)。代价是显存:按 2 × 层数 × KV 头数 × head_dim × 序列长度 × dtype 字节数 估,Llama-2-7B fp16 约 0.5MB/token,长上下文下 KV 往往比权重更占显存。这也是 PagedAttention(分页管理 KV,减少碎片并支持前缀共享)和 GQA/MQA(减少 KV 头数)这类优化的出发点。

Kernel 融合与 HBM 流量:先算每个张量多大

每个张量 2×10⁶ 个 FP16 元素 × 2B = 4MB。未融合时,X = A∘B 要读 A、B 写 X(3 个张量 = 12MB),Y = X + C 再读 X、C 写 Y(又 12MB),合计 24MB;融合成一个 Kernel 后只需读 A、B、C、写 Y(4 个张量 = 16MB),省下 8MB。答案选 C。这道题考的是「逐元素算子为什么适合融合」:省掉的是中间张量在 HBM 上的往返流量,而这类算子本身算术强度低、时间几乎全花在搬数据上,所以融合收益接近流量节省比例。

编程题解法:按定义模拟 + 去重 + Top-T

思路直白,坑都在细节上。对每个位置 i 先构造候选集合 C_i:i 是全局位就扫全序列;否则取窗口 [max(0, i-W), min(L-1, i+W)] 再并入全局集合 P。窗口与 P 可能重叠,必须用访问标记数组去重,否则同一个 j 会被加权累加两次。然后对每个候选算点积 score = Σ Q[i][x]·K[j][x],丢掉 score ≤ 0 的,按 (-score, j) 排序取前 T 个(分数相同时小下标优先,所以排序键要带 j);A_i 为空则该行输出全 0,否则 O[i][x] += score · V[j][x]。

复杂度:O(L · (D·|C_i| + |C_i| log |C_i|)),非全局位 |C_i| = O(G + W),全局位是 O(L)(最多 32 个,可接受),空间 O(L·D)。实现注意用 long long 存分数与累加结果,点积可能溢出 int;输入用快速读入,cin 记得关同步。