llama2.c中,最想知道的的一个问题是:模型文件(bin)怎么手搓的(c)读取运行起来?延展开来是一下几个问题:
在karpathy大神实现之前,一直认为是大厂的禁区,不可能完成的任务。看过大神micro-grad,nano-gpt等spelled-out系列教程,了解到karpathy就擅长与用基础语言构造toy轮子部件,然后完成一个五脏俱全的toy作品。花了2天的业余时间通读代码,画了结构图,大致形而上学了解些机理,在记忆模糊以及被其他事情拉扯去之前,写下笔记留恋。设计真是漂亮!!
run.c 实现了3个struct结构类,具体可以看代码,图比代码感觉更容易理解。
其中,Config和TransformerWeight结构是通过model.bin二进制文件读取解析出来,二者和在一起是模型结构和权重;RunState是运行时上下文。
这也回答了算子实现的问题,Llama2 LLM除了开始最后的token、pos处理,剩下都是标准化Transformer block的重复。特定系列的模型差别,就是Transformer block大小以及格式化配置的不同,其所用到的算子时有限的。
就是读取tokenizer.bin文件,导出两个lookup类型的对象,然后就是per token process...
argmax和sample用在有无温度参数的处理上。
run.c的主体流程非常传统,“果然应该这么设计。“的感觉,非常正统,设计精巧在于围绕结构结构的设计上。
简单的说: model.py::export --> bin --> run.c::Config TransformerWeight,具体结合下图,看以下代码:
特别要指出的时,权重的保存是按照算子类型(Attension、ffn)、然后是Layer层的顺序进行分组存储;TransfoermerWeight中的变量都是指针指向真正存储权重的空间,这些又是根据先解析出来Config信息申请。这样设计的保证了Config,TransformerWeight结构占用空间大小一致(更模型大小无关)。
没有时间,或者价值不大,进行python、C推理引擎推理的比较;也没有充裕的时间,单步跟踪run.c代码看看数据的流转。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。