MoE 系列论文解读:Gshard、FastMoE、Tutel、MegaBlocks 等

节前,我们组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。

针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。

总结链接如下:《AIGC 面试宝典》(2024版) 正式发布!


这篇文章中,我们简单回顾一下 MoE 的发展历程,介绍几个有代表性的 MoE 模型(按照时间顺序)。

1.1 马斯克发布 314B Grok-1

最近马斯克开源了 Twitter(xAI)的 LLM Grok-1,其包含 314B 参数量,是当前最大的开源 LLM,其对应的配置如下图所示(对应的代码库为 https://github.com/xai-org/grok-1/tree/main),可以看出:

  • 词表大小为 128*1024=131072

  • 序列长度为 8192

  • Embedding 大小为 6144

  • 使用了 GQA(每 6 个一组),8 个 KV Head,48 个 Query Head

  • 总共 64 层

  • 采用了 MoE,每层 8 个专家,每次激活 2 个专家

图片

1.2 数据、模型、专家并行

随着模型规模的增加,往往需要结合各种分布式并行策略,以下是 3 种并行策略及其相互融合(来自论文 [2101.03961] Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity),包括数据并行(Data Parallel,DP)、模型并行(Model Parallel,MP,或者称为 Tensor Parallel,TP)和专家并行(Expert Parallel,EP);实际上还有常见的流水线并行(Pipeline Parallel,PP);此外通过将大的 Batch 拆分为小的 Micro Batch 进行梯度累加,不同 Micro Batch 之间可以通过 Overlap 方式减少 Bubble,也是常用的方案,以上两种这里不再展开(需要说明的是,这里不包含 ZeRO 系列的并行策略,比如 ZeRO-DP 实际上也会切分模型参数):

如下图所示,从模型参数切分和数据切分的角度考虑(只考虑 FFN 层):

  • 第一列:数据并行

  • 上:所有设备(1-16)都有相同、全部的模型参数。

  • 下:每个设备只有一个数据分片,且不重复,共 16 个数据分片。

  • 第二列:模型并行

  • 上:所有设备(1-16)都只有模型参数的一部分,共 16 个分片。

  • 下:所有设备使用共同的一份数据。

  • 第三列:模型并行+数据并行,设备分为 4 组(1-4,5-8,9-12,13-16)

  • 上:每组(4 个设备)都有完整的模型参数副本,但是每组内的设备只有参数的一部分。

  • 下:数据分为 4 个切片,每组(4 个设备)对应一个数据切片。

  • 第四列:专家并行+数据并行,设备分为 16 组(1-16)

  • 上:每一个设备都有不同的专家,共 16 个专家。

  • 下:每个设备都有不同的数据分片(Token),共 16 个数据分片,一个专家对应一个分片。

  • 第五列:专家并行+模型并行+数据并行,有 4 组设备(1-4,5-8,9-12,13-16)

  • 上:有 4 个专家,每个专家分布在对应的 4 个设备上,比如绿色专家分布在 5,6,7,8 设备上。

  • 下:有 4 个数据分片,每组设备(每个专家)对应一个数据分片,一组设备里的 4 个设备共享一份数据分片。

图片

图片

1.3 补充

在了解这些文章时,需要考虑每个系统的潜在假设以及针对的场景,比如:

  1. 专家数量和 GPU(TPU)数量的关系可能导致不同的分布式并行策略:
  • 早期模型中每层的专家数非常多,可能达到几百甚至几千,此时通常是一个 GPU 一个专家(Gshard)或者一个 GPU 上多个专家。

  • 最近的 LLM-MoE 中,专家数量往往很小,可能只有 8 个或 16 个,而训练 LLM 的 GPU 往往达到几百、几千甚至上万个,往往可以将一个专家放在多个 GPU 上。此时也需要考虑切分方式,比如平均 1 个专家对应 4 个 GPU:

  • 一种方案是:2 个专家共享 8 个 GPU,每个 GPU 有 2 个专家的各 1/8

  • 另一种方案是:1 个专家独享 4 个 GPU,每个 GPU 有 1 个专家的 1/4

  1. 模型中除了 MoE 之外还包含多个模块,比如 Transformer 模型除了 FFN 还有 Attention,而很多工作都重点考虑 MoE(FFN)的专家模块。在 Attention 模块除了 DP 之外也可以使用 MP(TP)。

二、Adaptive Mixture of Local Experts

MoE 的概念起源自 1991 年的 Paper Adaptive Mixtures of Local Experts,其中每个 Expert Network 和 Gating Network 都会接受 Input,并执行各自的部分,Gating Network 会学习到各个 Expert 的权重,并将输出按照权重进行归一化,如下图所示:

图片

三、Sparsely-Gated MoE

在 [1701.06538] Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer 中,作者(也包括大名鼎鼎的 Geoffrey Hinton 和 Jeff Dean)将 MoE 引入到 LSTM 模型中,并提出了稀疏 MoE(Sparse MoE)的概念。

如下图 Figure 1 所示,作者引入了 Gating Network 机制,该机制可以选出 Topk 的 Expert(深灰色 Expert 2 和 Expert n-1)进行计算。这种稀疏性意味着只有部分专家被激活处理特定的输入,从而可以大大降低计算量:

图片

作者也进一步证明通过添加 MoE,可以灵活控制专家数,来获得不同容量的模型。如下图 Table 8 所示,作者分别构建了 32/256/1024/4096/16384/65535/131072 个专家的模型,其最大的为 137B 的 LSTM 模型。由于稀疏性的存在,虽然 137B 参数量很大,但可以比当时 SOTA 模型更低的计算成本下获得更好的效果:

图片

作者观察到,Gating Network 倾向于收敛到不均衡的状态,也就是总是为少数专家产生较大的权重(相应的参数更新也会很不均衡)。为了解决这一问题,作者设计了额外的损失函数,旨在鼓励所有专家具有同等的重要性,如下图所示:

图片

四、Gshard

在 [2006.16668] GShard: Scaling Giant Models with Conditional Computation and Automatic Sharding 中,作者首次将 MoE 引入到 Transformer 模型中。如下图 Figure 3 所示:

  • 增加 Position-wise Sparsely Gated MoE 层,将 FFN 层替换为 MoE 结构,MoE 中的每个专家都是一个 FFN(每个专家大小相同)

  • Gating 模块:通过 Gating 模块将输入路由到不同的专家(Transformer 模型输入的是 Token 序列,因此每个 Token 都会通过 Gating 选择不同的专家,而不是整个序列使用相同的专家,默认为 top2)。

  • Random routing:有些时候 Gating 模块得到的排名第二的专家的分数会很低,此时可以简单地忽略第二个专家。

  • 并非是每一层的 FFN 都替换为 MoE,而是间隔一层替换,如果有 12 层,则只有 6 层有 MoE(通常是可配置的)。

  • 采用专家并行(Expert Parallel,EP)策略,每个设备一个专家,除 MoE 之外的模型其它部分在所有设备存储一份相同的副本。(如果有 128 个专家,则使用 128 个 TPU Core;2048 个专家,则使用 2048 个 TPU Core)

图片

五、Switch Transformer

在 [2101.03961] Switch Transformers: Scaling to Trillion Parameter Models with Simple and Efficient Sparsity 中,作者相比 Gshard 等方案主要做了三点改进。

5.1 简化稀疏路由

在 [1701.06538] Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer 中,作者认为选择的稀疏专家的数目需要 > 1,在 Gshard 中作者也是使用的 top2 专家。而 Switch Transformer 中,作者发现仅使用一个专家也能保证模型的质量。这样有 3 个好处:

  • Router 计算更简单,通信量也更少。

  • 一个 Token 仅对应一个专家,计算量也更少。

  • 平均每个专家对应的 batch size 至少可以减半。

如下图 Figure 2 所示,其模型结构和 Gshard 中类似,图中的红框和绿框是同样的 MoE,只是对应不同的输入,经 Router 后也只连接一个专家:

图片

5.2 高效稀疏路由

作者采用了 Mesh-TensorFlow,其提供和 TensorFlow 相似的 API,提供了更简单的分布式数据并行和模型并行。作者的模型主要针对 TPU 设计,其在模型训练中不支持动态 Tensor shape,也就是要求每个专家输入的 Tensor shape 是固定的。然而,路由是动态的,相应路由到每个专家的 Tensor 的 shape 也是动态的,为了解决这一问题,作者提出了专家容量(Expert Capacity)的概念。如下所示,专家容量为每个 Batch 中总的 Token 数除以专家数,然后再乘以容量因子(Capacity Factor),即可得到专家容量(每个专家对应的 Token 数)。

图片

如下图 Figure 3 所示,有 6 个 Token,3 个专家,平均每个专家 2 个 Token:

  • 容量因子为 1.0:如下图中所示,则对应的专家容量为 2:

  • Expert 1 有 3 个 Token,则需要丢弃一个通过残差连接直接传到下一层。

  • Expert 2 有 2 个 Token,正好。

  • Expert 3 只有 1 个 Token,需要 Padding 1 个空的 Token。

  • 容量因子为 1.5:如下图右所示,则对应的专家容量为 3:

  • Expert 1 有 3 个 Token,正好。

  • Expert 2 只有 2 个 Token,需要 Padding 1 个空的 Token。

  • Expert 3 只有 1 个 Token,需要 Padding 2 个空的 Token。

图片

从上也可以看出,容量因子越大,需要 Padding 的 Token 也就越多,无效计算越多;负载越不均衡,需要 Padding 的 Token 也就越多,无效计算越多。为了更好地实现负载均衡,作者同样添加了 Load Balancing Loss。

5.3 增强的训练和微调技巧

Selective precision:稀疏专家模型相比传统 Transformer 模型训练更加困难,由于每一层 Router 的存在,可能导致训练的不稳定性,此外 BF16 等低精度格式可能加剧 Router 中 Softmax 计算的问题。本文作者提出了在模型的局部部分选择性地转为 FP32 精度,可以实现很好的稳定性,而不会产生昂贵的 FP32 Tensor 通信成本。具体来说,只在 Router 的内部使用 FP32 精度。如下图 Table 2 所示,本文的 Selective precision 可以同时实现高质量和高吞吐:

图片

小的初始化参数有助于稳定性:如下图所示,作者验证通过使用比较小的初始化参数可以获得更好的模型质量,并减小模型在训练早期的方差:

图片

Dropout 正则化:当前的这些 Transformer 模型通常是在大规模语料库上进行预训练,然后在较小的下游任务上微调,而当微调数据集比较小时经常出现过拟合,而 Switch Transformer 这类 MoE 模型可能加剧过拟合的程度。为了缓解这一问题,作者增加了专家内部(FFN)的 Dropout 比例,称为专家 Dropout(Expert Dropout,ED)。然而,作者发现所有层增加 Dropout 率会导致性能更差;作者发现,在非专家层使用较小的 Dropout 率可以缓解这一问题:

图片

六、FastMoE

6.1 摘要

之前的高性能分布式 MoE 训练系统主要是针对 Google 的硬件(TPU)和软件(Mesh TensorFlow),并且不向公众开放,针对 NVIDIA GPU 和 Pytorch 还没有相应方案。

在 [2103.13262] FastMoE: A Fast Mixture-of-Expert Training System 中,作者提出 FastMoE,其是一个基于 Pytorch 的分布式 MoE 训练系统,并提供高度优化的高性能加速方案。该系统支持将不同的专家放置在多个节点上的多个 GPU 中,从而实现专家数量和 GPU 数量线性增加。

PS:如下图所示(来自 fastmoe/doc/readme-cn.md at master),FastMoE 主要针对的是 Expert 比较多的场景,也就是一个 GPU 上有 1 个或多个 Expert。在 2021 年底的 v0.3.0 版本中集成了 Megatron-LM,通过 Megatron-LM 的 Tensor Parallel 来实现一个 Expert 分布在不同的 GPU 上。

图片

6.2 系统设计

6.2.1 灵活性

FastMoE 的灵活性主要体现在以下几个方面:

  • 支持任意的网络作为专家。作者对专家模块做了抽象,用户可以专注设计专家模块;此外,FastMoE 也支持将多个专家放在同一个 Worker 上。

  • 针对 Transformer 模型高度优化的 FFN。尤其是当多个专家放在一个 Worker 时,常见的方式是通过 for 循环串行的执行 Worker 上的多个专家,而作者实现了并行执行不同专家的方案。(Batched Gemm)

  • 插件式支持 Pytorch 和 Megatron-LM。作者对 FastMoE 进行了必要的抽象,使其很容易与其他框架集成,如下图所示为与 Megatron-LM 集成的示例:

图片

6.2.2 扩展模型容量

FastMoE 的模型并行方案。FastMoE 支持将专家分布在多个节点的多个 Worker 上,并且将不同 Worker 之间的数据通信隐藏起来,模型开发人员不用考虑。此外,在分布式 MoE 系统中的一个主要挑战为:动态路由导致分配给不同专家的输入样本数可能存在很大的差异。作者的方案为:在 Worker 之间交换实际的数据之前,先在 Worker 之间交换大小信息,Worker 根据相应信息分配 Buffer,然后传输真实的数据。

图片

异构同步模块。模型的不同部分可能在不同的 Worker 组间重复,这非常有挑战,因为分布式模块不得不识别是否需要对参数的梯度进行同步,以及与谁同步。因此,FastMoE 引入了数据并行通信组标签:

  • world:需要与所有 Worker 同步。

  • data parallel:需要与模型并行组正交的数据并行组中的 Worker 同步。

  • none:不需同步。

例如,无论模型并行设置如何,Gating Network 需要在所有 Worker 之间复制,因此标签为 world。注意力层可以划分为模型并行子层,因此其标签为 data parallel。每个 Worker 都包含几个特定的专家网络,其标签为 none。

6.3 优化激活

FastMoE 将所有输入样本一起 Batching 后发给同一个专家。由于数据表示的限制,FastMoE 使用专门开发的 CUDA Kernel 进行内存移动,以减少开销。如下图 Figure 4 所示,给定每个样本要进入的索引(Gating 输出),通过 Scatter 操作将所有样本按照对应顺序进行排布,执行完专家计算之后,再按照相反的 Gather 操作进行复原。(gate output 应该为 0, 1, 2, 1, 1, 0 ?)

图片

6.4 多 CUDA Stream 调度

如下图 Figure 8 所示,S 表示 Send,R 表示 Receive,C 表示 Compute,通过利用 CUDA 的 Multi Stream 机制,可以最大限度实现通信和计算的 overlap,实现加速的目的:

图片

七、Tutel

7.1 摘要

之前的 MoE 分布式训练系统往往采用静态执行方式(Tensor 的 Shape 在执行中不能改变),导致经 Token 路由之后可能存在 Token 丢弃或者 Padding 无效计算的问题,导致计算效率比较低。

在 [2206.03382] Tutel: Adaptive Mixture-of-Experts at Scale 中,作者提出了 Tutel,其具备动态自适应并行和流水并行(PS:非流水线并行)机制。Tutel 中作者设计了一个统一布局来分发 MoE 模型参数和输入数据,并利用其实现可切换并行性和动态流水并行,而无需引入数学不等价操作或者 Tensor 迁移开销,可以在运行时以零成本实现自适应并行/流水并行优化。基于这一关键设计,Tutel 实现了各种 MoE 加速技术,包括 Flexible All-to-All、二维分层(2DH)All-to-All,以及快速编码、解码等。综合所有技术,Tutel 相比之前的方案,在 16 个和 2048 个 A100 GPU 上,单个 MoE 层的速度提升 4.96x 和 5.75x。

作者评估表明,Tutel 可以高效地运行 SwinV2-MoE,其基于 Swin Transformer V2 构建。使用 Tutel 训练和推理 SwinV2-MoE 比 Fairseq 加速 1.55x 和 2.11x。同时,SwinV2-MoE 在预训练及下游视觉任务中比对应的密集模型实现了更高的准确性。

7.2 自适应 MoE

鉴于 EP、DP 和 MP 派生了 7 种不同的并行方法组合,一种方案是为每种方法设计一个执行流程,并使其可与其他方法切换。然而,实际上没有必要设计 7 个执行流程,因为其可以简化为更小但效率相当的问题。作者的方法是分析所有并行方法的复杂性,以将它们缩小到最小子集(这里作者只考虑最重要的通信复杂性,所有 GPU 都执行相同的计算,计算复杂度相同,通信复杂性直接决定了一种并行方法相比其他方法的效率)。如果它们满足以下条件则将其删除:

  1. 在任何情况下都不是最佳的。

  2. 是另一种方法的特例。

如下图 Table 3 所示为一些常见的参数:

图片

作者在参数表里没有具体介绍 r 参数,只在后文介绍,表示每个专家的 TP 数,也就是每个专家分布在几个 GPU 上:

  • 如果 r=1,则表示 EP+DP+MP 变为 EP+DP

  • 如果 r= W/E,则表示 EP+DP+MP 变为 EP+MP

如下图 Table 4 所示,经过一系列比较,作者得出结论,该子集只包含 DP(1) 和 EP+DP+MP(7):

  • 对于 DP(1):仅数据并行,不过采用的是 ZeRO-DP Stage-3,可以将模型参数分布在多个 GPU 设备,在前向计算的时候通过 All-Gather 操作获取所有模型参数进行计算。在反向时,执行一次 Reduce-Scatter。

  • 对于 MP(2):仅模型并行,每个 GPU 上都只有模型的 1/W,所有 GPU 加起来有一份完整模型。只要能使用 EP,则总会差于 EP+MP(6)。

  • 对于 EP(3):只有专家数量 >= GPU 数量才有意义,因此作者假设专家数量 < GPU 数量,这也是当前 LLM-MoE 的现状,不用考虑纯 EP 的方案。

图片

如下图 Figure 6 所示为相应的 Zero-DP,假设有 4 个 GPU,模型有 2 个专家,则每个 GPU 都只存储某个专家的 1/2。在前向计算时需要一次 All-Gather 获取到 2 个完整的专家参数。

图片

经过如上的分析后,作者得出了不同的分布式方案,如下图 Figure 8 所示,假设 ZeRO-DP 为 r=0,根据 r 的不同值可以选择不同的策略,特殊情况为上述介绍的 r=1 和 r=W/E:

图片

7.3 优化

7.3.1 Flexible All-to-All

常规的 FFN 层计算时,All-to-All 的 data layout 会和 Word-Size 有关,当 Word-Size(GPU)数目比较大时,性能可能会下降比较多:

图片

PS:出现这一问题的主要原因是:FFN layer 主要为矩阵乘法,GPU 处理大矩阵乘法非常高效,而如果矩阵中的某一维度比较小时,会导致矩阵乘法处于 Roofline-Model 的 Memory-Bound 区域,导致无法充分发挥 GPU 算力,并且维度越小此瓶颈越明显。当 World-Size 为 256 时,对应的矩阵短边为 16384/256=64,可能正好在 Roofline-Model 的转折点,这也是为什么当 Worhd-Size 进一步增大时性能会进一步降低。

Flexible All-to-All 的目的是去除和 World-Size 的相关性,如下图为优化后的效果:

图片

7.3.2 2DH All-to-All

如下图 Figure 15 所示,2DH All-to-All 的主要思路是充分考虑数据的局部性(GPU 内,同 node GPU、多 node GPU),将非连续内存空间对齐到连续内存空间,并将多个小的通信合并成大的通信:

  • 第一列 -> 第二列:GPU 内部交换数据(无通信)

  • 第二列 -> 第三列:同 node 的 GPU 间交换数据(NVLink)

  • 第三列 -> 第四列:GPU 内部交换数据(无通信)

  • 第四列 -> 第五列:跨 node 的 GPU 间交换数据(网络)

图片

如下图 Figure 20 和 Figure 21 所示,提出的 2DH All-to-All 比基线提升明显:

图片

7.3.3 Fast Encode 和 Decode Kernel 优化

如下图 Figure 3 所示,在专家并行模式下,专家层的前后会分别引入 All-to-All 通信操作。前一个 All-to-All 用于将每个 Worker 上的 Token 按照 Router 后对应的专家发送到专家所在的 GPU,也叫 All-to-All(Dispatch);而后一个 All-to-All 用于将专家计算后的 Token 重新按照原来的方式排列,也叫 All-to-All(Combine)。

图片

在 All-to-All(Dispatch)操作之前需要准备好 All-to-All 的输入,也叫 Encode;在 All-to-All(Combine)操作之后需要解包 All-to-All 的输出,组织为原始的顺序,也叫 Decode。而很多框架中 Encode 和 Decode 的实现都不够高效,有很多无效计算,因此作者定制了高性能 CUDA Kernel 来优化,如下图(a)为未优化的 Encode,(b)为优化后的 Encode。

图片

如下图 Figure 15 所示,优化后 Encode、Decode 相关的时间大幅降低(此外也可以有效节约显存):

图片

7.3.4 Adaptive Pipelining

此外,在 Tutel 中,作者也采用了 Multi-Stream 机制来实现计算和通信的重叠,以提升效率,这里不再展开。

八、MegaBlocks

8.1 摘要

MegaBlocks([2211.15841] MegaBlocks: Efficient Sparse Training with Mixture-of-Experts) 是斯坦福大学、微软及谷歌联合发布的在 GPU 上高效训练 MoE 的系统。之前我们提到过,MoE 的 Router 负载不均衡会导致需要删除 Token 或者 Padding 填充,本文中作者采用块稀疏操作对 MoE 计算进行了重新调整,并开发了新的块稀疏 GPU Kernel,以高效处理 MoE 中存在的动态性。作者提出的方法中从不丢弃 Token,并能与现有硬件很好地结合。

与最先进的 Tutel 库相比,端到端训练速度提高 40%;与使用高度优化的 Megatron-LM 框架训练的 DNN 相比,端到端训练速度提高 2.4x。

PS:需要说明的是,MegaBlocks 主要针对的还是单个 GPU 上包含多个专家的场景。

8.2 方法

MegaBlocks 主要解决的是 1 个 GPU 上有多个专家时,由于负载不均衡导致的 Token 丢弃或者 Padding 无效计算问题。如下图 Figure 3 所示,假设有 3 个专家,每个专家的 Capability 为 2 个 Token,Router 后分配给 3 个专家的 Token 分别为 3,1,2,因此 Expert-0 需要丢弃一个 Token,Expert-1 需要 Padding 一个 Token。假设 Token Embedding 维度为 1024,FFN 第一个 MLP 升维后为 4096:

  • (A):对应 3 个 (2, 1024) 和 (1024, 4096) 的矩阵乘法,每个输出都是 (2, 4096)

  • (B):可以表示为 Batch Gemm 来计算,输出为 (6, 12288),但只有对角线上有 3 个 (2, 4096) 的子矩阵,其他位置为 0。采用稀疏计算不会增加额外的计算量。

  • (C):同样可以表示为 Batch Gemm(可变 Shape),但是不丢弃 Token,也不 Padding,相当于 (3, 1024),(1, 1024) 和 (2, 1024) 的 3 个矩阵分别不同的 (1024, 4096) 的矩阵相乘,稀疏表示后生成的还是 (6, 12288) 矩阵。PS:这个图很容易让人迷惑,图中的列分块是作者想要支持可变大小的专家,但并没有实现。实际上当前用的专家大小都相同,所以各个专家列分块的大小也应该相同。

图片

如下图 Figure 5 所示为对应的稀疏分块矩阵表示方式:

图片

九、参考链接

  1. https://github.com/xai-org/grok-1/tree/main

  2. https://arxiv.org/abs/2101.03961

  3. https://www.cs.toronto.edu/~hinton/absps/jjnh91.pdf

  4. https://arxiv.org/abs/1701.06538

  5. https://arxiv.org/abs/2006.16668

  6. https://arxiv.org/abs/2101.03961

  7. https://arxiv.org/abs/2103.13262

  8. https://github.com/laekov/fastmoe/blob/master/doc/readme-cn.md

  9. https://arxiv.org/abs/2206.03382

  10. https://arxiv.org/abs/2211.15841

  11. https://huggingface.co/blog/zh/moe

  12. https://zhuanlan.zhihu.com/p/653518289

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/641454.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity在Windows平台播放HEVC/H.265格式视频的底层原理

相关术语、概念 HEVC/H.265 HEVC&#xff08;High Efficiency Video Coding&#xff09;是一种视频压缩标准&#xff0c;也被称为H.265。它是一种高效的视频编码标准&#xff0c;可以提供比之前的标准&#xff08;如H.264&#xff09;更高的压缩率&#xff0c;同时保持较高的…

力扣HOT100 - 31. 下一个排列

解题思路&#xff1a; 数字是逐步增大的 步骤如下&#xff1a; class Solution {public void nextPermutation(int[] nums) {int i nums.length - 2;while (i > 0 && nums[i] > nums[i 1]) i--;if (i > 0) {int j nums.length - 1;while (j > 0 &&…

015_表驱动编程思想(c实现)

【背景】 数据压倒一切。如果选择了正确的数据结构并把一切组织的井井有条&#xff0c;正确的算法就不言自明。编程的核心是数据结构&#xff0c;而不是算法。 ——Rob Pike 上面是这个名人说过的话&#xff0c;那么c语言之父 丹尼斯麦卡利斯泰尔里奇 的《c程序设计》里曾经…

【Linux取经路】基于信号量和环形队列的生产消费者模型

文章目录 一、POSIX 信号量二、POSIX 信号量的接口2.1 sem_init——初始化信号量2.2 sem_destroy——销毁信号量2.3 sem_wait——等待信号量2.4 sem_post——发布信号量 三、基于环形队列的生产消费者模型3.1 单生产单消费模型3.2 多生产多消费模型3.3 基于任务的多生产多消费模…

C# 利用Xejen框架源码,我们来开发一个基于Dapper技术的数据库通用的帮助访问类,通过Dapper的增删改查,可以访问Sqlite数据库

Dapper 是一个轻量级的对象关系映射&#xff08;ORM&#xff09;工具&#xff0c;适用于 .NET 平台。它由 Stack Overflow 团队开发&#xff0c;旨在提供简单、高效的数据访问功能。与其他重量级 ORM&#xff08;如 Entity Framework&#xff09;相比&#xff0c;Dapper 更加轻…

用这8种方法在海外媒体推广发稿平台上获得突破-华媒舍

在今天的数字时代&#xff0c;海外媒体推广发稿平台已经成为了许多机构和个人宣传和推广的有效途径。如何在这些平台上获得突破并吸引更多的关注是一个关键问题。本文将介绍8种方法&#xff0c;帮助您在海外媒体推广发稿平台上实现突破。 1. 确定目标受众 在开始使用海外媒体推…

C++语法|虚函数与多态详细讲解(六)|如何解释多态?(面试向)

系列汇总讲解&#xff0c;请移步&#xff1a; C语法&#xff5c;虚函数与多态详细讲解系列&#xff08;包含多重继承内容&#xff09; 多态分为了两种&#xff0c;一种是静态的多态&#xff0c;一种是动态的多态。 静态&#xff08;编译时期&#xff09;的多态 函数重载 boo…

pands使用openpyxl引擎实现EXCEL条件格式

通过python的openpyxl库&#xff0c;实现公式条件格式。 实现内容&#xff1a;D列单元格不等于E列同行单元格时标红。 #重点是formula后面的公式不需要“”号。 from openpyxl.styles import Color, PatternFill, Font, Border from openpyxl.styles.differential import Dif…

【设计模式】JAVA Design Patterns——Bytecode(字节码模式)

&#x1f50d;目的 允许编码行为作为虚拟机的指令 &#x1f50d;解释 真实世界例子 一个团队正在开发一款新的巫师对战游戏。巫师的行为需要经过精心的调整和上百次的游玩测试。每次当游戏设计师想改变巫师行为时都让程序员去修改代码这是不妥的&#xff0c;所以巫师行为以数据…

git push后一直卡在在Writing objects:问题

git push后一直卡在Writing objects: 解决&#xff1a;设置 git config --global http.postBuffer 5242880000在执行git push。 一般设置后就可以成功了&#xff0c;后面不用看。 2. 我这里结果又报错&#xff1a; fatal: protocol error: bad line length 8192 MiB | 107.46 …

【C++】d1

关键字&#xff1a; 运行、前缀、输入输出、换行 运行f10 前缀必须项&#xff1a; #include <iostream> using namespace std; 输入/输出&#xff1a; cin >> 输入 cout << 输出 语句通过>>或<<分开 换行 endl或者"\n"

想当安卓开发工程师?学习路线分享!

安卓开发学习路线 在前几篇文章中,对安卓开发岗位的岗位要求做了一些科普,本节文章将介绍安卓开发岗位的学习路线。 目前,网络上有很多面经、算法题解、算法课等学习资料,如何合理利用这些资料成为技术求职者的一大困惑。笔者整理了一份安卓开发岗位学习路线供大家参考,…

第四课 communcation服务-can配置第二弹

Davinci配置目标: 介绍DBC基本属性,并且配置出一个DBC。 将DBC导入到vector的davinci工具,生成我们想要的代码。 Davinci配置步骤: 1. 编辑DBC文件 DBC文件是一种非常重要的工具,所谓DBC就是Database CAN,CAN网络的数据库文件,定义了CAN网络的节点、消息、信号的所有…

网络安全知识核心20要点

1、什么是SQL注入攻击 概述 攻击者在 HTTP 请求中注入恶意的 SQL 代码&#xff0c;服务器使用参数构建数据库 SQL 命令时&#xff0c;恶意SQL 被一起构造&#xff0c;并在数据库中执行。 注入方法 用户登录&#xff0c;输入用户名 lianggzone&#xff0c;密码‘ or ‘1’’…

axios如何传递数组作为参数,后端又如何接收呢????

前端的参数是一个数组。 前端编写&#xff1a; 后端接收&#xff1a;

git解决版本冲突 -git pull

当在Git中遇到版本冲突时&#xff0c;通常是因为两个或更多的开发者在同一时间修改了同一个文件的相同部分&#xff0c;并将这些修改推送到远程仓库。Git无法自动合并这些修改&#xff0c;因此会产生冲突。以下是解决Git版本冲突的基本步骤&#xff1a; 拉取最新代码&#xff…

mybatis-plus 优雅的写service接口中方法(3)

多表联查 上文讲过了自定义sql &#xff0c;和wrapper的使用&#xff0c;但是我们可以发现 我们查询的都是数据库中的一张表&#xff0c;那么怎么进行多表联查呢&#xff0c;当然也是用自定义sql来进行实现 比如说 查询 id 为 1 2 4 的用户 并且 地址在北京 的 用户名称 普…

AI崛起,掌握它,开启智能新生活!

AI崛起&#xff0c;掌握它&#xff0c;开启智能新生活&#xff01; &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &…

LDAP: error code 32 - No Such Object

目前我的项目版本&#xff1a; Spring版本:5.3.15SpringBoot版本:2.6.3 完整错误 org.springframework.ldap.NameNotFoundException: [LDAP: error code 32 - No Such Object]; nested exception is javax.naming.NameNotFoundException: [LDAP: error code 32 - No Such Objec…