从FasterTransformer源码解读开始了解大模型(1.0)了解FasterTransformer

从FasterTransformer源码解读开始了解大模型(1.0)了解FasterTransformer

写在前面的话

最近的一年时间真是令人感慨,换了个工作方向,学了些深度算子开发相关知识,工作也转到对LLM的学习和开发了。入行不算深,还需要对整个LLM大模型进行更精细的了解。

如果从模型结构层去学习去看的话,HuggingFace的transformers仓库源码包含了多种多样的大模型结构源码,很方便去进行学习,每个model都有自己的modeling模型文件,适合去了解学习。不过从性能、算子结构以及作为一个大模型推理引擎的角度来看的话,NV的FasterTransformer作为一个推理引擎虽然已经并不是很跟得上时代了,不过从结构和算子的角度来看仍有可取之处。

之所以没有跟ffmpeg系列一样在前面写上"学龄前",是因为有些cuda的基础知识确实不是学龄前的水平,先掌握一点cuda技术栈的基础知识会更适合学习大模型工程代码,硬要说的话应该算是一二年级吧(大概),在代码解读中也会适当添加一些llm小知识,在添加小知识的过程中也可以得到学习

初步的源码学习计划

从FasterTransformer的现有源码开始进行分析,以GPT2或者Bloom结构(二者在结构上基本是近似的)为例来学习一些decoder only的模型,分析整个LLM的模型结构,之后再基于FasterTransform框架,将现在比较流行的类Llama结构的模型Llama2进行适配(原生的FasterTransformer目前是不支持Llama的)。

为什么是GPT2(BLOOM)? 在fastertransformer的multi_gpu_gpt代码中, 能够看到很多比较成熟的大模型框架的结构特点,如PP/TP划分,moe(混合专家)处理以及卡间通行等等,所以可以用来作为进行整体架构分析学习的不错的材料。更重要的一个原因是FasterTransformer里没有Llama,不然就讲llama了(悲)。不过没关系,等熟悉了源码之后,我们可以将llama集成到这个框架中,这样能够学习的更加深刻

零、什么是FasterTransformer

如果用简单的一句话来概括,FasterTransformer(下文简称FT或者ft)是一个用于大语言模型的推理引擎。目前ft的源代码里集成了bart,bert,gpt2(代码中叫multi_gpu_gpt)、t5等模型,如果有一定开发能力,还可以自己在ft里集成llama、chatglm等模型。

