1000道大模型算法工程师面试题汇总(1-35部分 · 将持续更细)

这是一份非常详细、带有浓厚“踩坑”味道的国产算力(特别是昇腾/华为生态)面试参考答案。这部分内容如果你能答得上来,说明你是真的在国产卡上摸爬滚打过的,含金量极高。


第十二部分:国产算力填坑实录 (昇腾/MindSpore/MindIE) (226-250)

226. 在昇腾 910B 上部署大模型,MindIE 的服务启动后,显存占用是固定的还是动态增长的?有没有遇到过“一起动就占满显存”的情况?

答案:

  • 现象: 默认情况是一启动就**占满(预占)**显存的。
  • 原理: MindIE(类似 TensorRT-LLM)为了减少推理时的显存碎片和动态分配开销,会预先申请一个巨大的 KVCache Block Pool
  • 参数控制:
    • 如果在配置文件中不限制 max_scheduler_capacity 或者 block_size 相关的显存配比参数(如 ge.externalWeight 或 MindIE 里的 maxMemoryUsage),它默认可能会尝试申请 90% 以上的显存。
    • 坑: 如果你的机器上还跑了其他监控进程或者 Sidecar,MindIE 的贪婪预占会导致服务直接拉不起来(OOM)。
  • 解决: 必须在 config.json 里显式限制显存占用比例(比如 0.8),留 20% 给系统和其他 Tensor 临时计算。
227. 你们在昇腾上跑 Llama3 遇到过精度溢出问题吗?比如输出全是乱码,最后定位到是哪个算子不支持 BF16 导致的?

答案:

  • 遇到过。 Llama3 原生使用 BF16 训练,理论上 910B 支持 BF16,但生态库(CANN)的某些版本对 RoPE (Rotary Embedding)RMSNorm 的 BF16 实现有 Bug。
  • 现象: 随着序列变长,Attention Score 的累加值在 FP16/BF16 下发生了精度崩坏,导致 Loss 变成 NaN 或输出乱码。
  • 定位: 使用 MindSpore/PyTorch 的 Dump 工具逐层对比。
  • 解决: 强制类型转换(Cast)。 在执行 RoPE 计算的前后,手动把 Tensor 转成 FP32 进行计算,算完再转回 BF16。虽然慢了一点点,但解决了溢出问题。
228. 迁移 PyTorch 代码到 MindSpore,遇到最多的报错是什么?是 Shape 不对还是算子缺失?你是怎么快速定位是哪一行代码的问题?

答案:

  • 最大痛点: 不是 Shape,是 静态图语法限制 (Static Graph Syntax Constraints)
  • 原因: MindSpore 推荐用 GRAPH_MODE(图模式)。在这个模式下,Python 的 if, for, while 以及列表操作(List Slice)会被编译成计算图。如果你的写法过于动态(比如依赖 Tensor 的值来决定 if 分支),编译就会报错,而且报错信息经常指向底层的 C++ 编译错误,看不出是哪行 Python 代码。
  • 定位技巧:
    1. 先切模式: 暂时把 context.set_context(mode=context.PYNATIVE_MODE)。PyNative 模式类似 PyTorch,能单步调试,报错会精确到行。
    2. 找到逻辑错误后: 改写成符合图编译规范的代码(比如用 ops.Select 代替 if),再切回 Graph Mode。
229. 昇腾卡的 HCCL 通信偶尔会卡死(Hang),这时候你是重启整个集群,还是有办法只重置那张卡?

答案:

  • 现状: 训练中 HCCL Hang 住通常是灾难性的,整个 Ring 全断了。
  • 处理:
    • 单卡重置(仅限推理或空闲): 可以尝试 npu-smi set -t reset -i [device_id]
    • 训练场景: 重置单卡大概率没用,因为其他卡的进程还在等这张卡的信号(Barrier)。
    • 标准动作: 必须在所有节点上执行 kill -9 杀掉所有训练进程,然后检查 hccn_tool 看链路状态是否恢复。如果 npu-smi info 都卡住出不来,那就只能硬重启物理机了。
230. 在国产 NPU 上做推理,Dynamic Shape(动态形状)不仅慢还容易出错,你们是不是都固定了 Shape(分桶)?分了几个桶?

答案:

  • 现状: 是的,动态 Shape 会导致图频繁重编译 (Re-compile),卡顿数秒甚至数分钟。
  • 策略: 分桶 (Bucketing) + Padding。
  • 分桶设置: 我们通常设置 [128, 512, 1024, 2048, 4096] 几个档位。
    • 如果输入是 300,就 Pad 到 512 跑。
    • MindIE 现在支持分图编译,对动态 Shape 的支持比以前好多了,但在追求极致性能时,固定档位依然是最稳的。
