收藏必备!一文搞懂MoE架构:DeepSeek MoE推理流程与SGLang框架实现详解 什么是 MoEMixture of ExpertsMoE是一种神经网络架构设计通过组合多个”专家”子网络来处理输入数据。其核心思想是不是让整个模型处理每个输入而是为每个输入动态选择最合适的专家子集。这种设计使模型能够在保持计算效率的同时显著扩大参数规模。本文简略梳理 DeepSeek MoE 结构的推理流程以及主流 SGLangv0.5.5 框架是如何进行推理希望能帮到大家~如有错误欢迎各位大佬指正。MoE 的结构MoE deepseek以 DeepSeek MoE layer 为例其包含 256 个路由专家和 1 个共享专家每个 Token 选择 Top-K 8 个路由专家再加权求和共享专家独立于路由网络。计算流程参考 SGLang 的 sglang/srt/models/deepseek_v2.py/ 中 class DeepseekV2MoE 实现。总体流程如下所示SGLang - deepseekv2.pyGategate 是一个 linear 线性层接收输入 hidden_states 并且为每个专家计算一个原始得分 logits。输入hidden_states shape [num_tokens, hidden_dim]输出router_logits shape [num_tokens, n_experts]# native代码为 logits F.linear(hidden_states, self.weight, None)Topk接收 router_logits 并决定每个 token 实际去哪个专家并计算相对应的权重。输入hidden_states shape [num_tokens, n_experts]输出topk_weights shape [num_tokens, K], topk_ids shape [k]native top-k 代码的计算过程def fused_topk_torch_native( hidden_states: torch.Tensor, gating_output: torch.Tensor, topk: int, renormalize: bool, correction_bias: torch.Tensor None, # 偏置项用于调整专家选择的公平性 ): if correction_bias is not None: n_router_experts gating_output.shape[-1] scores gating_output.softmax(dim-1) # 添加bias scores_for_choice scores_view(-1, n_router_experts) correction_bias.unsqueeze(0) # 计算top_k topk_ids torch.topk(scores_for_choice, ktopk, dim-1, sortedFalse)[1] # 取出top-k 对应的权重 # scores.shape [M, E] # topk_ids.shape [M, k], 专家编号 # 比如 # scores [[0.05, 0.10, 0.75, 0.10]] # softmax 后 # topk_ids [[2, 0]] # 选专家 2 和 0 # topk_weights scores.gather(1, topk_ids) # 结果 [[0.75, 0.05]] topk_weights scores.gather(1, topk_ids) else: assert ( hidden_states.shape[0] gating_output.shape[0] ), fNumber of tokens mismatch, {hidden_states.shape} vs {gating_output.shape} M, _ hidden_states.shape topk_weights torch.empty( M, topk, dtypetorch.float32, devicehidden_states.device ) topk_ids torch.empty(M, topk, dtypetorch.int32, devicehidden_states.device) topk_weights F.softmax(gating_output.float(), dim-1) topk_weights, topk_ids torch.topk(topk_weights, topk, dim-1) if renormalize: topk_weights topk_weights / topk_weights.sum(dim-1, keepdimTrue) return topk_weights, topk_idsDeepSeek V2/V3/R1 系列模型使用 grouped_topk 机制每个 token 只能选择固定数量的专家组然后在每个专家组内选择 top-k 个专家。具体的步骤如下所示按 expert group 分组选出 top-k groups这里代码中一般为 2 个 group在选中的 groups 内部再选 top-k experts支持融合共享专家返回每个 token 的 top-k 专家的 ID 和对应的 topk_weights 代码实现还是和之前一样只不过将 scores_for_choice 这个变量进行了 group 维度切分即def bias_grouped_topk_impl( hidden_states: torch.Tensor, gating_output: torch.Tensor, correction_bias: torch.Tensor, topk: int, ...): # 1. 用sigmoid对每个专家独立激活 scores gating_output.sigmoid() num_token scores.shape[0] num_experts scores.shape[1] scores_for_choice scores.view(num_token, -1) correction_bias.unsqueeze(0) # 2. group # 对每个group内部取top-2 experts的score并求和 - 得到该group的总强度 # 这是一种 group importance scoring策略(避免只看max) group_scores ( scores_for_choice.view(num_token, num_expert_group, -1) .topk(2, dim-1)[0] .sum(dim-1) ) # [n, n_group] # 3. 选择top-k groups group_idx torch.topk(group_scores, ktopk_group, dim-1, sortedFalse)[1] # [n, top_k_group] # 4. 构建mask 只在选中的groups中选择expert group_mask torch.zeros_like(group_scores) # [n, G] group_mask.scatter_(1, group_idx, 1) # 标记选中的 groups score_mask ( group_mask.unsqueeze(-1) .expand(num_token, num_expert_group, scores.shape[-1] // num_expert_group) .reshape(num_token, -1)) # [n, e] # 5. 在masked区域内做final top-k #把未选中group的scores设为 -inf 确保不会被选择 #从有效区域内选择topk tmp_scores scores_for_choice.masked_fill(~score_mask.bool(), float(-inf)) _, topk_ids torch.topk(tmp_scores, ktopk, dim-1, sorted(True if num_fused_shared_experts 0 else False)) topk_weights scores.gather(1, topk_ids) ...Expert computationmoe 的实现有很多种目前 SGlang 实现了如下三种DeepEPMoEFusedMoEFlashInferFP4MoE在 EP 并行的模式下其主要的流程都为1dispatch将输入 token 分发到指定的 rank 上的专家具体实现即为 all2all 通信其基本的流程都如下所示init设备数据 buffer 的初始化预留缓冲区token 计算计算向其他 rank 的 expert 发送的 token 数量以及要接收到的 token 数量并且检查 token 是否在 rank 中更新缓冲区将 num_token_per_ranknum_token_per_expert 即每个 token 放到发送缓冲区里面执行 All2ALL数据发送到目标 rank并且接受其他设备的数据后将其分配到本地专家2run_moe_coreSGLang 结合不同的优化方法和硬件类别实现了多个 MoeRunnerBackend 目前 FP8MoEMethod 支持 cutlass、deep_gemm、TritonMoe 的实现。3combine将专家的输出组合成最终结果。4shared expert forward执行共享专家的计算deepseek 为一个这里理论上可以与通信的过程 overlap因为 shared expert 的结果和通信 dispatch 的数据没有关联。计算之后与路由专家的结果相加如果做了 TP 并行的话最后还会执行一个 all-reduce 通信操作来得到最终的 MoE layer 的输出结果。优化点SBOsingle batch overlap在使用 DeepEP 的情况下可以使用 SBO 对 shared expert 推理和 dispatch 的通信过程进行 overlap相关 Issue# Single Batch Overlap for MoE Modelshttps://github.com/sgl-project/sglang/pull/9660SBO目前 sglang 在 sglang/python/sglang/srt/single_batch_overlap.py 中实现了该方法其流程为分发 tokens 到 routed experts。执行 routed MoE 计算up down GEMM。同时overlap在部分 SM 上执行 shared experts通过限制 GEMM 使用的 SM 数在剩余 SM 上准备/执行 combine 操作通过 CUDA Event 确保 combine 在 routed MoE 完成后才开始。最终输出融合结果 通过手动的控制 down_gemm、combine 在不同的 stream 上使用的 SM 数量来实现 overlap , 相关代码如下def execute_sbo( forward_shared_experts: Callable[[], Any], # 共享专家前向函数 experts: FusedMoE, hidden_states: torch.Tensor, topk_output: TopKOutput, alt_stream: Optional[torch.cuda.Stream] None, disable_sbo: bool False, ): # Step1 Dispatch, 分发token到experts dispatch_output experts.dispatcher.dispatch(...) # 将hidden_states 按照top-k分发的各rank上的expert buffer # Step2 计算overlap参数 # 1. 分配使用多少个 SM 分别给通信和计算 # 2. 创建cuda event和stream # 3. 是否启用overlap combine_overlap_args, down_gemm_overlap_args, meta_overlap_args _compute_overlap_args(...) # Step3 执行routed MoE Forward # 这里如果启用down_gemm_overlap_args,使用自定义的cute dsl kernel(flashinfer_cutedsl_moe_masked进行推理实现GEMM 和 combine的overlap combine_input experts.run_moe_core( dispatch_output, down_gemm_overlap_argsdown_gemm_overlap_args ) # Step4 异步启动shared experts if (not disable_sbo) and SboFlags.enable_combine_shared_two_stream_overlap(): with deep_gemm_wrapper.configure_deep_gemm_num_sms(compute_num_sms): forward_shared_experts() # ← 在受限 SM 上异步执行 # Step 5 执行combine # 在alt_stream执行 hidden_states experts.dispatcher.combine( combine_inputcombine_input, overlap_argscombine_overlap_args, # 包含 alt_stream, event, signal 等 )token 重排每个专家处理的 token 不是连续的现在是 topk_ids 的shape num_tokensnum_experts。即每个专家要处理的 token 在内存中不是连续排布的在 MOE 中每个 token 可能被分配给多个 expert每个 expert 只处理分配给它的 token如果这些 token 在原始输入 x 中是分散的比如 token05100 都去 expert 3那么GPU 无法高效的批处理内存访问不连续带宽利用率低难以启动一个大的、高效的 kernel 所以可以将要发给 expert 0 的 tokens 放一起expert 1 的放一起就能提高性能解决方法对 hidden_states 重排假设现在有如下 topk_ids# 每个token 两个experts topk_ids torch.tensor([ [3, 1], # token 0 → expert 3 和 1 [0, 2], # token 1 → expert 0 和 2 [1, 3], # token 2 → expert 1 和 3 [0, 1], # token 3 → expert 0 和 1 [2, 0], # token 4 → expert 2 和 0 [3, 2], # token 5 → expert 3 和 2 ])将62的 shape 拉成一维flat_idx topk_ids.view(-1) # [3, 1, 0, 2, 1, 3, 0, 1, 2, 0, 3, 2] # ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ #t0e0 t0e1 t1e0 t1e1 t2e0 t2e1 ...argsort() - 得到排序索引即按照专家大小来排序# 这里返回的是如果对flat_ids排序每个元素原来的位置在哪 idxs flat_idx.argsort() # 按 value 排序后从小到大 # value: 0 0 0 1 1 1 2 2 2 3 3 3 # index: 2 6 9 1 4 7 3 8 11 0 5 10 # 故idxs [2, 6, 9, 1, 4, 7, 3, 8, 11, 0, 5, 10]映射回原始 token IDtoken_indices idxs // 2 # idxs [2, 6, 9, 1, 4, 7, 3, 8,11, 0, 5,10] # //2 [1, 3, 4, 0, 2, 3, 1, 4, 5, 0, 2, 5]token_indices 表示排序后的每个“token-expert对”对应的原始 token 是哪个获取 sorted_tokenssorted_token x[token_indices]即[ x[1], # token 1 → expert 0 x[3], # token 3 → expert 0 x[4], # token 4 → expert 0 x[0], # token 0 → expert 1 x[2], # token 2 → expert 1 x[3], # token 3 → expert 1 x[1], # token 1 → expert 2 x[4], # token 4 → expert 2 x[5], # token 5 → expert 2 x[0], # token 0 → expert 3 x[2], # token 2 → expert 3 x[5], # token 5 → expert 3 ]获取每个专家被多少个 tokens 选中# cnts # token 0: [3,1] → 第0行第3列和第1列设为1 → [0,1,0,1,0] # token 1: [0,2] → 第1行第0列和第2列设为1 → [1,0,1,0,0] # token 2: [1,3] → 第2行第1列和第3列设为1 → [0,1,0,1,0] # token 3: [0,1] → 第3行第0列和第1列设为1 → [1,1,0,0,0] #所以 cnts #[[0, 1, 0, 1, 0], # [1, 0, 1, 0, 0], # [0, 1, 0, 1, 0], # [1, 1, 0, 0, 0]] tokens_per_experts cnts.sum(dim0) #[2,3,1,2,0]循环遍历每个专家进行推理# tokens_per_experts.shape (5, 1) (num_experts, 1) for i, num_tokens in enumerate(tokens_per_experts): end_idx start_idx num_tokens if num_tokens 0: continue tokens_for_this_experts sorted_tokens[start_idx : end_idx] # 用expert i 的权重计算 layer_w13_weight layer.w13_weight[i] layer_w2_weight layer.w2_weight[i] gate_up F.linear(tokens_for_this_expert, layer_w13_weight) gate_up act(gate_up) expert_out F.linear(gate_up, layer_w2_weight) outputs.append(expert_out) start_idx end_idxcombine - 聚合所有的 outputs 结果outs torch.cat(outputs, dim0) if len(outputs) else \ sorted_tokens.new_empty(0) # 创建空tensor 并用idxs 还原到原始的x排序 new_x torch.empty_like(outs) new_x[idxs] outs乘以路由权重new_x.view(*topk_ids.shape, -1) \ # (N, K, D_out) .type(topk_weights.dtype) \ # weights (N,K) .mul_(topk_weights.unsqueeze(dim-1)) \ .sum(dim1) \ # 对k维度求和 - 得到每个token的最终输出 .type(new_x.dtype) # 恢复dtypeTriton Fused MoE 优化策略融合 gate_proj 与 up_proj两者输入都是相同 hidden_states可以在 ffn_dim 上将权重 cat 到一起然后 chunkclass SiluAndMul(nn.Module): def __init__(self): super().__init__() torch.compile def forward(self, x:torch.Tensor) - torch.Tensor: x, y x.chunk(2,-1) return F.silu(x) * y融合不同专家的 gate_proj/up_proj/down_proj如将八个 down_proj 计算放在一起将 softmax、topk 等小算子融合SGLang kernelmoe_fused_gate.cu 代码走读https://github.com/sgl-project/sglang/blob/main/sgl-kernel/csrc/moe/moe_fused_gate.cu这里 kernel 的输入为经过 router 的 linear 层计算得到的结果。详细的代码可以参考 bbuf 大佬的解读有非常完整的说明图解 DeepSeek V3 biased_grouped_topk cuda 融合算子 fused_moe_gate kernelhttps://zhuanlan.zhihu.com/p/1895178845830771205普通人如何抓住AI大模型的风口为什么要学AI大模型当下⼈⼯智能市场迎来了爆发期并逐渐进⼊以⼈⼯通⽤智能AGI为主导的新时代。企业纷纷官宣“ AI ”战略为新兴技术⼈才创造丰富的就业机会⼈才缺⼝将达 400 万DeepSeek问世以来生成式AI和大模型技术爆发式增长让很多岗位重新成了炙手可热的新星岗位薪资远超很多后端岗位在程序员中稳居前列。与此同时AI与各行各业深度融合飞速发展成为炙手可热的新风口企业非常需要了解AI、懂AI、会用AI的员工纷纷开出高薪招聘AI大模型相关岗位。AI大模型开发工程师对AI大模型需要了解到什么程度呢我们先看一下招聘需求知道人家要什么能力一切就好办了我整理了AI大模型开发工程师需要掌握的知识如下大模型基础知识你得知道市面上的大模型产品生态和产品线还要了解Llama、Qwen等开源大模型与OpenAI等闭源模型的能力差异以及了解开源模型的二次开发优势以及闭源模型的商业化限制等等。了解这些技术的目的在于建立与算法工程师的共通语言确保能够沟通项目需求同时具备管理AI项目进展、合理分配项目资源、把握和控制项目成本的能力。产品经理还需要有业务sense这其实就又回到了产品人的看家本领上。我们知道先阶段AI的局限性还非常大模型生成的内容不理想甚至错误的情况屡见不鲜。因此AI产品经理看技术更多的是从技术边界、成本等角度出发选择合适的技术方案来实现需求甚至用业务来补足技术的短板。AI Agent现阶段AI Agent的发展可谓是百花齐放甚至有人说Agent就是未来应用该有的样子所以这个LLM的重要分支必须要掌握。Agent中文名为“智能体”由控制端Brain、感知端Perception和行动端Action组成是一种能够在特定环境中自主行动、感知环境、做出决策并与其他Agent或人类进行交互的计算机程序或实体。简单来说就是给大模型这个大脑装上“记忆”、装上“手”和“脚”让它自动完成工作。Agent的核心特性自主性能够独立做出决策不依赖人类的直接控制。适应性能够根据环境的变化调整其行为。交互性能够与人类或其他系统进行有效沟通和交互。对于大模型开发工程师来说学习Agent更多的是理解它的设计理念和工作方式。零代码的大模型应用开发平台也有很多比如dify、coze拿来做一个小项目你就会发现其实并不难。AI 应用项目开发流程如果产品形态和开发模式都和过去不一样了那还画啥原型怎么排项目周期这将深刻影响产品经理这个岗位本身的价值构成所以每个AI产品经理都必须要了解它。看着都是新词其实接触起来也不难。从0到1的大模型系统学习籽料最近很多程序员朋友都已经学习或者准备学习 AI 大模型后台也经常会有小伙伴咨询学习路线和学习资料我特别拜托北京清华大学学士和美国加州理工学院博士学位的鲁为民老师吴文俊奖得主给大家准备了一份涵盖了AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频全系列的学习资料这些学习资料不仅深入浅出而且非常实用让大家系统而高效地掌握AI大模型的各个知识点。这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】适学人群应届毕业生‌无工作经验但想要系统学习AI大模型技术期待通过实战项目掌握核心技术。零基础转型‌非技术背景但关注AI应用场景计划通过低代码工具实现“AI行业”跨界‌。业务赋能突破瓶颈传统开发者Java/前端等学习Transformer架构与LangChain框架向AI全栈工程师转型‌。AI大模型系统学习路线在面对AI大模型开发领域的复杂与深入精准学习显得尤为重要。一份系统的技术路线图不仅能够帮助开发者清晰地了解从入门到精通所需掌握的知识点还能提供一条高效、有序的学习路径。基础篇包括了大模型的基本情况核心原理带你认识了解大模型提示词Transformer架构预训练、SFT、RLHF等一些基础概念用最易懂的方式带你入门AI大模型进阶篇你将掌握RAGLangchain、Agent的核心原理和应用学习如何微调大模型让大模型更适合自己的行业需求私有化部署大模型让自己的数据更加安全项目实战篇会手把手一步步带着大家练习企业级落地项目比如电商行业的智能客服、智能销售项目教育行业的智慧校园、智能辅导项目等等但知道是一回事做又是另一回事初学者最常遇到的问题主要是理论知识缺乏、资源和工具的限制、模型理解和调试的复杂性在这基础上找到高质量的学习资源不浪费时间、不走弯路又是重中之重。AI大模型入门到实战的视频教程项目包看视频学习是一种高效、直观、灵活且富有吸引力的学习方式可以更直观地展示过程能有效提升学习兴趣和理解力是现在获取知识的重要途径光学理论是没用的要学会跟着一起敲要动手实操才能将自己的所学运用到实际当中去这时候可以搞点实战案例来学习。海量AI大模型必读的经典书籍PDF阅读AI大模型经典书籍可以帮助读者提高技术水平开拓视野掌握核心技术提高解决问题的能力同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说阅读经典书籍是非常有必要的。600AI大模型报告实时更新这套包含640份报告的合集涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师还是对AI大模型感兴趣的爱好者这套报告合集都将为您提供宝贵的信息和启示。AI大模型面试真题答案解析我们学习AI大模型必然是想找到高薪的工作下面这些面试题都是总结当前最新、最热、最高频的面试题并且每道题都有详细的答案面试前刷完这套面试题资料小小offer不在话下AI时代企业最需要的是既懂技术、又有实战经验的复合型人才**当前人工智能岗位需求多薪资高前景好。**在职场里选对赛道就能赢在起跑线。抓住AI这个风口相信下一个人生赢家就是你机会永远留给有准备的人。如何获取这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】