ik_llama.cpp 最小示例 llama-simple 深度解析:从零构建文本生成管线
ik_llama.cpp 最小示例 llama-simple 深度解析从零构建文本生成管线【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp本篇文章围绕 ik_llama.cpp 仓库中 examples/simple 目录下的最小示例展开完整剖析llama-simple这个可执行程序它用最少的代码量串联起加载模型 → 分词 → 构建 batch → 解码 → 采样 → 生成文本的完整推理管线。读完本文你将理解 llama.cpp 系 C API 的核心调用顺序、llama_batch的提交机制、贪心采样与 EOG 判断的实现方式并能读懂llama-simple输出的每一条性能指标从而为阅读llama-server、main等更复杂的示例打下基础。llama-simple 是什么llama-simple是 ik_llama.cpp 中刻意保持最小化的示例程序其官方定位在 examples/simple/README.md 中写得非常明确演示使用 llama.cpp 以给定 prompt 生成文本的最小用法demonstrate a minimal usage of llama.cpp for generating text with a given prompt。它与 examples/main 的定位完全不同mainllama-cli是功能完备的交互式 CLI支持对话模板、采样参数微调、语法约束、prompt 缓存等数十个开关llama-simple只做一件事输入 prompt输出续写结果全程只依赖 C API 加少量common辅助函数不涉及任何对话历史、模板渲染或高级采样。因此它非常适合作为理解 llama.cpp 类推理引擎工作流程的第一份源码教材。构建与运行构建方式llama-simple随示例整体一起构建其构建规则见 examples/simple/CMakeLists.txtset(TARGET llama-simple) add_executable(${TARGET} simple.cpp) install(TARGETS ${TARGET} RUNTIME) target_link_libraries(${TARGET} PRIVATE common llama ${CMAKE_THREAD_LIBS_INIT}) target_compile_features(${TARGET} PRIVATE cxx_std_11)要点生成的可执行文件名为llama-simple且会被install安装链接目标是common和llama两个库外加线程库common提供参数解析与批量操作辅助函数llama提供全部推理 C API编译标准为 C11该示例通过 examples/CMakeLists.txt 中的add_subdirectory(simple)被纳入整体构建。因此在仓库根目录执行常规的 CMake 配置与构建后即可在构建目录中得到llama-simple可执行文件。运行命令官方 README 给出的运行命令如下模型路径请替换为你本地的 GGUF 文件./llama-simple -m ./models/llama-7b-v2/ggml-model-f16.gguf -p Hello my name is其中-m指定模型文件GGUF 格式-p指定输入提示词prompt。由于simple.cpp在代码里已经把默认参数预设为params.prompt Hello my name is和params.n_predict 32见下文源码分析所以即使只传-m不传-p程序也会使用这个默认 prompt 续写 32 个 token。运行输出逐行解读README 给出了一个典型运行输出我们逐段解释其含义./llama-simple -m ./models/llama-7b-v2/ggml-model-f16.gguf -p Hello my name is ... main: n_len 32, n_ctx 2048, n_parallel 1, n_kv_req 32 Hello my name is Shawn and Im a 20 year old male from the United States. Im a 20 year old main: decoded 27 tokens in 2.31 s, speed: 11.68 t/s llama_print_timings: load time 579.15 ms llama_print_timings: sample time 0.72 ms / 28 runs ( 0.03 ms per token, 38888.89 tokens per second) llama_print_timings: prompt eval time 655.63 ms / 10 tokens ( 65.56 ms per token, 15.25 tokens per second) llama_print_timings: eval time 2180.97 ms / 27 runs ( 80.78 ms per token, 12.38 tokens per second) llama_print_timings: total time 2891.13 ms第一行日志是 simple.cpp 中打印的n_predict 32计划生成 32 个 token、n_ctx 2048模型上下文窗口、n_kv_req 32本次请求实际需要的 KV cache 空间并检查n_kv_req n_ctx以确保 KV cache 足够容纳 prompt 与生成 token中间两行是真实生成结果模型在 Hello my name is 之后续写出了 Shawn and Im a 20 year old male...decoded 27 tokens in 2.31 s, speed: 11.68 t/s是主循环统计实际解码了 27 个 token因为遇 EOG 提前结束吞吐约 11.68 token/s最后 5 行llama_print_timings是llama_print_timings(ctx)打印的详细计时对应源码 simple.cppload time模型文件加载耗时sample time采样贪心选择耗时28 runs 累计 0.72 msprompt eval timeprompt 预填充prefill阶段耗时10 个 token 用了 655.63 ms约 15.25 token/seval time逐 token 生成decode阶段耗时27 次解码 2180.97 ms约 12.38 token/stotal time总计 2.89 s。注意上述数字是 README 记录的一次参考运行结果受 CPU/GPU 环境与模型影响极大你在本机跑出的数值通常不同prompt eval与eval的吞吐差异正是并行预填充 vs 逐 token 自回归两种计算模式的典型体现。源码级剖析llama-simple 的七步推理管线simple.cpp 全文只有 175 行主流程清晰划分为七个阶段。下面结合源码逐段讲解。第一步参数解析与默认值gpt_params params; params.prompt Hello my name is; params.n_predict 32; if (!gpt_params_parse(argc, argv, params)) { print_usage(argc, argv, params); return 1; }gpt_params定义于 common/common.h是common库统一使用的参数聚合结构。程序先把prompt与n_predict设好默认值再用gpt_params_parse覆盖为命令行传入值解析失败时调用gpt_params_print_usage打印用法simple.cpp。gpt_params_parse在 common/common.cpp 中实现支持大量参数。与本示例直接相关的有参数含义默认值gpt_params结构-m, --model模型文件路径空字符串-p, --prompt提示词空simple 内覆盖为 Hello my name is-n, --predict, --n-predict生成 token 数-1表示无限-2表示直到填满上下文-1见 common/common.h-c, --ctx-size上下文大小0使用模型默认-t, --threadsCPU 计算线程数cpu_get_num_math()-b, --batch-size逻辑批大小prompt 处理2048-ub, --ubatch-size物理批大小512--numa启用 NUMA 支持关闭-n的解析逻辑在 common/common.cpp 中可见if (arg -n || arg --predict || arg --n-predict) { ... params.n_predict std::stoi(argv[i]); }。第二步后端初始化llama_backend_init(); llama_numa_init(params.numa);llama_backend_init()负责初始化后端CPU 线程池、BLAS 等llama_numa_init则按参数启用 NUMA 感知调度仅在--numa开启时有实际作用。第三步加载模型llama_model_params model_params common_model_params_to_llama(params); llama_model * model llama_model_load_from_file(params.model.c_str(), model_params);common_model_params_to_llama声明见 common/common.h把gpt_params转换为底层 C API 的llama_model_params结构随后llama_model_load_from_file从磁盘加载 GGUF 模型。若返回NULL程序打印 unable to load model 并退出。第四步创建推理上下文llama_context_params ctx_params common_context_params_to_llama(params); llama_context * ctx llama_init_from_model(model, ctx_params);上下文llama_context承载 KV cache 与运行时状态。这一步会把n_ctx上下文窗口等参数固化到实际运行环境。第五步分词与 KV 容量预检std::vectorllama_token tokens_list; tokens_list ::common_tokenize(ctx, params.prompt, true); const int n_ctx llama_n_ctx(ctx); const int n_kv_req tokens_list.size() (n_predict - tokens_list.size()); if (n_kv_req n_ctx) { LOG_TEE(%s: error: n_kv_req n_ctx, the required KV cache size is not big enough\n, __func__); LOG_TEE(%s: either reduce n_predict or increase n_ctx\n, __func__); return 1; }common_tokenizecommon/common.h把 prompt 字符串切成 token 序列第三个参数add_special true表示自动附加特殊 token如 BOSn_kv_req估算本次请求需要占用的 KV 位置数prompt token 数 待生成 token 数此处假设会生成满n_predict个若超出n_ctx程序给出两条修复建议减小n_predict或增大n_ctx通过-c参数。随后程序还会把 prompt 逐 token 还原打印到 stderr调用common_token_to_piece方便确认分词是否正确。第六步构建 batch 并预填充 promptllama_batch batch llama_batch_init(512, 0, 1); for (size_t i 0; i tokens_list.size(); i) { common_batch_add(batch, tokens_list[i], i, { 0 }, false); } batch.logits[batch.n_tokens - 1] true; if (llama_decode(ctx, batch) ! 0) { LOG_TEE(%s: llama_decode() failed\n, __func__); return 1; }这是全程序最关键的部分理解它就能理解 llama.cpp 的批处理模型llama_batch_init(512, 0, 1)分配一个最多容纳 512 个 token、每个 token 最多属于 1 个序列的 batchAPI 说明见 include/llama.hembd 0表示不使用 embedding 输入common_batch_add把 prompt 的每个 token 按位置i依次填入 batch辅助函数声明见 common/common.hbatch.logits[batch.n_tokens - 1] true是刻意为之只要求解码器为 batch 中最后一个 token 输出 logits因为生成阶段只需要最后一个位置的概率分布llama_decode(ctx, batch)一次性并行处理整个 prompt即 prefill/预填充阶段这也是为什么 README 输出中 prompt eval 10 个 token 只花了 655 ms——并行预填充远快于逐 token 生成。第七步自回归生成主循环while (n_cur n_predict) { // 1. 取最后一个 token 的 logits auto n_vocab llama_n_vocab(model); auto * logits llama_get_logits_ith(ctx, batch.n_tokens - 1); // 2. 构造候选数组 std::vectorllama_token_data candidates; for (llama_token token_id 0; token_id n_vocab; token_id) { candidates.emplace_back(llama_token_data{ token_id, logits[token_id], 0.0f }); } llama_token_data_array candidates_p { candidates.data(), candidates.size(), false }; // 3. 贪心采样 const llama_token new_token_id llama_sample_token_greedy(ctx, candidates_p); // 4. EOG 判断 if (llama_token_is_eog(model, new_token_id) || n_cur n_predict) { break; } // 5. 输出 token 并放入新 batch LOG_TEE(%s, common_token_to_piece(ctx, new_token_id).c_str()); common_batch_clear(batch); common_batch_add(batch, new_token_id, n_cur, { 0 }, true); // 6. 解码新 token if (llama_decode(ctx, batch)) { ... } }循环内每轮迭代执行取 logits → 采样 → 判 EOG → 提交单 token → 解码的闭环llama_get_logits_ithinclude/llama.h取第i个位置的 logits 指针-1表示最后一个位置程序把整个词表的 logits 全部包装进llama_token_data_arrayllama_sample_token_greedyinclude/llama.h执行贪心采样——直接选概率最高的 token。API 注释明确指出它不计算 token 概率即不做 softmax 归一化也能取 argmax因此速度极快这也解释了 README 中sample time只有 0.72 msllama_token_is_eoginclude/llama.h判断当前 token 是否为结束生成类 tokenEOS、EOT 等命中即终止所以示例中实际只解码了 27 个 token 而非满 32 个common_batch_clearcommon_batch_add复用同一块 batch 内存每轮只提交一个新 tokenadd_special参数此时为true表示需要计算 logits主循环结束时调用llama_print_timings(ctx)输出计时随后依次llama_batch_free、llama_free(ctx)、llama_free_model(model)、llama_backend_free()释放全部资源——这是每个 llama.cpp 程序都应当遵循的对称清理顺序。从 llama-simple 出发下一步进阶路线llama-simple刻意省略了真实应用需要的许多环节阅读源码时你可以对照以下清单观察它没做什么并据此规划进阶方向采样策略simple 只用贪心。更丰富的采样top-k、top-p、温度、重复惩罚等由llama_sample_*系列 API 与common_sampler提供可参考 common/sampling.cpp 与 examples/main/main.cpp多序列与批处理复用simple 单序列单请求llama_batch_init(512, 0, 1)的第三个参数n_seq_max 1多序列并行、KV cache 复用的完整实现见 examples/serverllama-server与 examples/batched对话与模板simple 无聊天模板渲染llama-server通过 models/templates 下的 jinja 模板支持多轮对话与工具调用性能测量llama_print_timings给出的五段计时是通用指标配合 examples/llama-bench 可以做更系统的基准对比。如果你想把llama-simple改成自己的第一个推理程序最自然的三个实验是把llama_sample_token_greedy换成llama_sample_token(ctx, candidates_p)配合common_sampler设定温度/top-p用-c 4096扩大上下文并观察 KV 预检行为或把common_tokenize的add_special改为false观察特殊 token 对生成质量的影响。小结llama-simple用约 175 行代码完整呈现了 llama.cpp 系推理引擎的最小可行管线参数解析 → 后端初始化 → 模型加载 → 上下文创建 → 分词与 KV 容量检查 → batch 预填充 → 自回归采样生成。它的每个环节都对应一组明确的 C API 调用llama_decode、llama_get_logits_ith、llama_sample_token_greedy、llama_token_is_eog这些调用同样构成了llama-cli、llama-server等重量级程序的地基。理解了这个最小闭环你就掌握了阅读 ik_llama.cpp 全部推理代码的钥匙。【免费下载链接】ik_llama.cppllama.cpp fork with additional SOTA quants and improved performance项目地址: https://gitcode.com/GitHub_Trending/ik/ik_llama.cpp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

从零搭建open-code-review:自动化代码评审的完整实践指南

从零搭建open-code-review:自动化代码评审的完整实践指南

周一早上十点,同事在群里扔了一条链接:"这个 PR 已经放三天了,有人能帮我看下吗?" 这种场景几乎每个研发团队都经历过。open-code-review 这个项目,最早就是为这件事做的自动化评审助理。它不追求取代人的判…

2026/9/22 1:24:44 阅读更多 →
Hermes Desktop 接入 Hindsight 长期记忆配置指南

Hermes Desktop 接入 Hindsight 长期记忆配置指南

Hermes Desktop 接入 Hindsight 长期记忆配置指南 【免费下载链接】hindsight Hindsight: Agent Memory That Learns 项目地址: https://gitcode.com/GitHub_Trending/hindsight2/hindsight Hermes Desktop 可以直接把 Hindsight 设为 Agent 的长期记忆提供方&#xff1…

2026/9/20 13:43:21 阅读更多 →
Android AudioFlinger驱动调试日志全解析

Android AudioFlinger驱动调试日志全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/21 15:53:40 阅读更多 →

最新新闻

游戏退款系统源码解析:3步搞定支付逆向工程

游戏退款系统源码解析:3步搞定支付逆向工程

游戏退款系统源码解析:3步搞定支付逆向工程 别再把时间浪费在翻几百页的《支付网关接入指南》上了。官方文档里全是合规废话,真正能跑通的逻辑藏在几行核心代码里。 很多后端新手接到“游戏退款”需求时,第一反应是去查 API…

2026/9/22 1:24:32 阅读更多 →
教育的本质:3个避坑指南让你面试不再答非所问

教育的本质:3个避坑指南让你面试不再答非所问

教育的本质:3个避坑指南让你面试不再答非所问 面试被问“教育的本质”时,你脑子里是不是还卡在“传道授业解惑”的背词阶段?别慌,大多数开发者都栽在这个看似文科、实则硬核的逻辑陷阱里。今天这篇避坑指南,不聊虚的,直接拆解这道题背后的性能优化逻辑…

2026/9/22 1:24:32 阅读更多 →
N43实战:从零搭建高效刷题系统

N43实战:从零搭建高效刷题系统

N43实战:从零搭建高效刷题系统 刚毕业那会儿,我手里攥着几份大厂给的算法题,复制代码到本地跑,结果直接报错。报错信息满屏红字,根本看不懂哪行出了问题。那种挫败感,谁懂?后来我发现,问题不在代码,在于环境配置和依赖管理太混乱。今天分享一套…

2026/9/22 1:24:31 阅读更多 →
综艺节目游戏性能优化:告别StackTrace报错,掌握最佳实践

综艺节目游戏性能优化:告别StackTrace报错,掌握最佳实践

综艺节目游戏性能优化:告别StackTrace报错,掌握最佳实践 凌晨三点,控制台里滚动的红色报错让人头皮发麻。StackTrace 堆栈长得像天书,一行行 at com.game.core...…

2026/9/22 1:24:31 阅读更多 →
3招搞定解压缩文件性能优化:从Python到Rust实战对比

3招搞定解压缩文件性能优化:从Python到Rust实战对比

3招搞定解压缩文件性能优化:从Python到Rust实战对比 你是不是也遇到过这种情况?网上复制了一段解压缩文件的代码,往本地一跑,直接报错 FileNotFoundError…

2026/9/22 1:24:31 阅读更多 →
3行代码跑通psp图:源码解析帮你彻底搞懂原理

3行代码跑通psp图:源码解析帮你彻底搞懂原理

3行代码跑通psp图:源码解析帮你彻底搞懂原理 刚拿到这份psp图代码,是不是满屏报错?别慌,复制来的代码跑不通不知道怎么调,这是每个新手入行的第一道坎。今天咱们不整虚的,直接拆解psp图的底层逻辑,用源码解析的方式,带你从原理到实战,一步…

2026/9/22 1:23:30 阅读更多 →

日新闻

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天

3台商务办公笔记本实测:手写实现环境配置,告别卡半天 配置环境就卡半天?别怪机器慢,多半是你没选对工具链。在Java、Go或Python的项目现场, 手写实现…

2026/9/22 0:00:41 阅读更多 →
剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑

剑帝加点速查手册:3分钟搞懂核心逻辑 面试被问原理答不上来,是不是常态?别慌。很多开发者对着 GitHub 开源仓库里的代码发呆,看似简单实则暗藏玄机。今天这份【剑帝加点】速查手册,直接带你拆解核心实现,把面试必考的原理讲透。…

2026/9/22 0:00:41 阅读更多 →
手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优

手写实现图片压缩网站核心:搞定WebP转换与质量调优 复制来的代码跑不通不知道怎么调?别慌,这种“复制粘贴地狱”在开发圈太常见了。尤其是做 图片压缩网站…

2026/9/22 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/21 3:13:20 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/21 2:19:36 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/21 4:51:05 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/19 23:35:34 阅读更多 →