Skip to content

Commit

Permalink
improve report
Browse files Browse the repository at this point in the history
  • Loading branch information
AyiStar committed May 30, 2024
1 parent 4c0a33f commit c3a009a
Showing 1 changed file with 29 additions and 22 deletions.
51 changes: 29 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
## 摘要

llama.cpp是一个开源的大语言模型(LLM)推理程序,支持包括Meta LLaMA等众多知名模型。在本项目中,我们将llama.cpp移植至龙芯处理器3A6000,并进行软硬件协同优化,以加速模型的CPU推理速度,使得以LLaMA3为代表的流行的大语言模型能够以可接受的速度运行于龙芯平台。截至本阶段,我们优化的计算性能,在项目的标准benchmark程序上,相较于开源社区中已有的相关工作,达到50%的提升,并能以流畅的用户体验进行13B级别的大语言模型推理。
* **项目目标**:将llama.cpp移植至龙芯处理器3A6000,并进行软硬件协同优化,加速模型的CPU推理速度,使得以Meta LLaMA为代表的流行的大语言模型能够以可接受的速度运行于龙芯平台;
* **完成情况**:本项目的规划和进展情况可见[dev.md](dev.md)。截至本阶段,在项目的标准benchmark程序上,相较于开源社区的[最新相关工作](https://github.com/ggerganov/llama.cpp/pull/6454),达到50%以上的GEMM FLOPS和模型prompt evluation吞吐量提升,并能以流畅的用户体验进行13B参数量的大语言模型推理;
* **主要创新**:定位和分析了大语言模型推理的主要性能瓶颈;针对龙芯平台进行了**SIMD****Cache**两个方向的计算优化;同时支持**浮点**参数和**量化**参数的运算加速;在3A6000处理器上进行了正确性和性能的标准测试。

本技术报告是对本项目的阶段性总结,也希望为后续工作及相关其他工作提供一些启发,具体包含以下5个章节
本技术报告是对本项目的阶段性总结,也希望为后续工作及相关其他工作提供一些启发,具体包含以下章节
1. 关于 llama.cpp 的背景介绍;
2. 针对龙芯平台的移植工作介绍;
3. 针对龙芯平台的软硬件协同优化工作介绍;
Expand All @@ -22,14 +24,14 @@ llama.cpp是一个开源的大语言模型(LLM)推理程序,支持包括Me
## 1. llama.cpp 背景介绍

### 1.1 什么是llama.cpp
llama.cpp是一个开源的大语言模型(Large Language Model, LLM)推理程序。所谓推理是指载入训练好的模型参数并运行模型,得到输出。LLM巨大的参数量,给推理过程的计算速度和内存占用都带来挑战。llama.cpp所解决的核心问题,就是在用户级设备,尤其是CPU上,进行高效的LLM推理。其解决该问题的主要手段包括:
llama.cpp是一个开源的大语言模型(Large Language Model, LLM)推理程序,支持包括Meta LLaMA等众多知名模型。所谓推理是指载入训练好的模型参数并运行模型,得到输出。LLM巨大的参数量,给推理过程的计算速度和内存占用都带来挑战。llama.cpp所解决的核心问题,就是在用户级设备,尤其是CPU上,进行高效的LLM推理。其解决该问题的主要手段包括:
1. 基于纯C/C++,无GC,面向底层,充分利用硬件特性,相比Python等语言天然具有性能优势;
2. 引入模型量化技术,显著减小内存占用,也间接提升运算性能。

针对以上两方面,我们分别进行简要介绍。

### 1.2 GGML
整个llama.cpp项目可以分为两部分:底层的张量库GGML(C语言),和应用层的模型推理代码(C++语言)。严格来说,GGML是一个独立的项目(https://github.com/ggerganov/ggml),但在实际开发中,GGML被完整包含在llama.cpp项目中(工程目录下的ggml*文件)一起开发,并反馈合并给上游的原仓库。
整个llama.cpp项目可以分为两部分:底层的张量库GGML(C语言),和应用层的模型推理代码(C++语言)。严格来说,GGML是一个[独立的项目](https://github.com/ggerganov/ggml),但在实际开发中,GGML被完整包含在llama.cpp项目中(工程目录下的ggml*文件)一起开发,并反馈合并给上游的原仓库。
GGML是一个纯C语言的张量库,类似PyTorch,包含以下功能:
1. 张量构建:多维数组及相关基本操作(如拷贝、赋值等),相当于PyTorch中的tensor;
2. 算子实现:加法、矩阵乘法等张量算子,包含在各平台的优化;
Expand Down Expand Up @@ -226,7 +228,7 @@ LA_INLINE vreg_t mul_sum_us8_pairs_float(const ivreg_t ax, const ivreg_t sy) {
} // namespace simd
```
其中部分代码借鉴了龙芯团队的相关工作(https://github.com/ggerganov/llama.cpp/pull/6454)。巧合的是,该工作出现在团队成员正在学习LASX指令集的过程中。事实证明,龙芯团队对于LASX的运用比我们要精到得多,我们学到技巧的同时,也省去了大量的工作量,在此也十分感谢张福新老师及时将相关工作进展同步于我们。在此工作的基础上,还我们进行了后续深入的优化(见3.4)。
其中部分代码借鉴了龙芯团队的[相关工作](https://github.com/ggerganov/llama.cpp/pull/6454)。巧合的是,该工作出现在团队成员正在学习LASX指令集的过程中。事实证明,龙芯团队对于LASX的运用比我们要精到得多,我们学到技巧的同时,也省去了大量的工作量,在此也十分感谢张福新老师及时将相关工作进展同步于我们。在此工作的基础上,还我们进行了后续深入的优化(见3.4)。
在实现中,我们还针对AVX2实现了同样的接口,因为其具有和LASX一样的256位向量寄存器,方便在其他平台同步开发测试。
Expand Down Expand Up @@ -589,9 +591,10 @@ LA_INLINE void gemm_block_kernel(const block_q4_1 *a, const block_q8_1 *b, float

### 4.1 工程目录结构
本项目的总体目录结构如下所示:
- `llama.cpp-b2430/`:Tag为 `b2430` 的 llama.cpp 的原始代码,是本项目开始时的最新release版本。
- `llama.cpp-b2430/`:Tag为 `b2430` 的 llama.cpp 的原始代码,是本项目开始时的最新release版本。
- `src/`:这是我们放置自己的优化代码的地方,即 `loongarch_matmul.[cpp|h]`
- `test/`:Benchmark测试代码,修改自 `llama.cpp-b2430/examples/benchmark/benchmark-matmult.cpp`。这意味着性能测量与社区先前报告的结果完全可比。
- `model_weights/`:存放模型参数文件。由于参数文件过大,我们没有直接将文件上传至代码仓库,而是在此目录下提供了下载文件的Python脚本。

### 4.2 工程实现概览
在开发过程中,我们尽量保持plug-in的原则,在原项目目录(`llama.cpp-b2430/`)内只对构建系统(Makefile)和一些包含条件编译的代码(用于插入我们的工作)进行必要的更改,大部分真正的开发工作都在 `src/` 目录中进行,其中声明的两个函数 `lamm_can_mul_mat()``lamm_mul_mat()` 被插入至 `llama.cpp-b2430/ggml.c` 中的GEMM执行调度函数 `ggml_compute_forward_mul_mat()` 来达到优化的目的。
Expand Down Expand Up @@ -651,38 +654,42 @@ make clean && make main LAMM_OPT_LEVEL=[0|1|2|3]

#### 4.4.1 矩阵乘法测试结果

| GEMM (gFLOPS) | F32 (t=1) | F32 (t=2) | F32 (t=4) | Q4_1 (t=1) | Q4_1 (t=2) | Q4_1 (t=4) |
| GEMM Benchmark | F32 (t=1) | F32 (t=2) | F32 (t=4) | Q4_1 (t=1) | Q4_1 (t=2) | Q4_1 (t=4) |
| ------------------------ | ---------- | ---------- | ---------- | ----------- | ----------- | ----------- |
| 直接移植 | 1.67 | 3.34 | 6.67 | 4.91 | 9.77 | 18.96 |
| SIMD优化 | 12.89 | 24.71 | 44.11 | 23.34 | 46.17 | 87.84 |
| SIMD+Cache优化 | **59.34** | **85.66** | **128.46** | **35.32** | **70.00** | **112.76** |
| 直接移植性能(gFLOPS) | 1.67 | 3.34 | 6.67 | 4.91 | 9.77 | 18.96 |
| SIMD优化(gFLOPS) | 12.89 | 24.71 | 44.11 | 23.34 | 46.17 | 87.84 |
| SIMD+Cache优化(gFLOPS) | **59.34** | **85.66** | **128.46** | **35.32** | **70.00** | **112.76** |
| 加速比 | 35.53/4.60 | 25.65/3.47 | 19.26/2.91 | 7.19/1.51 | 7.16/1.52 | 5.94/1.28 |

实验结果表明,本团队所作优化,在llama.cpp中矩阵乘法计算上实现的加速,相比直接移植以及龙芯团队做的SIMD优化,都具有明显优势
实验结果表明,本团队所作优化,在llama.cpp中矩阵乘法计算上可实现可观的加速


#### 4.4.2 模型推理测试结果

| Meta-LLaMA-2-7B (Tokens/Sec) | Q4_1 prompt evaluation (t=1)| Q4_1 text generation (t=1)| Q4_1 prompt evaluation (t=4)| Q4_1 text generation (t=4)|
| Meta-LLaMA-2-7B Inference | Q4_1 prompt evaluation (t=1)| Q4_1 text generation (t=1)| Q4_1 prompt evaluation (t=4)| Q4_1 text generation (t=4)|
| ------------------------ | --------------------- | ------------------- | ---------------------- | -------------------- |
| 直接移植 | 0.37 | 0.36 | 1.44 | 1.37 |
| SIMD优化 | 1.48 | 1.29 | 5.62 | 3.54 |
| SIMD+Cache优化 | **2.14** | **1.47** | **8.32** | **3.79** |
| 直接移植性能(Tokens/Sec) | 0.37 | 0.36 | 1.44 | 1.37 |
| SIMD优化(Tokens/Sec) | 1.48 | 1.29 | 5.62 | 3.54 |
| SIMD+Cache优化(Tokens/Sec) | **2.14** | **1.47** | **8.32** | **3.79** |
| 加速比 | 5.78/1.45 | 4.08/1.14 | 5.78/1.48 | 2.77/1.07 |


| Meta-LLaMA2-13B (Tokens/Sec) | Q4_1 prompt evaluation (t=1)| Q4_1 text generation (t=1)| Q4_1 prompt evaluation (t=4)| Q4_1 text generation (t=4)|
| Meta-LLaMA2-13B Inference | Q4_1 prompt evaluation (t=1)| Q4_1 text generation (t=1)| Q4_1 prompt evaluation (t=4)| Q4_1 text generation (t=4)|
| ------------------------ | --------------------- | ------------------- | ---------------------- | -------------------- |
| 直接移植 | 0.19 | 0.19 | 0.74 | 0.71 |
| SIMD优化 | 0.77 | 0.69 | 2.99 | 2.02 |
| SIMD+Cache优化 | **1.16** | **0.74** | **4.50** | **2.16** |

| 直接移植(Tokens/Sec) | 0.19 | 0.19 | 0.74 | 0.71 |
| SIMD优化(Tokens/Sec) | 0.77 | 0.69 | 2.99 | 2.02 |
| SIMD+Cache优化(Tokens/Sec) | **1.16** | **0.74** | **4.50** | **2.16** |
| 加速比 | 6.11/1.51 | 3.89/1.07 | 6.08/1.51 | 3.04/1.07 |

实验结果表明,本团队所作优化,在模型推理的吞吐量上可实现可观的加速,其中prompt evaluation阶段的加速效果比text generation阶段更为明显,这是因为相对来说,前者比后者更计算密集,后者更受制于内存访问。

## 5. 未来工作与收获总结
由于比赛时间和成员精力有限,本阶段所完成的工作距离理想目标还甚有欠缺,无论比赛是否继续,希望能够在未来补足,具体包括:
1. 对模型推理的进一步优化,例如Cache优化中分块参数(块形状)和分块策略的调优;
2. 对所有量化方式的优化的全面支持(目前只考虑了Q4_1);
3. 对大量模型在龙芯平台的可用性的全面评测(目前只测评了Meta LLaMA);
4. 将代码整理成PR并入社区。
3. 对大量模型在龙芯平台的可用性的全面评测(目前只测评了Meta LLaMA 2);
4. 针对模型推理过程的text generation阶段做进一步优化(目前prompt evaluation阶段效果更显著);
5. 将代码整理成PR并入社区。

本次比赛对我们来说是一次宝贵的经历,让我们有机会真正接触一项开源项目并进行工程实操。
这其中包括不少挑战,例如需要理解并改进一个2M LOC量级的实际工程项目,需要快速理解和掌握一个新的指令集架构,需要对较为陌生的性能优化领域展开调研,等等。在克服这些挑战的过程中也收获了很多,一言蔽之是增进了系统能力,无论是阅读代码、查找资料、还是阅读手册,我们在这个过程中开始领悟如何在一个复杂的系统中开展工作。
Expand Down

0 comments on commit c3a009a

Please sign in to comment.