OA辅助 / 面试训练复盘

Anthropic Fellow OA|OA1 & OA2 题目+思路:GPU 分配与随机树 Debug

Anthropic Fellow OA 共 90 分钟、5 个 level 的 GPU 分配题,每个 level 是独立 py 文件、引用不可改的系统代码;OA2 是 debug 类,修复机器学习相关代码。本文完整还原两道真题:LLM 推理调度器与极端随机树的定位修复。

Anthropic Fellow OA:LLM 推理调度器 + 极端随机树 Debug
训练主题配图 · 非客户现场证明

Anthropic Fellow OA 一共 90 分钟,包含 5 个 level 的题目,主要围绕 GPU 分配。每个 level 是独立的 py 文件,需要引用系统代码的函数,且系统代码不能更改;越往后难度越大。OA1 做完后半小时内收到 OA2,OA2 是 debug 类型,主要修复给定代码里的 bug,机器学习相关。

OA1 真题:LLM 推理调度器

实现一个类似 vLLM 或 SGLang 的请求调度器。每个请求先进入 waiting 队列,完成 Prefill 后转为 admitted,再逐 Token Decode,达到 max_tokens 后结束。每个时间步可使用的 GPU 工作量不能超过 max_work:先按进入顺序为所有已接纳请求安排 Decode,每次消耗 1 单位;剩余容量再按到达顺序安排 Prefill,其消耗等于 prompt_len。如果第一个等待请求放不下,本轮立即停止,不能跳过它去调度后面较小的请求。

思路是维护 waiting、admitted、finished 三组请求,每个时间步从 max_work 开始计算剩余容量。先按进入顺序处理 admitted 请求,每个 Decode 一个 Token 消耗 1 单位,达到 max_tokens 后移入完成队列;再从 waiting 队首依次尝试 Prefill,只有 prompt_len 不超过剩余容量才接纳,否则立即停止,不能跳过当前请求。每轮返回本次安排的任务,同时更新请求状态和已生成 Token 数。

class Request:
    def __init__(self, id_, prompt_len, max_tokens):
        self.id = id_
        self.prompt_len = prompt_len
        self.max_tokens = max_tokens
        self.tokens_generated = 0
        self.prefilled = False

def schedule_step(waiting, admitted, max_work):
    work = max_work
    tasks = []
    for req in admitted[:]:
        req.tokens_generated += 1
        tasks.append((req.id, 'decode'))
        work -= 1
        if req.tokens_generated >= req.max_tokens:
            admitted.remove(req)
    while waiting and work > 0:
        req = waiting[0]
        if req.prompt_len > work:
            break              # 放不下队首,立即停止,不能跳过
        waiting.pop(0)
        req.prefilled = True
        admitted.append(req)
        tasks.append((req.id, 'prefill'))
        work -= req.prompt_len
    return tasks

关键约束有两个:先 Decode 再 Prefill;队首等待请求放不下就整体停止,不能为了填满剩余容量而跳过它。这模拟了真实推理引擎里「保序、不饿死」的调度语义。

OA2 真题:调试极端随机树

题目提供一份基本可运行的 Extremely Randomized Trees 实现,但代码中存在一些 Bug,可能导致程序崩溃或模型准确率异常。需要阅读 trees.py 的实现和 tests/test_trees.py 中的测试,根据失败用例定位并修复问题,不能修改原有测试或文档说明。不要求额外优化速度,但修复时也不能把原有的 NumPy 向量化操作替换成明显更慢的多层循环。

思路是先运行完整测试确定失败范围,再按单个测试逐步缩小问题。重点检查建树的终止条件、随机特征与阈值选择、左右子树样本划分、空节点处理、预测结果聚合及随机种子是否符合测试约定。修复时尽量保持原有接口和 NumPy 向量化结构,每改一处就重跑相关测试,最后执行完整测试确认崩溃和准确率问题都解决。

# 极端随机树里常见的一处隐患:空节点切分
def _split(node, X, y):
    if len(y) == 0:
        node.value = 0
        return
    if len(set(y)) == 1:
        node.value = y[0]
        return
    # 随机选择特征与阈值,NumPy 向量化切分
    feature = node.rng.integers(0, X.shape[1])
    threshold = node.rng.uniform(X[:, feature].min(), X[:, feature].max())
    left_mask = X[:, feature] <= threshold
    # 修复:切分后一侧为空时,退化为叶子,避免无限递归
    if not left_mask.any() or left_mask.all():
        node.value = y.mean()
        return
    node.left = _split(Node(), X[left_mask], y[left_mask])
    node.right = _split(Node(), X[~left_mask], y[~left_mask])

这类 debug 题的共性:崩溃往往来自空样本或退化切分导致的无限递归;准确率异常往往来自随机种子没固定、特征/阈值选择逻辑与测试约定不一致。从失败测试倒推,比通读全部代码高效得多。

FAQ

OA1 为什么队首放不下就要停止,不能跳过调度后面的小请求?

这模拟了真实推理引擎的「保序、不饿死」语义:跳过队首会让长请求被后面小请求持续插队、永远得不到 Prefill。保持队列顺序是正确性的核心约束。

OA2 的 debug 题和普通算法 debug 有什么区别?

OA2 是机器学习相关代码,bug 常出在空样本切分、退化节点、随机种子和向量化索引上,需要懂一点 ML 数据流,不能只靠语法排查。从失败测试倒推范围最高效。

参考来源

联系 VOPathway

如果你希望把这套方法用于自己的 OA 或 VO 准备,可以把目标岗位、当前阶段、面试时间和主要难点发给 VOPathway,我们会据此安排针对性的练习与复盘。

  • 微信:Coding0201
  • 邮箱:[email protected]
  • Telegram:@OAVOProxy
  • WhatsApp:+86 178 6396 8105

可提供 OA辅助、OA辅导、VO辅助与 VO辅导。文章用于训练参考,不代表相关公司的官方流程;实际安排请以候选人收到的通知为准。

每一步,都更接近准备充分的自己。

本文用于面试准备与训练复盘。公司名称仅用于标识题型素材主题,不代表官方合作或录用承诺。

预约一次训练复盘 ↗