# llm **Repository Path**: uesoft/llm ## Basic Information - **Project Name**: llm - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-04 - **Last Updated**: 2026-09-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # llm — phi-2 GGUF 推理引擎 ``` read(Token) → transform(Token→Token) → write(Token) ``` 纯 C11 实现的 phi-2 推理引擎(无第三方依赖,仅 libm + pthread),自带 GGUF 解析、 K-quant 反量化、BPE 分词器、KV cache + RoPE 的 forward、流式命令行。 性能:Q4_K/Q5_K/Q6_K 反量化有 AVX2 内核(编译期 `-mavx2` 自动启用,否则回退 标量);`qmatvec` 由 pthread 常驻线程池按输出行切分并行。实测 phi-2.Q4_K_M 在 i5-1334U 上 **722 → 326 ms/token**(`-t 6`),相对最初的标量单线程 **3713 ms/token 提速 11.4x**。 ## 构建 ### WSL / Linux(主路径) ```bash ./mkllm.sh # 核心库 + llm-cli + 单元测试 + llm-server + 冒烟测试 SERVER=0 ./mkllm.sh # 跳过 llm-server SMOKE=0 ./mkllm.sh # 跳过冒烟测试 ``` 或直接用 Makefile: ```bash make -j$(nproc) # build/llm-core.a + build/test_equations + build/llm-cli make cli # 只构建 llm-cli make info # 打印模型信息 make run # 跑一次贪心解码 make chat # 交互模式 make test # 算子单元测试 make verify # 反量化内核一致性 (标量 vs AVX2 逐元素比对) make clean ``` ### Windows / MSVC `llm.2022.sln`(VS18,工具集 v145)打开后生成 `Release|Win32`: | 工程 | 产物 | 说明 | |------|------|------| | `llm.vcxproj` | `build/Release/llm-core.lib` | 核心静态库 | | `llm-cli.vcxproj` | `build/Release/llm-cli.exe` | 命令行(自动引用 llm-core.lib) | `llm.vcproj`(VC2005/VC8)只同步了文件树,用于浏览/编辑; 本机 VC8 缺 `mspdb80.dll`(cl.exe 返回 127),且 VC8 无 ``、不支持 C99 的 for 内声明,**不要用它编译**。 ## llm-cli 用法 ``` llm-cli -m ../models/phi-2.Q4_K_M.gguf -p "The capital of France is" -n 64 --temp 0 llm-cli -m model.gguf -i # 交互,保留上下文(/reset 清空, /exit 退出) llm-cli -m model.gguf -i --chat --temp 0 # 交互 + Q/A 模板(base 权重才会"答题") llm-cli -m model.gguf --info # 只打印模型信息 llm-cli -m model.gguf --tok "德国首都是" # 分词探针(含 round-trip 校验) llm-cli -m model.gguf -p "..." --profile # 打印反量化/点积/注意力的耗时分解 echo "Once upon a time" | llm-cli -m model.gguf --stdin -n 128 ``` | 选项 | 默认 | 说明 | |------|------|------| | `-m, --model PATH` | `../models/phi-2.Q4_K_M.gguf` | GGUF 模型 | | `-p, --prompt TEXT` | — | 提示词 | | `-n, --n-predict N` | 128 | 最多生成 token 数 | | `--temp F` | 0.7 | 温度,0 = 贪心 | | `--top-k N` | 40 | top-k | | `--top-p F` | 0.95 | nucleus | | `-c, --ctx N` | 模型值 | 上下文长度 | | `-s, --seed N` | 12345 | xorshift 种子 | | `--kv-mb N` | 0(不限制) | KV cache 内存上限 | | `-t, --threads N` | 0 = 自动 | matvec 线程数(见下方"线程数怎么选") | | `-i, --interactive` | — | 交互模式 | | `--chat` | 关 | `-i` 下把每行包成 `Q: ...\nA:` | | `--profile` | 关 | 打印每轮耗时分解 | | `--tok TEXT` | — | 只做分词探针 | | `--info` | — | 只打印模型信息 | | `--stdin` | — | 从 stdin 读提示词 | ### 线程数怎么选 默认值由 `cli_default_threads()` 探测:**只数支持超线程的核心(性能核)**。 依据是大小核 CPU 上 E-core 单核效率只有大核约一半,拉进来会拖住 barrier。 探测不到就退回 `nproc`。 i5-1334U(2 P-core×2T + 8 E-core)实测(`-p "Once upon a time" -n 24 --temp 0`, 取三轮中位数): | `-t` | 1 | 2 | 4 | 6 | 8 | 12 | |------|---|---|---|---|---|----| | ms/token | 722 | 407 | 363 | **326** | 336 | 342 | 即 6 线程后收益饱和。**输出与线程数无关**(逐字节一致,`make` 出来的 二进制可用 `diff` 验证:并行只切分输出行,不改变任何浮点运算顺序)。 ## 源码布局 | 文件 | 职责 | |------|------| | `persist/FileManager.c` | GGUF 解析 + 权重/词表加载 | | `core/quan.c` | K-quant 反量化(Q4_K/Q5_K/Q6_K,对齐 ggml 权威实现;含 AVX2 内核) | | `core/fp16.h` | fp16 → fp32 位域转换 | | `core/equations.c` | matmul / rms_norm / silu / softmax / 采样 | | `core/tokenizer.c` | GPT-2 风格 BPE(byte↔unicode + merges) | | `core/phi2.c` | phi-2 forward + pthread 线程池(并行 FFN + partial RoPE + KV cache) | | `llm-cli.c` | 命令行前端(UTF-8 安全的流式输出) | | `tools/verify_dequant.c` | 反量化 AVX2 vs 标量逐元素一致性校验 | | `mkllm.sh` / `Makefile` | 构建入口 | 细节与已知问题见 `docs/STATUS.md`。