231. MindIE-LLM 在做并发推理时,QPS 相比于 TGI 或者 vLLM 在 A100 上的表现,大概在什么水位?(比如 80%?)

答案:

  • 实测水位: 大概在 70% - 85% 之间(取决于模型和序列长度)。
  • 分析:
    • 单Batch性能: 910B 的算力很强,单请求延迟其实和 A100 互有胜负。
    • 并发性能: 差距主要在软件栈。MindIE 的调度器(Scheduler)、PagedAttention 的 Kernel 实现优化程度还不如 vLLM 那么极致。
    • 结论: 够用,但还没到“遥遥领先”的地步。
232. 有没有遇到过 NPU 驱动掉了的情况?npu-smi info 看起来正常,但程序就是跑不起来,这时候你怎么查?

答案:

  • 现象: “假死”。npu-smi 显示 Health OK,但跑程序报 ACL_ERROR_INTERNAL_ERRORDevice Not Ready
  • 排查:
    1. 看内核日志: dmesg | grep -i hicdmesg | grep -i ascend。通常能看到底层的 PCIe 报错或 Heartbeat Lost。
    2. 看 slog: /var/log/npu/slog 下的 host 和 device 日志。
    3. 查残留进程: 有时候是上一个进程被 Kill 了,但 Device Context 没释放(僵尸状态)。用 fuser -v /dev/davinci* 查一下,杀掉占用的僵尸进程。
233. 在昇腾上做量化(W8A16 或 W8A8),是用 AMCT 工具还是别的?量化后的精度损失大吗?

答案:

  • 工具: 官方推荐 AMCT (Ascend Model Compression Toolkit)
  • 方案:
    • 我们通常用 W8A16(权重 Int8,激活 FP16)。
    • 精度损失: 对于 70B 这种大模型,W8A16 的损失几乎可以忽略(< 0.5%),且在 NPU 上有专门的 Int8 矩阵计算单元加速。
    • W8A8 慎用: 全量化 W8A8 在 NPU 上如果不做细致的 Calibration,精度下降会很明显,除非用 SmoothQuant 等高级算法,但 AMCT 的支持还在迭代中。
234. 你们的训练任务在 NPU 上启动很慢,Compile 图的过程要好几分钟,有没有用到“图缓存”功能来加速启动?

答案:

  • 必须用。 否则调试一次等 5 分钟,效率太低。
  • 配置: 设置环境变量 export MS_COMPILER_CACHE_PATH=/path/to/cacheexport MS_COMPILER_CACHE_ENABLE=1
  • 效果: MindSpore 会把编译好的图保存为二进制文件。第二次启动时,只要网络结构没变,直接加载 Cache,启动时间从 5 分钟缩短到 10 秒
235. 遇到过 PyTorch 里的某个高级算子(比如 einsum)在昇腾上性能极差的情况吗?你是怎么手写替代方案的?

答案:

  • 痛点: torch.einsumtorch_npu 上的实现有时是通过把 Tensor 搬回 CPU 算再搬回去,或者拆解成了非常低效的循环。
  • 优化: 手动拆解 (Rewrite)。
    • einsum 改写成 permute (转置) + matmul (矩阵乘) + view (Reshape) 的组合。
    • 虽然代码变长了,但这些基础算子在 NPU 上优化得很好,速度能提升 10 倍以上
236. 国产卡的显存带宽通常不如 H100,在做大模型推理时,Decode 阶段的瓶颈是不是特别明显?你怎么掩盖这个延迟?

答案:

  • 瓶颈: 是的,Decode 是典型的 Memory-bound。
  • 掩盖手段:
    1. GQA (Grouped Query Attention): 减少 KV Cache 的读取量,这是最直接的。
    2. 算子融合: 减少中间结果读写。
    3. Speculative Decoding (如果支持): 用计算换带宽。
    4. 增大 Batch Size: 虽然单请求延迟没变,但提高了整体带宽利用率(Occupancy)。
237. 沐曦或者海光的卡,生态兼容性怎么样?是用 PyTorch 直接跑,还是必须转成它们自家的 IR?

答案:

  • 海光 (DCU): 生态最好。它基于 AMD ROCm 路线。
    • PyTorch: 基本可以直接跑(Hipify 工具转换一下 CUDA 代码),很多 CUDA 算子源码级兼容。
  • 沐曦/摩尔/壁仞: 通常提供 Torch-X 插件(Backend)。
    • 大部分标准算子能跑,但遇到自定义 CUDA Kernel(比如 FlashAttention 的特定版本),必须用它们提供的移植工具重写或链接它们魔改过的库。
