从FasterTransformer源码解读开始了解大模型(2.0)代码通读01

从FasterTransformer源码解读开始了解大模型(2.0)代码解读01-看看头文件

写在前面的话

本篇的内容直接开始我们的代码通读,整个通读可能需要好几篇文章来将一整个gpt的代码结构给讲清楚。目前的计划是先从整体model层次开始讲,将ContextDecoder和Decoder讲完之后,再从模块内部(MHA和FFN)代码开始讲,中间也会穿插一些技术点的讲解。

零、model层的结构参数

打开之前的src/fastertransformer/models/multi_gpu_gpt目录,正如我们在上一篇文章说过的,整体的model是由在ParallelGpt的代码中,而其中的ContextDecoder和Decoder两大模块的功能则是由ParallelGptContextDecoder和ParallelGptDecoder来进行组织。一个良好的习惯是我们可以先从头文件ParallelGpt.h开始看,了解一下大致的情况和需要的功能。

先看一下ParallelGpt.h的33~66行,这里是一些用于描述模型结构的参数

private:// meta datasize_t               head_num_;size_t               size_per_head_;size_t               inter_size_;size_t               num_layer_;size_t               vocab_size_;size_t               expert_num_;size_t               moe_k_;std::vector<int64_t> moe_layer_index_;int    start_id_;int    end_id_;float  beam_search_diversity_rate_;size_t hidden_units_;const float layernorm_eps_;  // OPTfloat       shared_contexts_ratio_;// TODO(bhsueh) remove these member because they are runtime parameterssize_t             top_k_;float              top_p_;unsigned long long random_seed_;float temperature_;float len_penalty_;float repetition_penalty_;size_t    local_head_num_;NcclParam tensor_para_;NcclParam pipeline_para_;std::shared_ptr<AbstractCustomComm> custom_all_reduce_comm_;int                                 enable_custom_all_reduce_;

这么多的参数,是否会出现看花了眼的情况?其实代码中很贴心地将一些相同功能方向的参数都给放在了一起,逐个看下来也不会特别困难。下面介绍一些结构上的参数来进行简单介绍,一些计算中用的参数则会在后续结合代码运行过程的源码解析来进行说明

首先是从head_num到moe_layer_index_这八个参数,都是用于描述模型基础属性的。head_num是用于描述MHA时拥有多少个注意力头的,size_per_head是用于描述MHA中每个头的大小的,最常见的模型一般是128,google的gemma则是256. inter_size是用于描述FFN的中间维度大小,num_layer是用于描述模型整体的层数的,vocab_size是用于描述token词表的大小

llm小知识-参数量:一般来说,参数量越多的模型(越大的模型)会拥有更多的层数(num_layer)和MHA的头数(head_num),这也就意味着它们能拥有更多的信息,模型效果也就越好,但同时,每个token的计算量和生成时间也就越长,也越吃硬件资源(算力和显存)

接下来是三个跟moe有关的参数,expert_num是专家的数量,moe_k则是用于控制在N个专家里取前k个参与计算,moe_layer_index是用于给不同专家做index标记。

llm小知识-moe:moe即Mixture-of-Experts,混合专家。是一种大模型结构上的优化,它使用MoE层替换掉了原来的FFN层,其中MoE层由多个专家FFN和一个router路由组成,每个token的隐藏状态经过router路由的计算,会被分配给多个(moe_k个)不同的专家Expert来完成计算

接下来是start_id和end_id,一般来说对于一个模型,start_id用于标记输入句子的开始,end_id用于表示decoder生成已经完成,在遇到生成的词为end_id时,就需要掐断自回归生成的过程了。

hidden_units_,是记录每个token隐藏状态大小的变量,一般来说这个大小会是size_per_head * head_num(也有例外,例如谷歌的gemma)

local_head_num,之前提到过我们可能会对模型进行tp划分,在MHA中,tp划分则是会对不同的head来进行切分,那么每张卡上就会只需要进行local_head_num / tp_num数量的头的计算,local_head_num就是用于进行单卡头数量记录的
tensor_para和pipeline_para,这两个参数是用于记录模型的tp和pp划分的,是NcclParam类型的变量,不同卡之间也可以靠这两个参数来完成Nccl通信。

一、模型推理参数

