从FasterTransformer源码解读开始了解大模型(1.1)一个decoder-only的模型长啥样

从FasterTransformer源码解读开始了解大模型(1.1)一个decoder-only的模型长啥样

写在前面的话

对于一个没有接触过LLM的初学者来说,如果想要了解一个大模型的推理框架,首先应该知道大模型整个的工作原理是怎样的,知道transformers的结构是怎么生成词的,否则很容易会在读代码的过程中越读越迷糊,进入一种“我在哪里?我在看什么?这一段是做什么的”困惑状态,所以在此先推荐从来没有接触过相关知识的同学去读一下Attention is all you need的论文原文。当然,对于一些初学者来说,读完这篇论文也会陷入一种半懂不懂的困惑状态,但是会在心中搭建起一个隐隐约约的初步的形状,在后面再回到工程代码的阅读中,这个隐隐约约的形状会被一步一步填充起来,变成一个清晰的样子。这里的FT源码解读的第二篇文章会直接从结构开始讲起,就不会讨论那么多“为什么这个结构是有效的”“为什么多头注意力要这样做设计”的问题了。

在写这篇文档的过程中,我发现自己对LLM框架的认知也并没有十分地清晰明了,如果整个解读过程中有不正确之处或者不够清晰的地方,也希望老师同学们能够指出和讨论 Orz

零、最初的样子

让我们回顾一下最初始的时候,Attention is all you need中所描述的encoder-decoder结构是怎样的:

在这里插入图片描述

这里是原论文中的结构,刚开始看是否有些半懂不懂?(个人认为这张结构解释图对初学者来说并不能算得上清晰明了hhhh)拆开来看的话,整个结构分为两块,左边的encoder和右边的decoder,在encoder的这半边,不做任何的ids的输出,只负责处理输入数据。真正输出ids的,则是decoder的部分,负责自回归地进行处理,往外一个一个吐词儿(从output probabilities中选出ids),在一些早期的大模型,如Bart、T5等等,依然遵循了encoder-decoder的结构。

一、decoder-only的样子

经过一段时间的代码模型的发展,很多流行的模型,比如gpt2,还有现在最流行的llama系列等等,都采用了decoder-only的样子,而从结构上来看,llama比gpt2,bloom这种还要更简单一些,但是却变得更加普遍和流行。所谓大道至简,大概就是这个道理罢。

decoder-only大概长成下面这个样子
在这里插入图片描述
decoder-only只保留了decoder的MHA的处理结构(MHA-Add&Norm-FFN-Add&Norm),对于输入来说,是一整个扔进去decoder结构的处理,对于生成阶段,依然是decoder结构(所以才叫decoder-only)。在FasterTransformer中,它将输入阶段的decoder称作ContextDecoder阶段,即上下文解码阶段(在有些框架中则习惯性地照旧称为encoder阶段但实际上处理有所区别,也有称为prefill阶段的),而实际自回归产生ids输出的阶段依然叫做decoder阶段。

可以看一下图中的流程,输入的ids经过embedding之后,会为句子中的每一个id生成一个hidden states(隐藏状态,在整个layer里的计算过程中其实都是以hidden stats隐藏状态的样子参与到运算中)。

之后隐藏状态会进入到layers中进行计算,每一层layer(在HuggingFace的transformer源码中称之为blocks)都包含了自己的layernorm、MHA、add residual、FFN等结构。在完成某一层(layer x)的计算后,输出得到的hidden states会作为下一层(layer x+1)的输入再次进入layer运算,直到所有的层计算完毕,最后一层输出的hidden states再经过一个lm head(线性层),产生一个跟词表长度一样长的raw logits数组,对这个raw logits进行softmax和采样选取,最终就可以得到这一次生成的结果output id了。

如果这个output id不是end id(结束词),可以将它作为输入再次喂给整个decoder结构,就实现一个自回归生成的过程。

llm小知识-模型的差异:这里的decoder-only模型并不是唯一标准化的,有些模型会在一些地方少掉第一次 pre-layernorm或者替换layernorm为其他的归一化操作(比如llama使用的是RMSnorm),有些是会增加或减少layernorm中的bias,有些模型则是会插入一些差异性的norm(比如google的gemma),但是总体来说MHA和FFN这两个大模块都不会缺失或者产生大的变化,在这两个模块计算完成后的add residual操作和norm操作也很少会做一些大的结构上的变化

在ft实际的处理逻辑中,在context decoder阶段,其中MHA依然遵守着前向的规则,即每一个词都只会跟自己前面的词计算注意力得分,并且将MHA计算注意力过程中所得到的K和V给记录下来(即K/V Cache)以在后续的计算过程中节省计算时间,在完成了context-decoder时最终会得到一个logits,这个logits将会成为生成的第一个词,也是自回归decoder阶段的第一个输入的词,由此,整个自回归生成就开始循环。