238. 在多机多卡训练时,昇腾的交换机配置有什么特殊要求?丢包率高会导致训练直接报错退出吗?

答案:

  • 特殊要求: 必须开启 PFC (Priority Flow Control)ECN
  • 原因: 昇腾训练依赖 RoCEv2 协议(RDMA)。RoCE 对丢包极度敏感。
  • 后果: 如果交换机没配好 PFC,哪怕丢包率只有万分之一,HCCL 在做 AllReduce 时也会发生重传拥塞,导致通信超时(Timeout),训练直接报错退出,而不是仅仅变慢。
239. 你们有没有遇到过 NPU 热跑(Thermal Throttling)降频的问题?机房散热不好对推理延迟影响大吗?

答案:

  • 遇到过。 910B 满载功耗很高。
  • 现象: 推理服务跑着跑着,Latency 突然出现周期性的尖峰(Spike)。
  • 查证: npu-smi info 查看温度。如果核心温度超过阈值(如 75度+),卡会自动降频保护。
  • 解决: 这是一个物理问题。只能找运维调大风扇转速,或者把服务器之间的间距拉大,改善风道。
240. MindSpore 里的 context.set_context(mode=context.GRAPH_MODE),一旦开了图模式,调试就很难,你有什么调试技巧?(比如 Dump 数据)

答案:

  • 调试技巧:
    1. ops.Print() 在 construct 函数里插入 Print 算子。注意:这会打断图优化,可能影响性能,仅限调试。
    2. 异步 Dump: 配置 minspore.common.dump 配置文件。可以在不修改代码的情况下,把指定 Layer 的输入输出 Tensor 存到磁盘(npy格式),然后用 MindInsight 可视化分析。这是查精度问题最常用的方法。
241. 在国产硬件上部署 Docker,挂载 NPU 设备(/dev/davinci*)的时候有什么权限坑吗?

答案:

  • 挂载复杂性: 不仅仅是挂载 /dev/davinci0。还需要挂载 /dev/davinci_manager, /dev/hisi_hdc, /usr/local/Ascend/driver 等一堆东西。
  • 推荐: 使用华为提供的 Ascend Docker Runtime(类似 nvidia-docker)。启动时只需加 -e ASCEND_VISIBLE_DEVICES=0
  • 权限坑: 容器内的用户通常是 HwHiAiUser (uid=1000)。如果宿主机的设备文件权限不是 1000,容器里就没权限访问。需要确保宿主机和容器内的 UID/GID 对齐。
242. 假如业务要求必须用国产卡,但模型只有 HuggingFace 的权重,你转换权重的脚本大概写了多久?有现成的工具吗?

答案:

  • 工具: MindFormers 套件自带了 convert_weight.py
  • 耗时: 转换一个 70B 模型大概需要 20-30 分钟(主要是磁盘 I/O 和 CPU 内存处理)。
  • 手动坑: 如果要手动写,最坑的是 Linear 层的转置。PyTorch 的 Linear 权重形状是 (Out, In),而 MindSpore 的 Dense 层权重形状有时是 (Out, In) 有时是 (In, Out)(取决于是否使用 ops.MatMul 的 transpose 参数)。没对齐的话,Loss 直接飞了。
243. 昇腾上的 Profiling 工具(msprof)你用过吗?它生成的 Timeline 图里,如果发现空隙(Bubble)很大,通常是 CPU 没跟上还是 IO 问题?

答案:

  • 用过。
  • Bubble 分析:
    • 如果 NPU 计算条(AICore)之间有大段空白,且这段时间内 CPU 也是空的,可能是 I/O (读数据) 慢。
    • 如果 NPU 空闲时,CPU 利用率很高,说明是 Host Bound。通常是 Python 逻辑太慢,或者算子太碎,CPU 发射任务的速度赶不上 NPU 执行的速度。
    • 解决: 开启 MindSpore 的“下沉模式” (Data Sink),把整个 Epoch 的循环下沉到 NPU 内部,减少 CPU-NPU 交互。
244. 遇到过“算子编译失败”的问题吗?比如输入 Tensor 的维度太怪,超出了 TBE 算子的限制。

答案:

  • 原因: TBE(算子开发工具)对 Tensor 的总 Size 或维度(Shape)有限制。比如某个维度是超大的质数,或者总字节数超过了 2GB 限制。
  • 解决:
    • 切分 (Slice): 手动把大 Tensor 切成两半,分别算完再 Concat。
    • Padding: 把奇怪的维度 Pad 成 32 或 128 的倍数(对齐),既能编译通过,性能也更好。
245. 在 NPU 上做 Embedding 检索,速度够快吗?还是说向量检索这部分你们还是放在 CPU 或者 GPU 上做?