接下来可以初步看一下65~87行的代码,主要会涉及到模型推理过程的一些特殊功能和参数配置,挑其中几个比较重要的部分进行简单解释。

		std::shared_ptr<AbstractCustomComm> custom_all_reduce_comm_;int                                 enable_custom_all_reduce_;const bool is_context_qk_buf_float_ =(std::getenv("CONTEXT_ATTENTION_BMM1_HALF_ACCUM") == nullptr ||std::string(std::getenv("CONTEXT_ATTENTION_BMM1_HALF_ACCUM")) != "ON");size_t        vocab_size_padded_;const int     int8_mode_      = 0;AttentionType attention_type_ = AttentionType::UNFUSED_MHA;// Prompt Learning ParametersPromptLearningType prompt_learning_type_;int                prompt_learning_start_id_;  // start_id for prompt_learning (only needed by prefix prompts)bool               has_p_prompt_tuning_;bool               has_prefix_prompt_;bool               has_prefix_soft_prompt_;// GPT Variants parameters: e.g. Meta OPTgptVariantParams gpt_variant_params_;ParallelGptDecoder<T>*        gpt_decoder_;ParallelGptContextDecoder<T>* gpt_context_decoder_;DynamicDecodeLayer<float>*    dynamic_decode_layer_;

在65和66行,ft为不同模型提供了自定义的all reduce通信方法,但一般来说我们只需要使用nccl通信就可以完成这一功能,所以一般不用。

vocab_size_padded_,这个参数习惯上来说是对vocab_size按8的倍数向上取整的。为什么要取整?因为在最后一步从隐藏状态通过lm_head计算生成vocab_size时也需要进行tp划分,所以需要保证每个tp分到的vocab_size大小是可以整除的,而一个GPU节点上最多可以有8张卡(tp=8),所以习惯按照8的倍数向上取整

int8_mode_,这个是用于控制不同量化方法的参数,不同的int8mode对应不同的量化方法,常见的有fp8,w4a16等等,量化会在后续的代码解析中进行一些简单说明和分析

attention_type_是用于控制计算MHA的不同方法的参数,MHA的计算有融合和非融合两种方式,如果使用融合的方式,那么整个MHA的计算就是使用一整个大融合算子来实现,否则的话就还是按照分开的不同算子kernel来进行计算。

Prompt Learning Parameters这几个是模型中用于处理自己特定的prompt的参数(相比于它能带来的方便,其实看起来更多的是增加了很多繁琐的处理步骤,所以并不是很常见)

gpt_variant_params则是一个用于decoder结构中控制一些layernorm层是否需要计算的参数,看一下它的定义:

struct gptVariantParams {// GPT default paramsfloat          layernorm_eps   = 1e-6f;LayerNormType  layernorm_type  = LayerNormType::pre_layernorm;ActivationType activation_type = ActivationType::Gelu;// Whether to have a learnt positional encoding.bool has_positional_encoding = true;// A layernom just after the word embedding and before the decoder.bool has_pre_decoder_layernorm = false;// A layernom after the decoder.bool has_post_decoder_layernorm = true;// detoxification adapters. refer tobool   has_adapters       = false;size_t adapter_inter_size = 0;// Whether to use the attention linear positional biasbool use_attention_linear_bias = false;
};

在这个定义中可以看见,除了控制layernorm的eps参数以外,还以一系列用于控制layernorm位置的参数(has_pre_decoder_layernorm、has_post_decoder_layernorm等等)和激活函数的参数,为了方便统一读取和管理,全部放在了这个结构体中来进行读取控制。

接下来的三个指针gpt_decoder_,gpt_context_decoder_,dynamic_decode_layer_则是主要负责完成context-decoder到decoder到采样生成这个过程的最主要的部分,也是由这三个指针指向的类来负责完成model层的主要功能的组装

二、成员函数和buffer

下面是一些成员函数的简单解释以及buffer的说明,可以先看89行~107行

		void allocateBuffer() override;void allocateBuffer(size_t batch_size,size_t beam_width,size_t max_seq_len,size_t memory_len,size_t max_input_len,bool   is_return_context_cum_log_probs);void freeBuffer() override;void initialize();void computeContextCumLogProbs(float*                      cum_log_probs,const T*                    context_decoder_outputs,const int*                  input_ids,const int*                  input_lengths,const size_t                batch_size,const size_t                beam_width,const size_t                max_input_length,const ParallelGptWeight<T>* gpt_weights);

首先是用于对所有的buffer指针进行内存分配和显存分配的函数allocateBuffer,这个函数会在每次进行一次完整推理时用到,对推理过程中用到的buffer进行预分配,而完成推理之后,则是由freeBuffer()函数来对buffer进行一些释放。

而initialize()函数则是对函数内部的一些参数进行初始化操作,在这里面会对上面提到的三个model的组成部分指针进行创建

computeContextCumLogProbs函数则是提供了一种方法,如果在推理最后需要返回logits时对logits进行收集和计算的函数。

接下来,从109行到175行,是protect成员中一系列用于指向buffer的指针,这些指针在这里不会一一进行功能说明(真的太多了),在实际运行代码讲解中遇到的时候再进行简单说明。