ft可以作为Triton(https://developer.nvidia.cn/triton-inference-server)的一个推理后端(backend)来提供推理服务,同时也可以自己编译自己的,直接进行离线推理,而ft的推理性能上是优于一些使用python的推理框架的(可以将ft的推理看做是一个巨大的cuda和C++的融合算子)。ft的代码是基于CUDA、cuBLAS的C++代码,卡间通信则是会使用到NCCL,如果能够较好的掌握ft的代码,除了能够了解一个基础的LLM推理引擎的基本架构是怎样的,也能够给自己的cuda相关知识以及c++基础知识带来一定好处。(虽然ft的代码写的并不是非常的优美,而且也存在一定资源调度等等的问题,但并不妨碍初学者从其中学到一些值得借鉴的东西)

ft仓库:https://github.com/NVIDIA/FasterTransformer

一、初看代码结构

如果要从结构上了解ft,那么直接从ft的源代码上开始看比较好。将ft的代码直接clone下来,其中主要的源代码在FasterTransformer/src文件夹中,其中可以看见多个子文件夹,从中可以看见ft的功能层次也划分的比较清晰:
在这里插入图片描述
cutlass_extensions:这个文件夹提供了基于cutlass的一些GEMM算子和量化GEMM算子(混合精度计算)的支持(GEMM通用矩阵乘,General Matrix Multiplication)

llm小知识-通用矩阵乘GEMM:其实大部分LLM中使用到的算子并不算多,其中主要的计算都是在做矩阵乘,所以很多加速推理的框架都是在各种各样的矩阵乘算法优化上下功夫,解决了GEMM优化的问题,就能够对推理框架的性能进行很可观的提升

kernels:这个文件夹内是所有models中注册的算子会使用到的一些cuda kernel,包括一些转置的kernel(transpose_*.cu),一些采样的kernel(sampling_topk、topp,beam search等等),一些基础算子(layernorm,激活activation_kernel)以及量化算子等等,它们由models和layers中的模型以及算子层来进行调用,负责在cuda上实现一些推理过程中的不同功能。

llm小知识-采样:这里的采样指的是概率的选取方式。大模型生成词的过程是会生成一个基于词表的logits,比如llama2的词表大小是32000个,那么每一步的生成就会产生32000个logits,对所有的logits进行排序,如果是topk采样,是取最高的k个词作为本次的生成词,如果是topp采样,则是将排在前面的词的logist一个个加起来直到大于等于p为止,这些词作为生成词。而beam search则是一种选取策略,比如设置beam search宽度为2,则是每次取两个词,将这两个词作为下一step的输入,那么选取最优可以得到四个词,从这四个最优词中再选取两个作为下一个step的输入,以此类推

layers:这个文件夹内是提供给models中进行大模型组装的功能层,其中包括linear线性层(adapter_layers),attention注意力层(attention_layers),beam search层,sampling采样层,FFN层和用于模型最后做一些dynamic处理的dynamicdecoder层等等,这些层主要是提供给model进行组装,内部的计算则是通过调用kernels中的一些算子kernel和cublas来进行实现

llm小知识-attention:关于attention就不得不提到经典的attention is all you need这篇文章了,如果不了解attention的建议去看一下或者找一些相关材料进行学习,attention机制可以说是所有大语言模型的基石,在这里就不进行展开赘述

models:这个文件夹里是所有目前ft支持的模型,每个模型都按照名称排列好,其中包括一些耳熟能详的bert、GPT(multi-gpu-gpt),t5等等,每个模型的实际处理逻辑和实现都是在这个文件夹中,在这里也可以学习到一些经典的大语言模型的结构,也可以算是源码解读的核心部分了。

tensorrt-plugin/tf_op/th_op/triton_backend:这几个文件夹则是为主流的一些服务框架和深度学习框架提供了ft的接口,通过这几个文件夹中的功能实现,能够在不同的深度学习框架和推理服务框架中接入ft,完成模型推理。后续代码解读会以triton_backend为例进行一些展开讲解

utils:这个文件夹则是实现了一些通用的工具类接口,包括不同数据类型的cublas矩阵乘,数据类型转换,内存管理单元、nccl通信单元和一些数据结构基础定义等等,它们主要是服务于models和layers中,类似于帮助框架实现基础功能的toolkit

##二、编译和测试

2.1 FT的编译

ft进行编译要相对简单,需要一个包含cuda相关库的基础环境,之后在主目录下新建一个build文件夹,按照需要填好自己的CMake编译项就可以了,这里以A100环境举例,DSM就需要设置为80。如果是其他的卡可以按实际情况,不同卡的CUDA架构和计算能力进行修改(https://developer.nvidia.com/cuda-gpus#compute)

mkdir build
cd build
cmake -DCMKAE_EXPORT_COMPILE_COMMANDS=1 \-DCMAKE_BUILD_TYPE=Release \-DCMAKE_INSTALL_PREFIX:PATH=./install/backend \-DSM=80 ..
make && make install

2.2 模型权重的转换

目前比较通用的开源大模型很多都可以在HuggingFace的官方库中找到,国内也有更新比较快的HuggingFace镜像站,在上面可以下砸到很多模型,这些模型可以通过transformers库直接加载,大多是以pytorch的方式或者safetensor的格式来存储的。而FT则需要进行权重转换,转换成FT自己的加载格式

在权重下载之后就可以进行转换了,好消息是官方提供了从HuggingFace权重到ft权重的转换脚本,在ft目录中的examples/pytorch/gpt/utils/huggingface_gpt_convert.py,直接使用这个python脚本就可以完成模型权重的转化了。

python3 huggingface_gpt_convert.py -saved_dir <save_path> -i <huggingface_model_path> -t_g 1 -i_g 1 -p 20

在脚本输入的参数中,包含一个参数叫-i_g,这个参数实际上会影响到在ft做推理时使用的TP数量,也会跟推理所使用的GPU数量有关,可以先不用考虑太复杂的情况,先使用一个GPU来进行(TP=1)

llm小知识-TP/PP:TP和PP是两种大模型的前向计算方式,TP为张量并行,PP为流水线并行,除此以外还有DP数据并行,后面做代码分析和模型解释的时候会更加详细地进行说明

权重转换完成后,会在<save_path>中找到我们转换后的权重,有一个1-gpu的文件夹,其中包含一个config.ini配置文件以及一堆.bin文件,这些bin文件是GPT模型中每一层计算的权重,config.ini则用于配置推理任务的各个参数项。为了把ft中的multi-gpu-gpt的example跑起来,我们还需要对config.ini做适当修改,参考下面修改后的config.ini

[ft_instance_hyperparameter]
model_name = gpt
model_dir = <save_path>/1-gpu
data_type = fp16
sparse = 0
int8_mode = 0
tensor_para_size = 1
pipeline_para_size = 1
max_seq_len = 1024
beam_width = 1
top_k = 1
top_p = 1
temperature = 1
request_batch_size = 1
beam_search_diversity_rate = 1
len_penalty = 1[gpt]
model_name = gpt
model_dir = <save_path>/1-gpu
head_num = 12
size_per_head = 64
inter_size = 3072
max_pos_seq_len = 1024
decoder_layers = 12
num_layer = 12
vocab_size = 50275
start_id = 50256
end_id = 50256
weight_data_type = fp16
tensor_para_size = 1
pipeline_para_size = 1
int8_mode = 0
sparse = 0
data_type = fp16[request]
request_batch_size = 1
request_output_len = 128

在这些参数中我们可以看见之前解释过的一些概念,例如topk/topp,PP/TP(pipeline_para_size/tensor_para_size),用于beam_search的beam_width等等。在ft_instance_hyperparameter中主要是一些任务型超参,是配置整个推理任务的,而gpt中则是一些结构型超参,是用于描述整个模型结构的,而request则是用于描述推理请求的。这里的参数太多,在第一篇文章中不会一一做解释,后面从源码解读上会将它们一一遍历解读的。

2.3 example测试

好了,一切准备就绪,看一下我们的样例运行起来会是怎样的吧。进入build/bin目录,这里有我们一开始编译完成的可执行文件,测试使用的输入的ids的话可以在examples/cpp/multi_gpu_gpt/start_dis.csv中找到,直接执行一下我们的测试:

./multi_gpu_gpt_example <save_path>/1-gpu/config.ini ../../examples/cpp/multi_gpu_gpt/start_dis.csv

稍微等待一下,便可以看到examples给我们吐出了它的推理结果
在这里插入图片描述
为什么是一行奇怪的数字?这里要提到一点就是在大模型推理中,每个人类所看见的字符都会通过一个词表映射到数字上,真正用于作为推理的输入以及输出实际上就是这些ids,一般称之为token_ids。那么该如何将ids转换成我们能看懂的话(words),或者将我们能看懂的话(words)转换为ids呢,可以借助transformers库来完成:

from transformers import AutoTokenizertokenizer = AutoTokenizer.from_pretrained("<model_path>", trust_remote_code=True)
# 这里要输入你的HuggingFace模型路径model_path#之后调用tokenizer的encode(将words转换为ids)或者decode(将ids转换为words)就可以了
ids = tokenizer.encode("how are you",return_tensors='pt')
print(ids)
words = tokenizer.decode([818, 262, 938, 3155, 286, 1528, 11, 257, 1688, 4652])
print(words)

下一回预告

下一回将会从代码开始入手,先整理描绘一个decoder-only结构模型应该有的样子,然后开始深入模型层(models)代码,参考模型结构来进行源码解读。好的开始是成功的一半,希望这一篇文章能够带来良好的开头,作为一个进入大模型世界的良好导航。努力尽可能保持一到两周一更新的频率吧(虽然也不知道能够坚持多久)

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

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

相关文章

谷粒商城——缓存的概念

1. 使用缓存的好处&#xff1a;减少数据库的访问频率&#xff0c;提高用户获取数据的速度。 2. 什么样的数据适合存储到缓存中&#xff1f; ①及时性、数据一致性要求不高的数据&#xff0c;例如物流信息、商品类目信息 ②访问量大更新频率不高的数据(读多、写少) 3. 读模式…

加密技术概述

传输数据时的四个问题 窃听 数字加密 假冒 消息认证或数字签名 篡改 消息认证码或数字签名 事后否认 数字签名 加密技术 将数据变成第三者的计算机无法理解的形式&#xff0c;然后再将其恢复成原本数据的一系列操作就是加密技术。 哈希函数 哈希函数可以把给定的数据转…

设计模式之状态模式(一)

设计模式专栏&#xff1a; http://t.csdnimg.cn/4Mt4u 目录 1.概述 2.结构 3.实现 4.总结 1.概述 状态模式( State Pattern)也称为状态机模式( State Machine pattern), 是允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类, 属于行为型模式。 在状…

Vue3+echarts绘制世界地图

先放效果图 之前所查找的资料都没有讲清楚如何引入地图文件并绘制地图&#xff0c;下面做一个记录。 首先下载对应的地图json文件&#xff0c;这里可以参考我的这篇文章&#xff0c;提供了下载地址&#xff1a;记录echarts各种地图json文件下载地址-CSDN博客 第二步&#xff…

笔记本和台式机主板内部结构分析

笔记本和态势机主板内存接口以及配件安装位置 笔记本主板 1 以thinkpad L-490为例,使用拆机小工具拆机&#xff0c;打开后面板&#xff0c;内部结构示意图如下 台式机主板 以技嘉-B660M-AORUS-PRO-AX型号主板为例 笔记本电脑和台式机电脑的相同之处 CPU&#xff1a;笔记本…

【boost_search搜索引擎】1.获取数据源

boost搜索引擎 1、项目介绍2、获取数据源 1、项目介绍 boost_search项目和百度那种不一样&#xff0c;百度是全站搜索&#xff0c;而boost_search是一个站内搜索。而项目的宏观上实现思路就如同图上的思路。 2、获取数据源 我们要实现一个站内搜索&#xff0c;我们就要有这…

Rust 程序设计语言学习——结构体

结构体和元组类似&#xff0c;它们都包含多个相关的值。和元组一样&#xff0c;结构体的每一部分可以是不同类型。但不同于元组&#xff0c;结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字&#xff0c;结构体比元组更灵活&#xff1a;不需要依赖顺序来…

医院预约挂号系统设计与实现|jsp+ Mysql+Java+ Tomcat(可运行源码+数据库+设计文档)

本项目包含可运行源码数据库LW&#xff0c;文末可获取本项目的所有资料。 推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 2024年56套包含java&#xff0c;…

初识kafka-数据存储篇1

目录 背景 1 kafka总体体系结构 2 疑问解答 2.1 高吞吐低延迟 2.2 实现分布式存储和数据读取 2.3 如何保证数据不丢失 背景 最近在和产品过项目审批的时候&#xff0c;深刻感受到业务方对系统的时时响应提出了更高的要求。目前手上大部分的业务都是基础定时任务去实现的&…

nodejs+vue高校会议室预订管理系统python-flask-django-php

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对系统进行规范而严格是十分有必要的&#xff0c;所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套高校会议室预订管理系统&#xff0c;帮助学校进行会议…

JDK,JRE,JVM之间的关系

他们明面上的关系是JDK包含JRE&#xff0c;JRE包含JVM。 简单理解JDK就是Java开发工具包。JRE是Java运行环境。JVM是Java虚拟机。 JDK是面向开发者的&#xff0c;JRE是面向JAVA程序的用户的。也就是说开发者开发JAVA程序是需要用到JDK&#xff0c;如果用户不去开发JAVA程序&am…

OpenHarmony IDL工具规格及使用说明书(仅对系统应用开放)

IDL接口描述语言简介 当客户端和服务器进行IPC通信时&#xff0c;需要定义双方都认可的接口&#xff0c;以保障双方可以成功通信&#xff0c;OpenHarmony IDL&#xff08;OpenHarmony Interface Definition Language&#xff09;则是一种定义此类接口的工具。OpenHarmony IDL先…

初识 Redis 浅谈分布式

目 录 一.认识 Redis二.浅谈分布式单机架构分布式是什么数据库分离和负载均衡理解负载均衡数据库读写分离引入缓存数据库分库分表引入微服务 三.概念补充四.分布式小结 一.认识 Redis 在 Redis 官网我们可以看到介绍 翻译过来就是&#xff1a;数以百万计的开发人员用作缓存、…

nodejs+vue高校社团管理小程序的设计与实现python-flask-django-php

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低学校的运营人员成本&#xff0c;实现了高校社团管理的标准化、制度化、程序化的管理&#xff0c;有效地防止了高校社团管理的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够及时、准…

t-rex2开放集目标检测

论文链接&#xff1a;http://arxiv.org/abs/2403.14610v1 项目链接&#xff1a;https://github.com/IDEA-Research/T-Rex 这篇文章的工作是基于t-rex1的工作继续做的&#xff0c;核心亮点&#xff1a; 是支持图片/文本两种模态的prompt进行输入&#xff0c;甚至进一步利用两…

CCF-CSP认证考试 202303-5 施肥 35/60/75/100分题解

更多 CSP 认证考试题目题解可以前往&#xff1a;CSP-CCF 认证考试真题题解 原题链接&#xff1a; 202303-5 施肥 时间限制&#xff1a; 2.0s 内存限制&#xff1a; 1.0GB 问题描述 春天到了&#xff0c;西西艾弗岛上的 n n n 块田地需要施肥了。 n n n 块田地编号为 1 , 2…

基于Google云原生工程师的kubernetes最佳实践(二)

目录 二、应用部署篇 为deployment打上丰富的label,以便selecting 使用sidecar容器部署agent、proxy等组件 使用init container处理依赖关系,而不要用sidecar 镜像tag使用版本号,不要用latest或空tag 为pod设置readiness和liveness探针 不要给所有服务都使用LoadBalance…

【微服务】以模块化单体架构开发微服务应用

目录 推荐超级课程: Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战我们知道,起初,单体应用有显著的优势:它们更容易开发和部署。从开发人员的角度来看,这种简单性是有益的。一切都是集中的,可以快速更新任何部分的业务逻辑并立即看到结果。这种开…

竞赛 python opencv 深度学习 指纹识别算法实现

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python opencv 深度学习 指纹识别算法实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;4分创新点&#xff1a;4分 该项目较为新颖…

ETL数据倾斜与资源优化

1.数据倾斜实例 数据倾斜在MapReduce编程模型中比较常见&#xff0c;由于key值分布不均&#xff0c;大量的相同key被存储分配到一个分区里&#xff0c;出现只有少量的机器在计算&#xff0c;其他机器等待的情况。主要分为JOIN数据倾斜和GROUP BY数据倾斜。 1.1GROUP BY数据倾…