1.BitMapåçä¸å®ç°
2.Catlike Coding Custom SRP学习之旅——11Post Processing
3.TensorRT-LLM(持续更新)
4.布隆过滤器(Bloom Filter)详解
5.手把手教你微调百亿大模型:基于Firefly微调Qwen1.5-14b
6.深入源码解析LevelDB
BitMapåçä¸å®ç°
æ¯è¾ç»å ¸çé®é¢æ¯ï¼ å¨åªè½å¤ä½¿ç¨2Gçå åä¸ï¼å¦ä½å®æ以ä¸æä½ï¼â ï¼å¯¹äº¿ä¸ªä¸éå¤çæ´æ°è¿è¡æåºã
â¡ï¼æ¾åºäº¿ä¸ªæ°åä¸éå¤çæ°åã
æ 论æ¯æåºè¿æ¯æ¾éå¤çæ°åé½éè¦å°è¿äº¿ä¸ªæ°åå å ¥å°å åä¸å¨å»è¿è¡æä½ï¼å¾ææ¾ï¼é¢ç®ç»åºç2Gå åéå¶è¯´æäºå¨è¿æ ·çåºæ¯ä¸æ¯ä¸è½å¤å°æææ°é½å å ¥å°å åä¸ç
* 4/ï¼* * ï¼ = 3.G
é£ä¹è¿æ¶åå°±éè¦ç¨å° BitMapç»æäº
bitMap使ç¨ä¸ä¸ªbit为0/1ä½ä¸ºmapçvalueæ¥æ è®°ä¸ä¸ªæ°åæ¯å¦åå¨,èmapçkeyå¼æ£æ¯è¿ä¸ªæ°åæ¬èº«ã
ç¸æ¯äºä¸è¬çæ°æ®ç»æéè¦ç¨4个byteå»åå¨æ°å¼æ¬èº«ï¼ç¸å½äºæ¯èçäº 4*8ï¼1 = åçå å空é´
bitMapä¸ä¸å®è¦ç¨bitæ°ç»,å¯ä»¥ä½¿ç¨ int,longçççåºæ¬æ°æ®ç±»åå®ç°ï¼å ä¸ºå ¶å®è´¨é½æ¯å¨bitä½ä¸åæ°æ®ï¼ç¨åªç§ç±»ååªæ¯å³å®äºæç»å®ç°åºæ¥çBitMapçå ç½®æ°ç»ä¸å个å ç´ åæ¾æ°æ®çå¤å°
ä¾å¦ï¼javaä¸çBitSet使ç¨Longæ°ç»
BitMapçå®ç°å½ç¶å°ä¸äºä½è¿ç®ï¼å æ¥æç¡®å 个常è§ä½è¿ç®ï¼è¿æ¯å®ç°BitMapçåºç¡ï¼
set(bitIndex): æ·»å æä½
1 .ç¡®å®è¯¥æ°å¤äºæ°ç»ä¸çåªä¸ªå ç´ çä½ä¸
int wordIndex = bitIndex >> 5;
å 为æç¨çæ¯int[]å®ç°ï¼æ以è¿éå³ç§» 5 ä½ï¼2^5 = ï¼
2 .ç¡®å®ç¸å¯¹äºè¯¥å ç´ ä¸çä½ç½®å移
int bitPosition = bitIndex & ((1 << 5) - 1);
è¿éç¸å½äºæ¯ bitIndex % ï¼1<<5ï¼çå模è¿ç®ï¼å 为å½å模è¿ç®çé¤æ°æ¯2ç次å¹ï¼æ以å¯ä»¥ä½¿ç¨ä»¥ä¸çä½è¿ç®æ¥è®¡ç®ï¼æåæçï¼å¯¹æ¯HashMapç容é为ä»ä¹æ»æ¯2çå¹æ¬¡æ¹çé®é¢ï¼HashMapæ±ä¸æ æ¶ä¹æ¯ä½¿ç¨ hash&(n-1)ï¼
tips: ä½è¿ç®çä¼å 级æ¯ä½äº+,-çççï¼æ以è¦å ä¸æ¬å·,é²æ¢åçä¸å¯æè¿°çé误
3 .å°è¯¥ä½ç½®1
bits[wordIndex] |= 1 << bitPosition;
ç¸å½äºæ¯å°æå®ä½ç½®å¤çbitå¼ç½®1ï¼å ¶ä»ä½ç½®ä¿æä¸åï¼ä¹å°±æ¯å°ä»¥è¿ä¸ªbitIndex为keyçä½ç½®ä¸º1
tips: è¿éæ¯åèäºç½ä¸çåä½å¤§ä½¬çæç« ,åä½ + æä½æï¼å对æ¯äºä¸BitSetçæºç ï¼
words[wordIndex] |= (1L << bitIndex);
没æåä½æä½ï¼ç´æ¥|ï¼è¿ä¸¤ä¸ªä¸æ ·åï¼çæ¡å½ç¶æ¯ä¸æ ·ç
举个æ åï¼
1 << == 1<<
1L << ==1L<<
å³å¯¹äºintålongåæ°æ®ï¼ç´æ¥å·¦ç§»å ¶ä½æ°ç¸å½äºæ¯é带äºå¯¹å ¶çå模æä½
æ»ç»ï¼ä½¿ç¨Bit-mapçææ³ï¼æ们å¯ä»¥å°åå¨ç©ºé´è¿è¡å缩ï¼èä¸å¯ä»¥å¯¹æ°åè¿è¡å¿«éæåºãå»éåæ¥è¯¢çæä½ã
Bloom Fliteræ¯Bit-mapææ³çä¸ç§æ©å±ï¼å®å¯ä»¥å¨å 许ä½é误ççåºæ¯ä¸ï¼å¤§å¤§å°è¿è¡ç©ºé´å缩ï¼æ¯ä¸ç§æ¿é误çæ¢å空é´çæ°æ®ç»æ
å½ä¸ä¸ªå ç´ å å ¥å¸éè¿æ»¤å¨ä¸çæ¶åï¼ä¼è¿è¡åªäºæä½ï¼
å½æ们éè¦å¤æä¸ä¸ªå ç´ æ¯å¦åå¨äºå¸éè¿æ»¤å¨çæ¶åï¼ä¼è¿è¡åªäºæä½ï¼
ç¶åï¼ä¸å®ä¼åºç°è¿æ ·ä¸ç§æ åµï¼ä¸åçå符串å¯è½åå¸åºæ¥çä½ç½®ç¸åï¼å¯ä»¥éå½å¢å ä½æ°ç»å¤§å°æè è°æ´æ们çåå¸å½æ°æ¥éä½æ¦çï¼,å æ¤ï¼å¸éè¿æ»¤å¨å¯è½ä¼åå¨è¯¯å¤çæ åµ
æ»ç»æ¥è¯´å°±æ¯ï¼ å¸éè¿æ»¤å¨è¯´æ个å ç´ åå¨ï¼å°æ¦çä¼è¯¯å¤ãå¸éè¿æ»¤å¨è¯´æ个å ç´ ä¸å¨ï¼é£ä¹è¿ä¸ªå ç´ ä¸å®ä¸å¨ã
Bloom Filterçåºç¨: 常ç¨äºè§£å³ç¼åç©¿éçåºæ¯ã
Catlike Coding Custom SRP学习之旅——Post Processing
来到了后处理环节,这是渲染管线中关键的一环。后处理技术能够显著提升画面效果,比如色调映射、Bloom、抗锯齿等,三货币源码都能在后处理中实现。除了改善整体画面效果,后处理还能用于实现描边等美术效果。本文将主要介绍后处理堆栈和Bloom效果等内容。
考虑到篇幅和工作量,本文将从第4章节后半部分开始,以及未来的章节,主要提炼原教程的内容,尽量减少篇幅和实际代码。在我的Github工程中,包含了对源代码的详细注释,需要深入了解代码细节的读者可以查看我的Github工程。对于文章中的错误,欢迎读者批评指正。
以下是原教程链接和我的Github工程:
CatlikeCoding-SRP-Tutorial
我的Github工程
1. 后处理堆栈(Post-FX Stack)
FX,全称是Special Effects,即特殊效果,也称为VFX(Visual Special Effects),即视觉特效。参考维基百科,视觉效果(Visual effects,简称VFX)是在**制作中,在真人动作镜头之外创造或操纵图像的过程。游戏很多技术都会沿用影视技术上的一些技术,比如在色调映射时,可以采用ACES(**色调映射)等。关于Special Effects为什么叫FX,而不是SE,网上似乎只是因为FX谐音Effects,让人不知道从哪吐槽。
通常来说,游戏源码钩子因为后处理会包含很多不同的效果,如色调映射、Bloom、抗锯齿等等,因此后处理在渲染管线中的结构往往是一个堆栈式的结构(URP中也是如此,使用了Post Process Volume)。因此,在本篇中,我们将搭建这样一个堆栈结构,并实现Bloom效果。
1.1 配置资源(Settings Asset)
首先,我们定义PostFXSettings资源,即Scriptable Object,将其作为渲染管线的一项可配置属性,这样便于我们配置不同的后处理堆栈,并可以方便地切换。
1.2 栈对象(Stack Object)
类似于Light和Shadows,我们同样使用一个类来存储包括Camera、ScriptableRenderContext、PostFXSettings,并在其中执行后处理堆栈。
1.3 使用堆栈(Using the Stack)
在进行后处理前,我们首先需要获取当前摄像机画面的标识RenderTargetIdentifier,RenderTargetIdentifier用于标识CommandBuffer的RenderTexture。在这里,我们使用一个简单的int来标识sourceRT。
对于一个后处理效果而言,其实现过程说来很简单,传入一个矩形Mesh(其纹理即当前画面),使用一个Shader渲染该矩形Mesh,将其覆盖回Camera的RT上,我们通过Blit函数来实现该功能。
1.4 强制清除(Forced Clearing)
因为我们将摄像机渲染到了中间RT上,我们虽然会在每帧结束时释放该RT空间,但是基于Unity自身对RT的管理策略,其并不会真正地清除该RT,aop源码详解因此我们在下一帧时,该RT中会留存上一帧的渲染结果,导致了每一帧画面都是在前一帧的结果之上绘制的。
1.5 Gizmos
我们还需要在后处理前后绘制不同的Gizmos部分,这部分略~
1.6 自定义绘制(Custom Drawing)
使用Blit方法绘制后处理,实际上会绘制一个矩形,也就是2个三角面,即6个顶点。但我们完全可以只用一个三角面来绘制整个画面,因此我们使用自定义的绘制函数代替Blit。
1.7 屏蔽部分FX(Don't Always Apply FX)
目前,我们对于所有摄像机都执行了后处理。但是,我们希望只对Game视图和Scene视图摄像机进行后处理,并对不同Scene视图提供单独的开关控制。很简单,通过判断摄像机类型来屏蔽。
1.8 复制(Copying)
接下来,完善下Copy Pass。我们在片元着色器中,对原画面进行采样,并且由于其不存在Mip,我们可以指定mip等级0进行采样,避免一部分性能消耗。
2. 辉光(Bloom)
目前,我们已经实现了后处理堆栈的框架,接下来实现一个Bloom效果。Bloom效果应该非常常见,也是经常被用于美化画面,其主要作用就是让画面亮的区域更亮。
2.1 Bloom金字塔(Bloom Pyramid)
为了实现Bloom效果,我们需要提取画面中亮的像素,并让这些亮的像素影响周围暗的像素。因此,需要首先实现RT的降采样。通过降采样,网站源码sql我们可以很轻易地实现模糊功能。
2.2 配置辉光(Configurable Bloom)
通常来说,我们并不需要降采样到很小的尺寸,因此我们将最大降采样迭代次数和最小尺寸作为可配置选项。
2.3 高斯滤波(Gaussian Filtering)
目前,我们使用双线性滤波来实现降采样,这样的结果会有很多颗粒感,因此我们可以使用高斯滤波,并且使用更大的高斯核函数,通过9x9的高斯滤波加上双线性采样,实现x的模糊效果。
2.4 叠加模糊(Additive Blurring)
对于Bloom的增亮,我们直接将每次降采样后的Pyramid一步步叠加到原RT上,即直接让两张不同尺寸的以相同尺寸采样,叠加颜色,这一步也叫上采样。
2.5 双三次上采样(Bicubic Upsampling)
在上采样过程中,我们使用了双线性采样,这样可能依然会导致块状的模糊效果,因此我们可以增加双三次采样Bicubic Sampling的可选项,以此提供更高质量的上采样。
2.6 半分辨率(Half Resolution)
由于Bloom会渲染多张Pyramid,因此其消耗是比较大的,其实我们完全没必要从初始分辨率开始降采样,从一半的分辨率开始采样的效果也很好。
2.7 阈值(Threshold)
目前,我们对整个RT的每个像素都进行了增亮,这让这个画面看起来过曝了一般,但其实Bloom只需要对亮的区域增亮,本身暗的地方就不需要增亮了。
2.8 强度(Intensity)
最后,提供一个Intensity选项,控制Bloom的整体强度。
结束语
大功告成,我们在渲染管线中增加了后处理堆栈,以及实现了一个Bloom效果,装机模拟源码其实在做完这篇之后,我觉得这个渲染管线才算基本上达成了大部分需要的功能,也算是一个里程碑吧。
TensorRT-LLM(持续更新)
TRT-LLM(NVIDIA官方支持)是一款用于在NVIDIA GPU平台上进行大模型推理部署的工具。
其整体流程是将LLM构建为engine模型,支持多种大模型,如单机单卡、单机多卡(NCCL)、多机多卡,以及量化(8/4bit)等功能。
TRT-LLM的runtime支持chat和stream两种模式,并支持python和cpp(可以直接使用cpp,也可以使用cpp的bybind接口)两种模式的runtime。
构建离线模型可以通过example下的各个模型的build.py实现,而运行模型则可通过example下的run.py进行。
TRT-LLM默认支持kv-cache,支持PagedAttention,支持flashattention,支持MHA/MQA/GQA等。
在cpp下,TRT-LLM实现了许多llm场景下的高性能cuda kernel,并基于TensorRT的plugin机制,支持各种算子调用。
与hugging face transformers(HF)相比,TRT-LLM在性能上提升2~3倍左右。
TRT-LLM易用性很强,可能与其LLM模型结构比较固定有关。
TRT-LLM的weight_only模式仅仅压缩模型体积,计算时依旧是dequant到input.dtype做计算。
TRT-LLM的量化:W4A(表示weight为4bit,输入数据即activation为fp)。
LLM模型推理,性能损耗大头在data 搬移,即memory bound,compute bound占比较少。
TRT-LLM运行时内存可以通过一下参数调整,使用适合当前业务模型的参数即可。
TRT-LLM对于Batch Manager提供了.a文件,用于支持in-flight batching of requests,来较小队列中的数据排队时间,提高GPU利用率。
当前支持(0.7.1)的模型如下:
tensorrt llm需要进行源码编译安装,官方提供的方式为通过docker进行安装。
docker方式编译可以参考官方文档,此处做进一步说明。使用docker方式,会将依赖的各种编译工具和sdk都下载好,后面会详细分析一下docker的编译过程。
编译有2种包,一种是仅包含cpp的代码包,一种是cpp+python的wheel包。
docker的整个编译过程从如下命令开始:调用make,makefile在 docker/Makefile 下面,里面主要是调用了docker命令来进行构建。
后续非docker方式编译llm,也是基于上述docker编译。
一些小技巧:在编译llm过程中,会通过pip install一些python包,llm脚本中默认使用了NVIDIA的源,我们可以替换为国内的源,速度快一些。
整个过程就是将docker file中的过程拆解出来,直接执行,不通过docker来执行。
编译好的文件位于:build/tensorrt_llm-0.5.0-py3-none-any.whl。
默认编译选项下的一些编译配置信息如下:
以官方样例bloom为例:bloom example
核心在于:编译时使用的环境信息和运行时的环境信息要一致,如:python版本,cuda/cudnn/nccl/tensorrt等。
环境安装后以后,参考官方bloom样例,进行模型下载,样例执行即可。
最终生成的engine模型:
以chatglm2-6b模型为基础,进行lora微调后,对模型进行参数合并后,可以使用tensortrt-llm的example进行部署,合并后的模型的推理结果和合并前的模型的推理结果一致。
lora的源码不在赘述,主要看一下lora模型参数是如何合并到base model中的:
lora模型如下:
base模型如下:
模型构建是指将python模型构建为tensort的engine格式的模型。
整体流程如下:
整体流程可以总结为:
可以看出,原理上和模型转换并没有区别,只是实现方式有差异而已。
pytorch模型参数如何加载在tensortrt-llm中?关于量化参数加载
1. 先提取fp格式的参数
2. 调用cpp的实现进行参数量化
整体而言,模型参数加载的关键在于:算子weight一一对应,拷贝复制。
每种模型,都需要搭建和pytorch严格一致的模型架构,并将算子weight严格对应的加载到tensortrt-llm模型中
即:关键点在于:熟悉原始pytorch模型结构和参数保存方式,熟悉tensorrt-llm的模型结构和参数设定方法。
模型构建成功后,有两个文件:config.json文件推理时会用到,主要内容如下:模型参数信息和plugin信息。
在模型构建好后,就可以做模型推理,推理流程如下:
TRT-LLM Python Runtime分析
1. load_tokenizer
2. parse_input
基于 tokenizer 对输入的text做分词,得到分词的id
3. runner选择&模型加载
4.推理
5. 内存管理
TRT-layer实现举例
(1)对tensorrt的接口调用:以cast算子为例:functional.py是对TensorRT python API接口的调用
调用tensorrt接口完成一次推理计算
(2)TRT-LLM python侧对cpp侧的调用
调到cpp侧后,就会调用cpp侧的cuda kernel
trtllm更新快,用了一些高版本的python特性,新的trtllm版本在python3.8上,不一定能跑起来
布隆过滤器(Bloom Filter)详解
布隆过滤器(Bloom Filter),一种年由布隆提出的高效数据结构,用于判断元素是否在集合中。其优势在于空间效率和查询速度,但存在误判率和删除难题。布隆过滤器由长二进制数组和多个哈希函数构成,新元素映射位置置1。判断时,若所有映射位置均为1,则认为在集合;有0则判断不在。尽管可能产生误报,但通过位数组节省空间,比如MB内存可处理亿长度数组。常用MurmurHash哈希算法,如mmh3库,它的随机分布特性使其在Redis等系统中广泛使用。
在Scrapy-Redis中,可以将布隆过滤器与redis的bitmap结合,设置位长度为2的次方,通过setbit和getbit操作实现。将自定义的bloomfilter.py文件添加到scrapy_redis源码目录,并在dupefilter.py中进行相应修改。需要注意的是,爬虫结束后可通过redis_conn.delete(key名称)释放空间。使用时,只需将scrapy_redis替换到项目中,遵循常规的Scrapy-Redis设置即可。
手把手教你微调百亿大模型:基于Firefly微调Qwen1.5-b
本文旨在引导新手通过使用Firefly项目微调Qwen1.5-b模型,学习大模型的微调流程。此教程不仅适用于微调llama、ziya、bloom等模型,同时Firefly项目正在逐步兼容更多开源大模型,如InternLM、CPM-bee、ChatGLM2等。此教程是大模型训练的步步指引,即使你是训练大模型的新手,也能通过本文快速在单显卡上训练出自己的大模型。 访问Firefly项目链接:ewRedisBitSet(store*redis.Client,keystring,bitsuint)*redisBitSet{ return&redisBitSet{ store:store,key:key,bits:bits,}}到这里位数组操作就全部实现了,接下来看下如何通过 k 个散列函数计算出 k 个位点
k 次散列计算出 k 个位点
//k次散列计算出k个offsetfunc(f*Filter)getLocations(data[]byte)[]uint{ //创建指定容量的切片locations:=make([]uint,maps)//maps表示k值,作者定义为了常量:fori:=uint(0);i<maps;i++{ //哈希计算,使用的是"MurmurHash3"算法,并每次追加一个固定的i字节进行计算hashValue:=hash.Hash(append(data,byte(i)))//取下标offsetlocations[i]=uint(hashValue%uint(f.bits))}returnlocations}插入与查询
添加与查询实现就非常简单了,组合一下上面的函数就行。
//添加元素func(f*Filter)Add(data[]byte)error{ locations:=f.getLocations(data)returnf.bitSet.set(locations)}//检查是否存在func(f*Filter)Exists(data[]byte)(bool,error){ locations:=f.getLocations(data)isSet,err:=f.bitSet.check(locations)iferr!=nil{ returnfalse,err}if!isSet{ returnfalse,nil}returntrue,nil}改进建议整体实现非常简洁高效,那么有没有改进的空间呢?
个人认为还是有的,上面提到过自动计算最优 m 与 k 的数学公式,如果创建参数改为:
预期总数量expectedInsertions
期望误差falseProbability
就更好了,虽然作者注释里特别提到了误差说明,但是实际上作为很多开发者对位数组长度并不敏感,无法直观知道 bits 传多少预期误差会是多少。
//NewcreateaFilter,storeisthebackedredis,keyisthekeyforthebloomfilter,//bitsishowmanybitswillbeused,mapsishowmanyhashesforeachaddition.//bestpractices://elements-meanshowmanyactualelements//whenmaps=,formula:0.7*(bits/maps),bits=*elements,theerrorrateis0.<1e-4//fordetailederrorratetable,see/zeromicro/go-zero欢迎使用 go-zero 并 star 支持我们!
微信交流群关注『微服务实践』公众号并点击 交流群 获取社区群二维码。
自然语言处理大模型BLOOM模型结构源码解析(张量并行版)
BLOOM模型结构解析,采用Megatron-DeepSpeed框架进行训练,张量并行采用1D模式。基于BigScience开源代码仓库,本文将详细介绍张量并行版BLOOM的原理和结构。 单机版BLOOM解析见文章。 模型结构实现依赖mpu模块,推荐系列文章深入理解mpu工具。 Megatron-DeepSpeed张量并行工具代码mpu详解,覆盖并行环境初始化、Collective通信封装、张量并行层实现、测试以及Embedding层、交叉熵实现与测试。 Embedding层:Transformer Embedding层包含Word、Position、TokenType三类,分别将输入映射为稠密向量、注入位置信息、类别信息。通常,位置信息通过ALiBi注入,无需传统Position Embedding,TokenType Embedding为可选项。张量并行版BLOOM Embedding层代码在megatron/model/language_model.py,通过参数控制三类Embedding使用。 激活函数:位于megatron/model/utils.py,BLOOM激活函数采用近似公式实现。 掩码:张量并行版模型用于预训练,采用Causal Mask确保当前token仅见左侧token。掩码实现于megatron/model/fused_softmax.py,将缩放、mask、softmax融合。 ALiBi:位置信息注入机制,通过调整query-key点积中静态偏差实现。8个注意力头使用等比序列m计算斜率,个头则有不同序列。实现于megatron/model/transformer.py。 MLP层:全连接层结构,列并行第一层,行并行第二层,实现于megatron/model/transformer.py。 多头注意力层:基于标准多头注意力添加ALiBi,简化版代码位于megatron/model/transformer.py。 并行Transformer层:对应单机版BlookBlock,实现于megatron/model/transformer.py。 并行Transformer及语言模型:ParallelTransformer类堆叠多个ParallelTransformerLayer,TransformerLanguageModel类在开始添加Embedding层,在末尾添加Pooler,逻辑简单,代码未详述。 相关文章系列覆盖大模型研究、RETRO、MPT、ChatGLM-6B、BLOOM、LoRA、推理工具测试、LaMDA、Chinchilla、GLM-B等。