在protect成员中还有两个函数,一个setOutputTensors和sendTensorsToFirstPipelineNode,这里的两个函数是在完成推理后,将数据按照tensor进行组装并返回到头节点中的。在没有进行pp切分时其实已经可以直接组装好了

在下面186到246行的代码中,是一些public成员函数,从函数名就可以直接看出这些函数的具体作用和功能,以及它们返回的结果是什么,这里就不再多做赘述了,可以简单提到的是registerCallback和unRegisterCallback这两个函数,这两个函数是用于注册和注销生成token并返回的回调函数的,这里涉及到返回生成结果的两种方式,流式和非流式,会在返回结果的过程中产生一些区别。

llm小知识-流式和非流式:在推理框架产生token之后,流式的返回方式会在每次产生一个token之后就立马返回一个token,非流式的返回方式则是在所有token都生成完毕之后再一次性返回所有token。这两种方式没有性能上的差异,只会有使用体验上的不同。一般来说,输出长度较长的交互式场景推荐使用流式,方便用户一边等待一边看,短输出场景、预测式场景适合使用非流式,一次性返回全部结果。

下一回预告

下一回将会从ParallelGpt.cc的代码开始讲解,对其部分功能函数以及主要的函数forward进行一些分析,在分析过程中会对一些buffer指针功能以及代码部分进行分析说明。在解析过程中会对一些不是非常重要的代码进行跳过,并不会逐条分析(很多都是用不上的)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java8 Stream API在集合上执行复杂的数据处理查询

Java 8 引入的 Stream API 是一个高级工具&#xff0c;用于在集合上执行复杂的数据处理查询。Stream API 通过提供一系列的中间操作和最终操作&#xff0c;支持声明式处理&#xff08;类似于SQL声明式语句&#xff09;并且可以轻松使用多核架构。 创建Stream流 创建Stream 流…

HTML+VUE3组合式+ELEMENT的容器模板示例(含侧栏导航,表格,...)

一个简单的在html中使用Vue3及Element-plus vue-icons的整合示例&#xff1a; 一、示例截图 二、文件代码 直接复制到html文件在浏览器打开即可预览 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title&g…

CCleaner系统优化与隐私保护工具,中文绿色便携版 v6.23.11010

01 软件介绍 CCleaner 是一款高级的系统优化工具&#xff0c;其设计宗旨在于彻底清理 Windows 操作系统中积累的无用文件和冗余的注册表项。此举旨在显著提升计算机的运行效率并回收磁盘空间。该软件拥有高效的能力&#xff0c;可以清除包括临时文件、浏览器缓存及其历史记录在…

哪些设计模式,你使用过哪些设计模式

Java框架中运用了多种设计模式&#xff0c;以下是一些具体的例子以及它们在框架中的应用&#xff1a; 单例模式&#xff08;Singleton Pattern&#xff09;&#xff1a; 确保一个类只有一个实例&#xff0c;并提供全局访问点。例如&#xff0c;Java中的Runtime类使用了单例模式…

08 - hive的集合函数、高级聚合函数、炸裂函数以及窗口函数

目录 1、集合函数 1.1、size&#xff1a;集合中元素的个数 1.2、map&#xff1a;创建map集合 1.3、map_keys&#xff1a; 返回map中的key 1.4、map_values: 返回map中的value 1.5、array 声明array集合 1.6、array_contains: 判断array中是否包含某个元素 1.7、sort_a…

python中多态的概念及简单样例

目录 1、多态概念及关键要素&#xff1a; 2、代码样例&#xff1a; 1、多态概念及关键要素&#xff1a; 多态是面向对象编程中一个重要的概念&#xff0c;它允许不同类的对象对同一消息做出不同的响应。简单来说&#xff0c;多态性是指相同的方法调用可以在不同的对象上产生不…

UIKit之UIButton

功能需求&#xff1a; 点击按钮切换按钮的文字和背景图片&#xff0c;同时点击上下左右可以移动图片位置&#xff0c;点击加或减可以放大或缩小图片。 分析&#xff1a; 实现一个UIView的子类即可&#xff0c;该子类包含多个按钮。 实现步骤&#xff1a; 使用OC语言&#xf…

TypeScript常见面试题第七节

题目三十一:TypeScript 中声明合并的工作原理? 一、讲解视频 TS面试题三十一:TypeScript 中声明合并的工作原理? 二、题目解析 本题目考察对于 ts 中声明合并知识的了解,“声明合并”是指编译器将针对同一个名字的两个独立声明合并为单一声明。 合并后的声明同时拥有原先…

每日资讯——OpenAI与谷歌相争,火药味甚浓

OpenAI与苹果达成合作&#xff0c;ChatGPT或集成至IOS18 AI语音助手存在”幻觉“问题&#xff0c;或将集成至ChatGPT免费版 整合音频转录、文本转语音等功能的软件。奥特曼的终极目标是开发类似电影《她》中&#xff0c;可高度响应的虚拟助手&#xff0c;提升苹果Siri等现有语…