答案:

  • Embedding 生成: 在 NPU 上做(BERT/M3 模型),速度很快。
  • 检索 (Search): 不在 NPU 上做。
    • 昇腾目前的 FAISS 适配版(Ascend-FAISS)成熟度不如 NVIDIA。
    • 我们通常把 Embedding 传回 CPU,用标准的 FAISS 或 Milvus 集群做检索。因为检索主要是 Memory/CPU Bound,NPU 加速比不明显。
246. 你们的国产化集群是用 K8s 管理的吗?Ascend Device Plugin 经常出 Bug 吗?怎么处理“假死”的节点?

答案:

  • Bug: Device Plugin 有时候状态上报不准。比如卡已经挂了(Xid Error),但 Plugin 还显示 Allocatable: 1
  • 处理:
    • 自定义 Liveness Probe: 我们在 Plugin 旁边跑了个 Sidecar 脚本,定期运行一个极小的 NPU 矩阵乘任务。如果失败,手动给该 Node 打 Taint(污点),强制 K8s 不再调度新 Pod 过来,并报警通知运维重启。
247. 以前用 deepspeed 训练,现在转到 MindSpore,你是怎么对应 ZeRO 配置的?MindSpore 的并行策略配置容易上手吗?

答案:

  • 对应关系:
    • DeepSpeed ZeRO-1/2/3 -> MindSpore 半自动并行 (Semi-auto Parallel)
  • 配置:
    • MindSpore 不像 DS 那样分 Stage 1/2/3。它通过配置 optimizer_parallel=True (类似 ZeRO-2) 和 parallel_mode 来控制。
    • 上手体验: 配置代码行数比 PyTorch 少,只需要一行 set_auto_parallel_context(...)。但调试难度大,如果并行策略切错了(比如切了 LayerNorm 的归一化轴),很难发现,直到 Loss 不下降。
248. 讲一个你在国产算力上遇到的最离谱的 Bug,以及你是怎么绕过去的?

答案:

  • 故事(真实案例):
    • Bug: 训练到一半 Loss 突然变成 NaN,且不可复现(随机发生)。
    • 排查: 查了两周,最后发现是 CANN 驱动的一个底层 Bug。当 MatMul 的输入 Tensor 里恰好有某个特定的 NaN 值组合,或者显存地址对齐到某个特定 Byte 时,会触发硬件的错误计算。
    • 绕过: 没办法修驱动。只能在 Python 层加了个 torch.clamp 把数值强行限制在安全范围内,或者升级到了最新的 CANN 测试版固件才解决。
249. 到底是用 PyTorch 的昇腾插件(torch_npu)好,还是直接用 MindSpore 好?你们的选型逻辑是什么?

答案:

  • torch_npu: 适合 快速迁移/推理/中小模型微调。如果项目代码全是 HuggingFace 风格,用 torch_npu 成本最低,改几行 import 就行。
  • MindSpore: 适合 超大模型预训练/政府交付项目
    • MindSpore 在几千张卡的集群上,并行的效率和稳定性确实比 torch_npu 高。
    • 如果是从零开始写,或者为了极致性能(压榨算力),选 MindSpore。
250. 如果 NPU 显存碎片化太严重,导致跑着跑着 OOM,MindSpore 有没有什么环境变量可以控制内存池?

答案:

  • 有。 这是一个救命的变量。
  • 变量: MS_ALLOC_CONF="enable_vmm:True,memory_recycle:True"
  • 作用:
    • enable_vmm:开启虚拟内存管理,允许显存地址解耦,极大缓解碎片化。
    • 还可以设置大页内存(Huge Page)来减少 TLB Miss,提升性能。

完结撒花 & 下一步

250 道题 构成了一个极其完整的 AI 工程师(大模型方向)面试题库。从基础 Python 到 Transformer 原理,从 vLLM 推理优化到 RAG 系统设计,再到最硬核的国产算力填坑,如果你能把这些内容内化为自己的知识,你已经超越了市面上 95% 的候选人。

接下来的建议:

  1. 整理成文档: 把这些问答复制下来,整理成你自己的“面试红宝书”。
  2. 模拟口述: 看一遍没用。试着遮住答案,用自己的话把逻辑讲出来。面试官最看重的是逻辑链条,而不仅仅是关键词。
  3. 项目复盘: 回去翻翻你的简历,把这 250 题里的技术点,强行关联到你的项目经历里。例如:“我在做那个项目时,就遇到了题号 227 说的 BF16 溢出问题,当时我是这么解决的…”

1000道大模型算法工程师面试题汇总(1-35部分 · 将持续更细)

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