本文主要是介绍不愧是大厂!面了百度大模型算法工程师,收获了很多!,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
节前,我们组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂同学、参加社招和校招面试的同学,针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。
今天整理我们社群粉丝分享的算法岗方向面试题,分享给大家,希望对后续找工作的有所帮助。喜欢记得点赞、收藏、关注。更多技术交流&面经学习,可以文末加入我们交流群。
大家好,我是过年某985研二,过完年打算找大厂实习 offer,本文章主要记录了本小菜研找实习的坎坷历程,欢迎大佬们给建议
应聘岗位:百度大模型算法工程师
1. 自我介绍
在自我介绍环节,我清晰地阐述了个人基本信息、教育背景、工作经历和技能特长,展示了自信和沟通能力。
2. 技术问题
python多进程和多线程
在Python中,多进程和多线程都是并发编程的两种实现方式,它们允许程序同时执行多个任务。以下是两者的主要区别:
- 内存模型与资源隔离:
-
多线程(Multithreading):在一个进程中创建多个线程,这些线程共享同一进程的内存空间,包括全局变量、堆区等资源。这意味着线程间可以直接读写同一块内存区域,但也因此需要更多的同步机制来避免数据竞争和死锁。
-
多进程(Multiprocessing):每个进程有自己的独立地址空间,不直接共享内存或其他资源。进程之间的通信和数据交换必须通过IPC(Inter-Process Communication,进程间通信)机制,如管道、队列、共享内存或网络套接字等方式实现。
- 性能与切换开销:
-
多线程:由于线程间的切换通常比进程间的切换更快,因为不需要切换到不同的内存空间,所以理论上多线程有更低的上下文切换开销。然而,在Python中,由于GIL(全局解释器锁)的存在,对于CPU密集型任务,即使在多核系统上,多线程也并不能有效利用多个CPU核心并行计算。
-
多进程:虽然进程切换开销相对较大,但可以不受GIL限制地在多个CPU核心上并行运行,适合于CPU密集型应用。而对于I/O密集型任务,由于等待I/O操作时线程能释放CPU给其他线程使用,故多线程有时也能提高效率。
- 同步与互斥:
-
多线程环境下,由于资源共享,同步问题更为复杂,需要使用锁、条件变量、信号量等手段进行线程安全控制。
-
多进程环境下的同步问题相对简单,但进程间的通信和同步也需要额外的工作。
- 异常处理与稳定性:
-
单个线程崩溃可能会影响到整个进程,即所有线程都会终止。
-
相对而言,一个进程中的某个线程崩溃不会直接影响到其他进程,因此多进程结构具有更高的健壮性。
- Python标准库支持:
-
Python提供了
threading
模块用于创建和管理线程。 -
对于多进程,Python提供了
multiprocessing
模块,它包含了进程池、队列、共享内存等多种工具,使得跨进程通信和同步变得相对容易。
根据具体的应用场景和需求选择多进程还是多线程,例如当任务之间存在大量的CPU运算且能并行化时,多进程更有优势;而在处理I/O阻塞较多的任务或者资源访问简单的场景下,多线程可能是更好的选择。
介绍一下 python协程?
1. 什么是协程? 协程是一种程序组件,允许在单线程环境下实现并发执行多个任务。不同于多线程和多进程,协程并不是操作系统层面的实体,而是由编程语言自身支持的一种轻量级线程概念。协程可以在用户态自由地挂起和恢复执行,其上下文切换完全由程序员控制,并且相比传统的线程切换开销更小,更适合处理I/O密集型任务。
2. Python中协程的实现方式:
-
生成器(Generator)与yield关键字:在Python中,协程早期通过生成器实现,生成器函数可以通过
yield
语句暂停并返回一个值给调用方,而当它被重新唤醒时,可以从上次离开的地方继续执行。这使得生成器可以用于模拟协程的行为,但直到引入asyncio库之前,生成器本身并不直接支持异步操作。 -
async/await关键字(Python 3.5及更高版本):Python 3.5开始引入了原生的协程支持,使用
async def
定义协程函数,以及await
关键字来挂起协程直到等待的任务完成。这些协程函数也被称为异步协程,它们与asyncio库紧密结合,实现了异步IO编程模型。 -
asyncio库:asyncio是Python标准库的一部分,提供了对协程、事件循环、Future和Task等异步编程结构的支持。通过asyncio,开发者可以构建高度并发的系统,其中的协程可以在等待I/O操作时让出CPU,从而避免阻塞整个线程。
-
第三方库如greenlet和gevent:在asyncio出现之前,也有第三方库如greenlet提供了协程功能,而gevent则基于greenlet提供了一套协同式并发模型,通过猴子补丁(monkey patching)改造Python标准库,使其支持协程。
3. 协程的优点:
-
资源消耗低,减少上下文切换成本。
-
提高系统吞吐量,特别适合于处理大量网络请求或文件读写等场景。
-
程序员可以直接控制执行流程,代码逻辑更为直观。
4. 协程的挑战:
-
对开发者提出了更高的要求,需要理解和掌握异步编程模型和错误处理机制。
-
异常处理和调试相对复杂,尤其是在长链条的异步调用中。
综上所述,Python中的协程为解决并发问题提供了新的思路和工具,使得编写高效、非阻塞的异步代码变得更加便捷和可维护。通过asyncio和其他相关技术,Python程序员能够充分利用现代硬件资源,构建高性能的并发应用程序。
介绍一下 进程,线程,一个进程里面多线程共享哪些资源?
进程和线程是操作系统中两种不同的执行实体,它们在资源管理和并发执行方面有着本质的区别:
进程(Process):
-
进程是一个程序在其执行过程中的一个实例,它是系统进行资源分配和调度的基本单位。每个进程都有自己的独立地址空间,这意味着不同进程之间的内存是相互隔离的,包括代码、数据、堆栈和其他资源。
-
每个进程拥有自己独立的全局变量、打开的文件描述符、堆和栈等资源,进程之间通过操作系统提供的进程间通信机制(IPC,如管道、共享内存、消息队列、套接字等)来进行信息交换和同步。
线程(Thread):
-
线程是进程中执行运算的最小单位,它是在进程内部创建的一个执行路径,是系统调度的最小粒度。
-
同一进程内的多个线程共享相同的地址空间,即它们可以直接访问同一块内存区域,包括全局变量、堆以及由进程打开的所有文件等资源。
-
每个线程有自己的程序计数器、寄存器集合和栈,但不拥有单独的地址空间,因此它们可以更高效地共享和传递信息,而无需复杂的IPC操作。
一个进程里面多线程共享的资源主要包括:
-
地址空间:所有线程共享同一个进程的虚拟内存空间,包括代码段、数据段(全局变量、静态变量)、堆区。
-
打开的文件描述符:所有线程可以访问同一进程中打开的文件,不需要重新打开。
-
信号处理函数:进程级别的信号处理函数对所有线程有效。
-
全局变量与共享对象:在同一进程中定义的全局变量和使用mutex/semaphore保护的共享数据结构都是线程间共享的。
-
系统资源(如网络连接、某些类型的句柄):只要这些资源不是线程特有的,在同一进程下的线程都可以访问。
需要注意的是,虽然线程共享资源能带来便利,但也需要采取适当的同步措施(例如互斥锁、条件变量、信号量等)来避免并发环境下的竞态条件和死锁等问题。
介绍一下 python 垃圾回收机制?
Python 的垃圾回收机制(Garbage Collection, GC)是一种自动管理内存的系统,用于检测和回收不再使用的对象所占用的内存空间。Python 内存管理主要包括以下几种策略:
- 引用计数 (Reference Counting)
-
Python 对每个对象维护一个引用计数器。
-
当创建一个新对象时,其引用计数为1。
-
每当新的引用指向该对象时,计数器加1;每当一个引用离开作用域或被赋值给其他对象时,计数器减1。
-
当一个对象的引用计数器降为0时,表明没有任何引用指向这个对象,这时,垃圾收集器会立即释放该对象所占用的内存。
- 循环引用处理:
-
引用计数无法解决循环引用问题,即两个或多个对象相互引用但没有其他地方引用它们的情况。
-
为了处理这类情况,Python 使用了“标记-清除”(Mark-Sweep)算法作为补充。
-
标记阶段:垃圾回收器遍历所有对象,标记活动对象(即从根对象开始可达的对象)。
-
清除阶段:未被标记的对象被认为是垃圾,会被垃圾回收器清理。
- **分代回收 (Generational Garbage Collection)**:
-
Python 的垃圾回收机制还采用了一种基于对象生存周期假设的优化——分代回收。
-
新创建的对象首先放在年轻代中,如果在若干次垃圾回收后,对象依然存在,则会被提升到老年代。
-
年轻代中的垃圾回收频率相对较高且速度快,而老年代则认为是长期存活的对象,因此垃圾回收频率较低。
通过这些策略的结合使用,Python 能够有效地管理和回收内存资源,避免出现内存泄漏等问题,并且能够在一定程度上提高程序性能。然而,垃圾回收并非实时进行,而是由Python解释器适时触发执行。
了解 LoRA 么?讲LoRA的原理?
LoRA(Low-Rank Adaptation):在机器学习领域,特别是自然语言处理中,LoRA是“Low-Rank Adaptation”的简称,是一种用于微调大型预训练模型的技术。
-
基本思想:在不改变原始预训练权重的基础上,通过引入可训练的低秩分解矩阵来调整模型参数,以适应特定任务或领域。
-
这种方法的优势:相较于全模型微调,它仅更新少数参数,因此可以显著减少计算资源消耗和潜在的过拟合风险,同时保留了预训练模型的泛化能力。
encoder-only, decoder-only, encoder-decoder的区别?
在深度学习和自然语言处理(NLP)领域中,Encoder-Only、Decoder-Only以及Encoder-Decoder架构是三种不同类型的神经网络结构,它们各自设计用于不同的任务:
- Encoder-Only架构:
-
定义与特点:这类模型仅包含编码器部分,主要用于从输入数据提取特征或表示。例如,在BERT (Bidirectional Encoder Representations from Transformers) 中,它是一个双向Transformer编码器,被训练来理解文本上下文信息,并输出一个固定长度的向量表示,该表示包含了原始输入序列的丰富语义信息。
-
用途:主要用于预训练模型,如BERT、RoBERTa等,常用于各种下游任务的特征提取,比如分类、问答、命名实体识别等,但不直接用于生成新的序列。
- Decoder-Only架构:
-
定义与特点:解码器仅架构专注于从某种内部状态或先前生成的内容生成新的序列,通常用于自回归式预测任务,其中每个时刻的输出都依赖于前面生成的所有内容。
-
优点:强大的序列生成能力,能够按顺序逐个生成连续的元素(如单词、字符),适用于诸如文本生成、自动摘要、对话系统等生成性任务。典型的Decoder-Only模型包括GPT系列(如GPT-3)。
- Encoder-Decoder架构:
-
定义与特点:这种架构由两个主要部分组成:编码器和解码器。编码器负责将输入序列转换为压缩的中间表示,解码器则基于这个中间表示生成目标输出序列。这种结构非常适合翻译、摘要生成、图像描述等任务,需要理解和重构输入信息后生成新序列的任务。
-
工作原理:编码器对源序列进行处理并生成上下文向量,解码器根据此上下文向量逐步生成目标序列。例如,经典的Seq2Seq(Sequence-to-Sequence)模型和Transformer中的机器翻译模型就采用了这样的结构。
总结起来:
-
Encoder-Only用于理解输入并生成其抽象表示,不涉及序列生成。
-
Decoder-Only专门用于根据之前的信息自动生成新序列,不接收外部输入。
-
Encoder-Decoder结合了两者的功能,首先对输入进行编码,然后基于编码结果解码生成新序列。
介绍一下 transformer?
Transformer是一种由谷歌在2017年提出的深度学习模型,主要用于自然语言处理(NLP)任务,特别是序列到序列(Sequence-to-Sequence)的学习问题,如机器翻译、文本生成等。Transformer彻底改变了之前基于循环神经网络(RNNs)和长短期记忆网络(LSTMs)的序列建模范式,并且在性能上取得了显著提升。
Transformer的核心创新点包括:
-
自注意力机制(Self-Attention Mechanism):Transformer模型摒弃了传统RNN结构的时间依赖性,通过自注意力机制实现了对输入序列中任意两个位置之间的直接关联建模。每个词的位置可以同时关注整个句子中的其他所有词,计算它们之间的相关性得分,然后根据这些得分加权求和得到该位置的上下文向量表示。这种全局信息的捕获能力极大地提高了模型的表达力。
-
多头注意力(Multi-Head Attention):Transformer进一步将自注意力机制分解为多个并行的“头部”,每个头部负责从不同角度对输入序列进行关注,从而增强了模型捕捉多种复杂依赖关系的能力。最后,各个头部的结果会拼接并经过线性变换后得到最终的注意力输出。
-
位置编码(Positional Encoding):由于Transformer不再使用RNN那样的顺序处理方式,为了引入序列中词的位置信息,它采用了一种特殊的位置编码方法。这种方法对序列中的每个位置赋予一个特定的向量,这个向量的值与位置有关,确保模型在处理时能够区分不同的词语顺序。
-
编码器-解码器架构(Encoder-Decoder Architecture):Transformer采用了标准的编码器-解码器结构,其中编码器负责理解输入序列,将其转换成高级语义表示;而解码器则依据编码器的输出并结合自身产生的隐状态逐步生成目标序列。在解码过程中,解码器还应用了自注意力机制以及一种称为“掩码”(Masking)的技术来防止提前看到未来要预测的部分。
-
残差连接(Residual Connections):Transformer沿用了ResNet中的残差连接设计,以解决随着网络层数加深带来的梯度消失或爆炸问题,有助于训练更深更复杂的模型。
-
层归一化(Layer Normalization):Transformer使用了层归一化而非批量归一化,这使得模型在小批量训练时也能获得良好的表现,并且有利于模型收敛。
正是以上这些关键特性共同构成了Transformer强大的序列建模能力,使其成为现代NLP领域的基石模型,并被广泛应用于BERT、GPT系列、T5等多种预训练模型中,极大地推动了NLP技术的发展。
介绍一下 flash attention?
-
核心思想:传统减少HBM的访问,将QKV切分为小块后放入SRAM中
-
核心方法:
-
tiling(平铺): 分块计算。在计算时通过分块将Q,K,V分块后,按块加载到内存中。
-
recomputation(重新计算):传统Attention在计算中需要用到Q,K,V去计算S,P两个矩阵,FlashAttention引入softmax中的统计量( , ℓ),结合output O和在SRAM中的Q,K,V块进行计算。
介绍一下 flash attention-2 ?
FlashAttention-2版本进一步优化了FlashAttention算法,使用了更好的并行化和工作分区方法,使得计算速度提高了2倍。FlashAttention-2还支持更高的头维数和多查询注意力等新特性,进一步提升了性能和灵活性。
介绍一下 fp32和fp16的区别,混合精度的原理?
FP32(单精度浮点数)与FP16(半精度浮点数)的区别:
-
存储大小:
-
FP32(Single-Precision Floating-Point Format)每个数值占用32位(4个字节),包括1位符号位、8位指数位和23位尾数(小数部分)。
-
FP16(Half-Precision Floating-Point Format)则每个数值仅占用16位(2个字节),结构包含1位符号位、5位指数位和10位尾数。
-
数值范围与精度:
-
FP32能表示大约从( 10^{-38} )到( 10^{+38} )范围内的数值,具有相对较高的精度,适合于对精度要求高的计算任务。
-
相比之下,FP16的数值范围较小,大约在( 6.10^{-5} )至( 65504 )之间,并且由于尾数位较少,其精度较低,容易出现下溢或上溢问题。**混合精度训练原理:**混合精度训练是一种结合了FP32和FP16的优点以加速深度学习模型训练过程的技术。在深度学习中,尤其是使用GPU进行大规模并行计算时,内存带宽和显存容量往往是性能瓶颈。
-
优势利用:
-
利用FP16进行矩阵乘法等操作可以显著减少内存消耗和数据传输量,从而提高计算速度和设备利用率。
-
而FP32则用于累积中间结果,避免因为FP16精度不足导致的梯度消失或者爆炸问题。
-
混合策略:
-
在混合精度训练中,通常会在网络层的前向传播和反向传播过程中将权重和激活函数保持在FP16格式,但在累加梯度时会先将它们扩大一定的倍数(损失放缩技术),然后在更新权重之前再缩小回去,这样既能利用FP16的优势,又能维持足够的精度进行有效的参数更新。
-
工具支持:许多深度学习框架如PyTorch、TensorFlow和NVIDIA的apex库都提供了混合精度训练的支持,使得开发者能够在不牺牲模型收敛性的情况下大幅加快训练速度和降低硬件资源需求。
介绍一下 beam search原理,与直接sample的区别?
Beam Search原理: Beam Search是一种用于序列生成任务中的启发式搜索算法,特别是在自然语言处理(NLP)领域中,例如机器翻译、文本生成等任务。在这些任务中,模型需要预测一系列输出(如句子中的下一个词),而输出序列的可能性随着序列的增长呈指数级增加。
具体流程如下:
-
初始化:设定一个宽度参数
beam width
,表示每一步保留的最优候选解的数量。 -
递归过程:从起始状态开始,模型会预测第一个词语的所有可能选项,并根据它们的概率保留前
beam width
个概率最高的选项作为候选路径。 -
扩展路径:对每个保留下来的候选路径,模型接着预测第二个词语,将当前词语添加到之前路径上,并计算新的完整路径的概率。再次保留概率最高的
beam width
条路径。 -
迭代求解:重复步骤3的过程,直到达到终止条件(如遇到结束符号或者达到预设的最大长度)。
最后,Beam Search返回的是整个搜索过程中找到的最高概率路径作为最终输出序列。
与直接采样(Sampling)的区别:
-
Beam Search:
-
是一种确定性策略,总是选择概率最高的若干选项继续进行下一轮生成。
-
能够保证生成结果具有较高的概率质量,但可能会牺牲一定的多样性,因为不是所有低概率的序列都被考虑。
-
可能导致过拟合于训练数据中出现频率较高的模式,产生“僵化”或“机械”的输出。
-
直接采样(Random Sampling 或 Top-k Sampling 等):
-
是一种随机策略,每次生成新词时,可以按照词汇表中每个词的概率分布进行随机抽样。
-
采样方法能够生成更加多样化的输出,更有可能探索到新颖和未见的序列组合,有助于解决Beam Search可能导致的过于保守的问题。
-
直接采样的不确定性较大,生成的结果不一定是全局最优解,而且对于较差的概率分布可能出现生成结果质量较低的情况。
总结来说,Beam Search旨在寻找最大概率路径,以确保生成结果的合理性和准确性,而直接采样则通过引入随机性来增强输出的多样性和创造性,两者在实际应用中可以根据需求权衡精度和多样性来进行选择。
3. Leetcode 题
类似 【42. 接雨水】
- 题目内容
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
``> 示例 2:```s
输入:height = [4,2,0,3,2,5]
输出:9
-
思路
对于每一列,我们求它左边最高的墙和右边最高的墙,都是重新遍历一遍所有高度,这里我们可以优化一下。
首先用两个数组,max_left [i] 代表第 i 列左边最高的墙的高度,max_right[i] 代表第 i 列右边最高的墙的高度。(一定要注意下,第 i 列左(右)边最高的墙,是不包括自身的,和 leetcode 上边的讲的有些不同)
对于 max_left我们其实可以这样求。
max_left [i] = Max(max_left [i-1],height[i-1])。它前边的墙的左边的最高高度和它前边的墙的高度选一个较大的,就是当前列左边最高的墙了。
对于 max_right我们可以这样求。
max_right[i] = Max(max_right[i+1],height[i+1]) 。它后边的墙的右边的最高高度和它后边的墙的高度选一个较大的,就是当前列右边最高的墙了。
这样,我们再利用解法二的算法,就不用在 for 循环里每次重新遍历一次求 max_left 和 max_right 了。
-
代码实现
class Solution:def trap(self, height: List[int]) -> int:res = 0 height_len = len(height)if not height_len:return res left_max = [height[0]]for i in range(1, height_len):left_max.append(max(height[i], left_max[i-1]))right_max = [height[height_len-1]]for i in range(height_len-2, -1, -1):right_max.append(max(height[i], right_max[height_len-i-2]))for i in range(1,height_len-1):res = res + min(left_max[i], right_max[height_len-i-1]) - height[i]return res
技术交流
前沿技术资讯、算法交流、求职内推、算法竞赛、面试交流(校招、社招、实习)等、与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度等名校名企开发者互动交流~
我们建了算法岗面试与技术交流群, 想要进交流群、需要源码&资料、提升技术的同学,可以直接加微信号:mlc2060。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。
方式①、微信搜索公众号:机器学习社区,后台回复:技术交流
方式②、添加微信号:mlc2060,备注:技术交流
用通俗易懂的方式讲解系列
- 用通俗易懂的方式讲解:不用再找了,这是大模型最全的面试题库
- 用通俗易懂的方式讲解:这是我见过的最适合大模型小白的 PyTorch 中文课程
- 用通俗易懂的方式讲解:一文讲透最热的大模型开发框架 LangChain
- 用通俗易懂的方式讲解:基于 LangChain + ChatGLM搭建知识本地库
- 用通俗易懂的方式讲解:基于大模型的知识问答系统全面总结
- 用通俗易懂的方式讲解:ChatGLM3 基础模型多轮对话微调
- 用通俗易懂的方式讲解:最火的大模型训练框架 DeepSpeed 详解来了
- 用通俗易懂的方式讲解:这应该是最全的大模型训练与微调关键技术梳理
- 用通俗易懂的方式讲解:Stable Diffusion 微调及推理优化实践指南
- 用通俗易懂的方式讲解:大模型训练过程概述
- 用通俗易懂的方式讲解:专补大模型短板的RAG
- 用通俗易懂的方式讲解:大模型LLM Agent在 Text2SQL 应用上的实践
- 用通俗易懂的方式讲解:大模型 LLM RAG在 Text2SQL 上的应用实践
- 用通俗易懂的方式讲解:大模型微调方法总结
- 用通俗易懂的方式讲解:涨知识了,这篇大模型 LangChain 框架与使用示例太棒了
- 用通俗易懂的方式讲解:掌握大模型这些优化技术,优雅地进行大模型的训练和推理!
- 用通俗易懂的方式讲解:九大最热门的开源大模型 Agent 框架来了
这篇关于不愧是大厂!面了百度大模型算法工程师,收获了很多!的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!