【暑期实习】阿里云 AI infra一面复盘

先做代码题,再深挖算子优化、图融合和量化

这场阿里一面整体给我的感觉是,节奏比较紧,前面先处理了一个在线代码题,后面基本都是顺着项目经历往下深挖。代码题是“队列的最大值”,要求均摊 O(1) 地返回当前队列最大值,我当时用的是普通队列加单调双端队列这套常见思路:一个队列维护正常入队出队,另一个双端队列维护当前可能成为最大值的候选元素。这个题本身不算特别难,但相当于是先热一下身,也看你对基础数据结构是不是熟。

后面的主体还是项目追问,而且问得挺细。面试官先从我做过的算子优化、图优化这些经历切进来,重点问的是:你到底怎么判断哪些地方值得优化,哪些算子值得单独提出来做性能优化,哪些链路值得做融合。我当时的回答主线比较直接:先把不开图优化和开图优化的计算图都拉出来,对比前后变化,再看哪些高频算子没有被自动优化覆盖,哪些算子链在图里重复出现很多次。如果是单个算子在整张图里占比很高,就优先做单算子性能优化;如果是一串算子反复出现,而且中间依赖关系比较干净,就更适合做融合。这个逻辑听起来不复杂,但真问起来,还是会一路追到你怎么扫描图、怎么判断独立性、怎么决定要不要下手。

融合这一块问得尤其细。不是那种泛泛地问“会不会算子融合”,而是直接问你:如果一串算子里有中间结果被别的分支依赖,那你怎么办;如果有个常量被很多地方共用,你怎么判断能不能融。我这里回答的大意是,融合前一定先判断输入输出是不是独立,如果中间节点还被图里其他地方引用,那就要非常谨慎,很多时候这种链根本不该硬融;真正适合下手的,是那种输入相对单一、输出也不会被额外分叉使用的一整段链路。也就是说,判断“能不能融”其实比“怎么融”更重要,不然最后很容易为了追求图上看起来更少的节点数,反而把语义搞坏。

中间还聊到了算子执行流程和性能来源。面试官会顺着我做过的 add 类算子优化继续问,比如你说它是 latency bound,那具体慢在哪。我这里讲的是一个比较工程化的点:有些看起来很简单的二元算子,真正耗时的并不全在算数本身,而在输入输出 buffer 的准备、数据拷贝和不必要的内存分配上。比如如果能确认某个输入张量在当前图里是独立的、不再被其他节点使用,那就可以直接复用它的地址作为输出地址,而不是每次都新申请一块输出内存。这个优化本身不花哨,但在高频算子上是能真正省出时间的。

另一个比较深的部分是,他会继续追问你对 GPU 执行和数据搬运过程到底理解到哪一步。比如 Host to Device、Device to Host 这种显式拷贝在今天的框架里到底怎么发生,统一地址空间和显式地址空间的差别是什么,当前做的工作里有没有碰到更先进一些的地址管理或者互联能力。我这里能答上的还是偏现有工程里的实际体验:现在手上的这套东西仍然很依赖显式地分清 host 和 device、显式地处理数据搬运,而不是那种已经完全统一抽象掉的状态。这个地方能明显感觉出来,对方其实不是在考名词,而是在判断你对底层软件栈和硬件演进有没有概念。

量化这一块也被拿出来单独问了。主要不是问“你知道几个名词”,而是问 W8A8、FP8、AWQ/W4A16 这些方案到底差在哪,为什么权重和激活在很多场景下会采用不一样的精度策略,以及中间累加结果为什么通常要放到更宽的位宽里去承接。我这里答得相对老实,核心还是围绕两个点:一是权重和激活对量化误差的敏感性不完全一样,很多时候权重更适合压低精度,激活则更容易影响最终结果;二是矩阵乘这种成加过程,中间累加结果如果位宽不够,很容易直接溢出,所以实际实现里通常会留更大的累加空间,再在后面做反量化或者类型转换。感觉这一段面试官更想看的是你有没有把“量化”当成一个完整的数据流过程去理解,而不是只停在“能省显存”这句话上。