HCIP的学习(14)

过滤策略—filter-policy ​ 思科中&#xff1a;分发列表 ​ 过滤策略是只能够针对于路由信息进行筛选&#xff08;过滤&#xff09;的工具&#xff0c;而无法针对于LSA进行过滤。 在R4的出方向上配置过滤策略&#xff0c;使得R1不能学习到23.0.0.0/24路由信息1、抓取流量 […

Sping源码(七)—ConfigurationClassPostProcessor ——@PropertySources解析

序言 先来简单回顾一下ConfigurationClassPostProcessor大致的一个处理流程&#xff0c;再来详细的讲解PropertySources注解的处理逻辑。 详细的步骤可参考ConfigurationClassPostProcessor这篇帖子。 流程图 从获取所有BeanDefinition -> 过滤、赋值、遍历 -> 解析 -&…

自建WSUS更新服务器完成内网的安全补丁更新

一、适用场景 1、企业内部网络无法访问外网&#xff0c;所以搭建WSUS服务器&#xff0c;可以让内网环境进行更新补丁。 2、校园内部的电脑实训室一般不用外网资源&#xff0c;偶尔开启外网使用时&#xff0c;电脑实训室集体自动更新占用外网资源量大&#xff0c;所以搭建WSUS服…

项目文档分享

Hello , 我是小恒。提前祝福妈妈母亲节快乐 。 本文写一篇初成的项目文档 &#xff08;不是README.md哈&#xff09;&#xff0c;仅供参考 项目名称 脚本存储网页 项目简介 本项目旨在创建一个网页&#xff0c;用于存储和展示各种命令&#xff0c;用户可以通过粘贴复制命令到…

【深耕 Python】Quantum Computing 量子计算机(6)计算<m|V|n>数值积分

写在前面 往期量子计算机博客&#xff1a; 【深耕 Python】Quantum Computing 量子计算机&#xff08;1&#xff09;图像绘制基础 【深耕 Python】Quantum Computing 量子计算机&#xff08;2&#xff09;绘制电子运动平面波 【深耕 Python】Quantum Computing 量子计算机&…

【前端】HTML实现个人简历信息展示页面

文章目录 前言一、 综合案例&#xff1a;个人简历信息展示页面 前言 这篇博客仅仅是对HTML的基本结构进行了一些说明&#xff0c;关于HTML的更多讲解以及CSS、Javascript部分的讲解可以关注一下下面的专栏&#xff0c;会持续更新的。 链接&#xff1a; Web前端学习专栏 下面我…

039——解决室内不能使用GPS问题

目录 引入 GUI整改 client添加GPS分析 完善服务器网络通讯部分代码 添加GPS的BSW层 GPS操作部分代码&#xff08;相当于驱动&#xff09; 效果展示 项目管理操作 引入 最近在写论文加上出去玩了一圈所以停更了一段时间。上次咱们GPS有个室内用不了的问题&#xff0c;咱…

【Python从入门到进阶】54、使用Python轻松操作SQLite数据库

一、引言 1、什么是SQLite SQLite的起源可以追溯到2000年&#xff0c;由D. Richard Hipp&#xff08;理查德希普&#xff09;所创建。作为一个独立的开发者&#xff0c;Hipp在寻找一个能够在嵌入式系统中使用的轻量级数据库时&#xff0c;发现现有的解决方案要么过于庞大&…

SpringCloud使用Nacos作为配置中心实现动态数据源切换

一、Nacos-Server 了解Nacos可以直接阅读官方文档 使用Nacos&#xff0c;我们需要有Nacos-Server&#xff0c;此处就不使用官方提供的release版本了&#xff0c;而是自己编译&#xff0c;因为本来就是Java开发的&#xff0c;所以对于Javaer来说也没啥难度&#xff01; git c…

linux安装clamav病毒扫描与删除

ClamAV介绍 ClamAV是Linux操作系统一款免费的杀毒工具&#xff0c;通过命令执行病毒库升级、查找病毒和删除病毒。 安装ClamAV 方法一&#x1f4a1; Tips&#xff1a;在CentOS操作系统上安装ClamAV&#xff0c;请分别执行以下命令 yum install epel-release -y yum install cla…

2024OD机试卷-虚拟理财游戏 (java)

题目:虚拟理财游戏 题目描述 在一款虚拟游戏中生活,你必须进行投资以增强在虚拟游戏中的资产以免被淘汰出局。 现有一家Bank,它提供有若干理财产品 m 个,风险及投资回报不同,你有 N(元)进行投资,能接收的总风险值为X。 你要在可接受范围内选择最优的投资方式获得最大…