有些新入门的同学可能会疑惑,隐藏状态是如何生成的?MHA或者FFN这些必要模块具体是怎么进行计算的?算出来又都是什么样的结果呢?这里如果着急可以直接去看HuggingFace的transformer的源码,其中每个modeling都会有自己的对应实现,如果不着急的话,后续的源码解读都会一一给出答案。

二、从源码角度来看结构

我们再从代码的角度来看一下,FT的源码在搭建一个模型的时候,是否符合我们刚刚描述的结构.

打开ft的源码,进入gpt的目录src/fastertransformer/models/multi_gpu_gpt,可以看见从model层,gpt所有需要的模块和代码:
在这里插入图片描述

其中模型的主文件叫做ParallelGpt,它负责一整个模型的组装和模型的计算。就是我们之前所描述的一整个的decoder-only结构,以及其他的一些内容。

可以看见这里分为两个部分,负责处理输入部分的叫做ParallelGptContextDecoder,就是我们之前所描述的负责做context decoder的结构,负责做生成的叫做ParallelGptDecoder,由它来完成output ids的生成。

另外,还有两个weight相关的模块代码,ParallelGptWeight对应着一整个的ParallelGpt计算所需要的权重,由这个模块负责进行管理。而ParallelGptWeight中则通过一个数组来管理每一层(layers)的单独的权重,每一层单独的权重是由ParallelGptDecoderLayerWeight来组成和管理。

而在ParallelGptContextDecoder以及ParallelGptDecoder中所使用到的比如MHA模块,以及FFN模块等等,则全都在另一个目录下,src/fastertransformer/layers这个目录下进行管理。在这个目录下你可以找到所有关于单层layer中需要的计算和处理的模块,包括不同模型的MHA或者FFN等等。

从上面也可以看见,FT的文件组织基本符合我们所描述的模型结构,模型(models)下面有自己的结构,每个结构中的层(layers)中所包含的结构则由另外一个layers文件夹中的代码文件来进行管理和实现。

下一回预告

下一回将会正式开始源码解读的环节,从ParallelGpt.cc的代码开始讲解。伴随着源码讲解,也会附加一些大模型工程上的内容和概念,尽量做到说清楚,说明白。不过由于ft源码本身在上面增加了很多的补丁和if/else,所以需要稍微做一些抽丝剥茧一般的筛选。

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

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

相关文章

了解自动化机器学习 AutoML

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 自动化机器学习(AutoML)概述 自动化机器学习(AutoML)旨在自动化机器学习模型的开发流程,通过简化或去除需要专业知识的复杂步骤,…

CSS面试题常用知识总结day03

大家好我是没钱的君子下流坯,用自己的话解释自己的知识 前端行业下坡路,甚至可说前端已死,我还想在前段行业在干下去,所以从新开始储备自己的知识。 从CSS——>Javascript——>VUE2——>Vuex、VueRouter、webpack——>…

Stale Diffusion、Drag Your Noise、PhysReaction、CityGaussian

本文首发于公众号:机器感知 Stale Diffusion、Drag Your Noise、PhysReaction、CityGaussian Drag Your Noise: Interactive Point-based Editing via Diffusion Semantic Propagation Point-based interactive editing serves as an essential tool to compleme…

vite打包失败 - out of memory

在做项目时&#xff0c;随着需求的不断增加&#xff0c;我们的代码文件会越来越大&#xff0c;但是在打包时&#xff0c;在 Node 中通过 JavaScript 使用内存的大小却是有限制的。于是&#xff0c;今天打算部署代码时&#xff0c;报错了: <--- JS stacktrace ---> JS st…

Nuxt 3 项目中配置 Tailwind CSS

官方文档&#xff1a;https://www.tailwindcss.cn/docs/guides/nuxtjs#standard 安装 Tailwind CSS 及其相关依赖 执行如下命令&#xff0c;在 Nuxt 项目中安装 Tailwind CSS 及其相关依赖 npm install -D tailwindcss postcss autoprefixerpnpm install -D tailwindcss post…

VUE必知必会

一、简介 Vue.js是一个流行的JavaScript框架&#xff0c;用于构建用户界面和单页应用程序&#xff08;SPA&#xff09;。自2014年由前Google工程师尤雨溪发布以来&#xff0c;Vue迅速获得了广泛的关注和使用&#xff0c;特别是在前端开发领域。 核心特性 响应式数据绑定&#…

【cpp】快速排序优化

标题&#xff1a;【cpp】快速排序 水墨不写bug 正文开始&#xff1a; 快速排序的局限性&#xff1a; 虽然快速排序是一种高效的排序算法&#xff0c;但也存在一些局限性&#xff1a; 最坏情况下的时间复杂度&#xff1a;如果选择的基准元素不合适&#xff0c;或者数组中存在大…

vue基本写法