后面还问到了 TensorFlow 插件机制和 profiling。比如 TensorFlow 这套插件开发为什么让人觉得麻烦,和 PyTorch 的 extension 比起来差别在哪;再比如你现在手上有哪些工具可以观察 kernel 的性能瓶颈,能看到多细。我这边主要讲的是,TensorFlow 这套链路在开发体验上确实更重,注册、底层实现、对接调用这些步骤都更绕;profiling 这边,我平时会先用自己写的轻量级 timing 方法做粗筛,看看时间主要花在数据搬运还是计算,再用更细的工具去看更具体的 kernel 表现。至少到目前这个阶段,我可以比较稳定地判断一个 kernel 更偏访存瓶颈还是计算瓶颈,但再往 layout、cache、冲突模式这些更细的层面,还在继续补。

整体下来,这一面不像那种特别“压迫式”的面试,但问题其实挺实。代码题只是开场,真正拉开差距的还是后面这些追问:你是不是自己看过图,你知不知道什么时候该融、什么时候不该融,你是不是清楚性能到底慢在哪,你对量化和底层执行流程到底是“听说过”,还是能把它讲成一个完整过程。对我自己来说,这一面答得比较顺的是图优化筛选逻辑、单算子优化思路、量化和 kernel 观察方法;相对一般的是再往下走到更底层的硬件细节和互联实现时,自己的理解还不够系统。

#面试复盘##暑期实习##一面##阿里云##AI infra#
Ai infra 面试复盘 文章被收录于专栏

12345

全部评论
佬 打扰下 考虑我司么 考虑的话 可以看我主页帖子
点赞 回复 分享
发布于 04-11 14:40 上海

相关推荐

