面灵AI→

联芸科技固件研发一面:Cache 命中率怎么统计与调优、RTMO 抓任务时长、合并有序链表去重

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 自我介绍,并介绍一个印象最深、收获最大的项目。
  2. Cache 命中率如何判断高低?怎么统计?
  3. 抓到 Cache miss 之后,具体怎么调优?
  4. 芯片每个核的 Cache 容量多大?
  5. 代码里的 volatile 变量,结合 Cache 应该如何优化或规避问题?
  6. RTMO 抓取任务执行时间,是硬件工具还是软件包?原理是什么?
  7. 采集到任务运行时长数据之后,如何分析使用?
  8. 项目日常使用什么调试工具?
  9. 介绍一下你的课题项目,以及课题相关的问题。
  10. 投屏笔试:合并两个有序链表并去重,讲讲你的代码思路?如果单个链表内部本身有重复节点怎么处理?
  11. 研究生专业课主要学哪些内容?
  12. 说说你的优点和缺点。

《参考解析》

Cache 命中率的统计先分清层级:硬件层面用 PMU 计数器(x86 的 perf stat -e cache-references,cache-misses,L1-dcache-load-misses,ARM 用 perf 或芯片厂商的性能计数器),算 1 - misses/accesses;软件层面靠插桩 + 仿真(QEMU / gem5 / 厂商的 trace 工具)或 RTOS 的任务级 profiling。判断高低要看基线:L1 通常 95% 以上、L2 80%~90%、L3 60% 左右算健康,但更重要的是和「同 workload 的历史值」比,绝对值意义有限。

抓到 miss 之后的调优按数据布局优先:把热点数据改成连续访问(数组代替链表、SoA 代替 AoS)、按 cache line(通常 64B)对齐并避免伪共享(多核写同一 line 的不同字段要 padding)、把大循环分块(blocking / tiling)让工作集塞进 L1、按行优先遍历二维数组、减少指针跳转和虚调用、必要的 prefetch 指令。指令侧看 i-cache:减少大函数内联膨胀、把冷路径移出热函数。

volatile 与 Cache 的关系要说清它不解决什么:volatile 只保证编译器每次都从内存读写、不优化掉访问、不重排同线程内对它的访问,但它不产生内存屏障(跨架构需要 atomic / mb())、也不保证原子性;涉及外设寄存器(MMIO)或 DMA 缓冲区时,还要处理 Cache 一致性——要么把缓冲区放 non-cacheable 区、要么在 DMA 前后做 cache clean / invalidate,否则 CPU 读到的是旧 line。

任务时长采集属于软件插桩(RTMO 这类在任务切换点打时间戳、算差值),和硬件 trace(ETM / 芯片的 instruction trace)是两条路;分析时看最大 / P99 而不是平均值,找长尾任务、看是否被中断或锁抢占打断,再对齐 CPU Load 曲线定位热点。

合并去重这题的关键是「两链表各自也可能有重复」:做法是三指针——a、b 分别遍历,另用一个 tail 维护结果链表,每次取较小者,若与 tail 的最后一个值相同就跳过(这一步同时干掉单链表内部重复),相等时两指针同时前进;任一链表走完后,剩下的继续按「与 tail 不同才接」的规则追加。整体 O(m+n)、O(1) 额外空间。面试官指出漏了内部重复,本质是只考虑了跨链表去重——这是这类题最常见的失分点。