<p style"margin-left:.0001pt;text-align:justify;">Vue.js 是一种流行的 JavaScript 框架&#xff0c;用于构建用户界面。下面是 Vue.js 的一些标准写法和最佳实践:</p> 1. Vue 实例&#xff1a; 创建 Vue 实例时&#xff0c;可以指定一些选项来定义应…

Netty 3 - 组件和设计

这里将回顾我们之前章节讲到过的主要概念和组件。 1 Channel 、EventLoop和ChannelFuture Channel —— Socket;EventLoop —— 控制流、多线程处理、并发;ChannelFuture —— 异步通知。 1.1 Channel 接口 基本的I/O操作&#xff08;bind()、connect()、read()和write()&a…

【嵌入式开发 Linux 常用命令系列 4.3 -- git add 不 add untracked file】

请阅读【嵌入式开发学习必备专栏 】 文章目录 git add 不add untracked file git add 不add untracked file 如果你想要Git在执行git add .时不添加未跟踪的文件&#xff08;untracked files&#xff09;&#xff0c;你可以使用以下命令&#xff1a; git add -u这个命令只会加…

boost共享内存使用(3)managed_shared_memory共享内存分配器

文章目录 概述使用示例 概述 Boost.Interprocess提供了一些基本的类来创建共享内存对象和文件映射&#xff0c;并将这些可映射的类映射到进程的地址空间中。 然而&#xff0c;管理这些内存段对于非平凡的任务来说并不容易。一个映射区域是一个固定长度的内存缓冲区&#xff0…

免注册,ChatGPT可即时访问了!

AI又有啥进展&#xff1f;一起看看吧 Apple进军个人家用机器人 Apple在放弃自动驾驶汽车项目并推出混合现实头显后&#xff0c;正在进军个人机器人领域&#xff0c;处于开发家用环境机器人的早期阶段 报告中提到了两种可能的机器人设计。一种是移动机器人&#xff0c;可以跟…

鸿蒙OS元服务开发:【(Stage模型)学习窗口沉浸式能力】

一、体验窗口沉浸式能力说明 在看视频、玩游戏等场景下&#xff0c;用户往往希望隐藏状态栏、导航栏等不必要的系统窗口&#xff0c;从而获得更佳的沉浸式体验。此时可以借助窗口沉浸式能力&#xff08;窗口沉浸式能力都是针对应用主窗口而言的&#xff09;&#xff0c;达到预…

二叉堆解读

在数据结构和算法中&#xff0c;二叉堆是一种非常重要的数据结构&#xff0c;它被广泛用于实现优先队列、堆排序等场景。本文将介绍二叉堆的基本概念、性质、操作以及应用场景。 一、基本概念 二叉堆是一种特殊的完全二叉树&#xff0c;它满足堆性质&#xff1a;对于每个节点…

练习题(2024/4/3)

1题目描述&#xff1a; 给定两个大小分别为 m 和 n 的正序&#xff08;从小到大&#xff09;数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为 O(log (mn)) 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,3], nums2 [2] 输出&…

Redis Hash结构操作

基础篇Redis 6.4 Hash结构操作 在基础篇的最后&#xff0c;咱们对Hash结构操作一下&#xff0c;收一个小尾巴&#xff0c;这个代码咱们就不再解释啦 马上就开始新的篇章~~~进入到我们的Redis实战篇 SpringBootTest class RedisStringTests {Autowiredprivate StringRedisTe…

电子商务平台中大数据的应用|主流电商平台大数据采集API接口

(一)电商平台物流管理中大数据的应用 电商平台订单详情订单列表物流信息API接口应用 电子商务企业对射频识别设备、条形码扫描设备、全球定位系统及销售网站、交通、库存等管理软件数据进行实时或近实时的分析研究,提高物流速度和准确性。部分电商平台已建立高效的物流配送网…

什么是Java中的分布式系统?举例说明

在Java中&#xff0c;分布式系统是由一组通过网络进行通信、为了完成共同的任务而协调工作的计算机节点组成的系统。这种系统架构的目的是利用更多的机器处理更多的数据&#xff0c;从而解决单个计算机无法应对的计算、存储任务。 当单个节点的处理能力无法满足日益增长的计算…

【STL】vector的底层原理及其实现

vector的介绍 vector是一个可变的数组序列容器。 1.vector的底层实际上就是一个数组。因此vector也可以采用连续存储空间来存储元素。也可以直接用下标访问vector的元素。我们完全可以把它就当成一个自定义类型的数组使用。 2.除了可以直接用下标访问元素&#xff0c;vector还…

掌握数据相关性新利器:基于R、Python的Copula变量相关性分析及AI大模型应用探索

在工程、水文和金融等各学科的研究中&#xff0c;总是会遇到很多变量&#xff0c;研究这些相互纠缠的变量间的相关关系是各学科的研究的重点。虽然皮尔逊相关、秩相关等相关系数提供了变量间相关关系的粗略结果&#xff0c;但这些系数都存在着无法克服的困难。例如&#xff0c;…