查看15道真题和解析
点赞 评论 收藏
分享
感觉Python相关的面经和八股很少,主包主要分享下自己的一些面试,都是一些基础,少数涉及项目最近面的一家1.最常使用的 Python 版本?常用3.6和3.12,提到新版本中字典的+=操作的字节码变为原子操作,以及3.14正在尝试移除GIL锁。2.提到了多线程,问对Python中进程、线程与协程的理解从操作系统轻量级进程(LWP)角度回答的,多线程、多进程都对应多个LWP,但是一个进程对应一个解释器,GIL锁导致多线程只能利用单核,而协程是在用户态通过事件循环实现的应用层调度,只对应一个LWP。3.这3个并发模型的应用场景?多线程常用于传统Web开发中IO密集操作;多进程用于启动多个Worker利用多核;协程更适用于处理IO密集型任务,但容易被计算操作阻塞事件循环,多线程则不会。4.举几个 Python 魔术方法的例子。举例说明了__new__(构造单例)、__init__(初始化)、__call__(类装饰器)、上下文管理器(__enter__/__exit__)和迭代器(__iter__/__next__)等方法。5.对元类的理解元类类的类,是控制类生成阶段的钩子,举例实习中曾见过通过元类为类的方法自动添加限流,但通常能用继承或装饰器解决的问题不会使用元类。6.提到类生成,问有没有了解过子类生成的魔术方法__init_subclass__不知道,之前没有了解过……7.静态注释覆盖率自己开发基本会全量覆盖注解和必要注释,以追求代码自解释性(其实想问的是类型注解,没理解对,不过也答了相关的内容)8.对 Pydantic 的理解Pydantic通过类型注解实现数据校验和序列化,V2版本用Rust重写核心以提升校验和序列化这种CPU密集型操作的效率,可使用Field对象和装饰器+自定义方法定义字段或字段间校验。9.Pydantic如何从类中读取声明并完成 Schema 校验?没看过这块源码,推断是从类的__annotations__私有变量中提取类型注解信息,然后再进行处理。10.是否尝试过用 Pydantic 对第三方或自定义类(不继承BaseModel)做声明?没有做过……11.开发中有遇到数据库死锁的情况吗?开发中未实际遇到过死锁,但举例可能场景,可通过在事务中按字段排序固定顺序操作数据库来预防和解决。12.接触过的数据库表或Redis Key最大数据规模有多大?因为实习项目都是ToB私有化部署,接触过最大也就单表不到千万级几百万的数据量,跟面试官说想考察优化和治理策略可以给场景。13.讲一下实习中提到的租户资源多线程查询慢的问题,是如何发现、排查和解决的?(面试官可能以为这是个数据库优化)通过本地打印线程耗时发现,根因是元类为调用其它SaaS接口的client的所有方法添加了粗粒度限流导致。14.DevOps 实践经验?实习项目中使用GitLab的CI/CD流水线,了解其YAML配置文件的写法及代码检查、依赖扫描等钩子作用。15.个人玩具项目中状态机和 Outbox 的设计(第一个问我玩具项目的面试官!)状态机是通过定义字典控制对象状态的合法流转以及流转动作;Outbox模式通过在数据库事务中新增本地消息表插入待发送消息,用定时任务补偿发送失败,来保证操作原子性与一致性。16.本地响应很快的接口,到线上需要6、7秒,会从哪些方面排查?采用分治思想,从前后端全链路、本地与线上环境差异、数据库、缓存网络延迟、以及服务器资源耗尽(如TCP连接队列满)等层面排查。(面试官说没有提到主要的用户前端请求进入服务器的完整链路,比如DNS解析、CDN分发等)总结:面试官很nice,其实主包一直是对自己对Python底层的理解还是很自信的,开发框架和一些常用的模块都看过源码,但是面试官还是能顺着我说的拷打我(基本上一般面试官想拷打我需要在他的场景追问才行,这个可以顺着我的理解追问),但是最后还是很认可主包的之前面的一家1.实习中数据模型初始化操作健壮性优化怎么做的?针对其它SaaS不同版本可能出现同一个接口不同的表现形式,通过读取环境变量切换执行逻辑,同时针对资源名称哈希值可能重复的问题,分别增加了版本判断校验逻辑和基于“实例名+删除时间”的联合唯一校验字段。2.Python是强类型还是弱类型?Python是强类型语言。3.Python是动态类型还是静态类型?Python是解释执行的动态语言,代码由Python虚拟机中的解释器逐行解释执行,但也会编译成.pyc字节码文件。因为运行时才知道数据类型,Python函数本来就能接受和返回不同类型 一些模块源码中常用Overload装饰器主要是为了通过静态检查工具和方便开发者阅读。4.Python有哪些数据类型?Python中一切皆对象,常用数据类型包括整型、浮点型、字符串、列表、字典、元组和集合。5.哪些数据类型是可变的,哪些是不可变的?整型是不可变对象,重新赋值其内存地址会变;列表是可变对象,修改内容其内存地址不变,并举例说明将可变对象作为函数默认参数会引发数据串扰问题。5.熟悉的魔术方法?老演员6.元类的理解依旧老演员7.既然很多能用继承解决,为什么一定要引入元类?只有继承解决不了问题的时候才需要用元类,比如框架设计让开发者继承就可以自动注册自定义插件而不需要加类装饰器,或者真的需要控制类的生成而不是类的表现。8.写基本SQL语句有哪些关键字?SELECT、FROM、LEFT JOIN、GROUP BY、WHERE、HAVING和LIMIT等常用关键字。9.SQL语句的执行顺序是怎样的?从FROM开始,然后SELECT选择列和行,最后LIMIT10.Django ORM分组写法记不清api了…但好像也说对了annotate总结:半小时初面,看主包底子没啥问题还要面下一个候选人就结束了……主包是误打误撞学的Python后端,最近也学了一些agent开发,当然时间紧没有太深入学也没有大量投递这些岗位,不过感觉如果面试得是用Python做agent开发的公司,应该这些也都可能会问(其实之前还有面的一家岗位写的后端,实际是agent,然后面完还给我发offer了,我的感受是其实agent开发和后端工程落地还是蛮像的…如果你不去深究大模型本身的话)
查看26道真题和解析
点赞 评论 收藏
分享
评论
点赞
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务