llama.cpp CPU 佔用分析:400% 的 CPU 追蹤到 ggml 熱點函式
當 llama.cpp 在 CPU 上執行 LLaMA 2 模型時,它可以輕鬆消耗掉 400% 的 CPU 核心資源。這些 CPU 時間究竟花在了哪裡?我們使用 OpenResty XRay 對一個正在執行量化 7B 模型的、未經修改的 llama.cpp 程序進行了實時剖析,並將 CPU 佔用追蹤到兩條最主要的程式碼路徑:ggml_compute_forward_mul_mat(通用矩陣乘法)和 ggml_vec_dot_q4_K_q8_K(k_quants.c 中的量化向量點積)。
本文將展示完整的剖析過程——從觀察到高 CPU 佔用開始,一直定位到具體的原始檔和行號。
執行 llama.cpp 並觀察到 400% 的 CPU 使用率
首先,編譯 llama.cpp 時開啟除錯符號,以便剖析工具能夠解析函式名和原始碼位置:
cd llama.cpp
make -j4 OPT="-g -O3"
然後使用量化後的 LLaMA 2 7B 模型執行 main 程式。LLaMA 2 是 Meta 公司開源的大語言模型。這裡我們使用 Q4_K_M 量化版本,它將 7B 模型壓縮到約 4 GB——小到足以透過 llama.cpp 完全在 CPU 上執行:
./main -m models/llama-2-7b-chat.ggmlv3.q4_K_M.bin -n 4096 -p "Linux"
其中 -n 4096 選項指定生成的 token 數,-p "Linux" 則是用來生成內容的提示詞。
程序載入模型後開始生成文字。請注意輸出中的 system_info 一行——它顯示 n_threads = 4、AVX = 1、AVX2 = 1 以及 BLAS = 0,表示當前構建使用了 AVX2 SIMD 指令,但沒有連結外部 BLAS 庫:
在另一個終端中,top 命令顯示 main 程序消耗了接近 400% 的 CPU——4 個核心全部被打滿:
問題來了:llama.cpp 內部究竟是哪些 C++ 函式造成了這麼高的 CPU 佔用?
使用 OpenResty XRay 剖析 llama.cpp 的 CPU 佔用
我們使用 OpenResty XRay 來回答這個問題。OpenResty XRay 可以透過動態追蹤技術直接附加到正在執行的、未經修改的程序上並生成 CPU 火焰圖——無需重新編譯,也無需插樁。
在 OpenResty XRay 的 Web 控制檯中,進入 Guided Analysis(引導式分析)頁面,選擇 High CPU usage(高 CPU 使用率)作為問題型別,然後從程序列表中選擇 llama.cpp 的 main 程序。控制檯顯示該程序的 CPU 佔用為 320.4%,並且完整的命令列清晰可見:
將應用程式型別設定為 C/C++,最大分析時間保持預設的 300 秒不變。點選 Start analyzing(開始分析)後,系統會持續執行多輪取樣分析。對這個案例來說,兩輪分析就足夠了。停止分析後,系統會自動生成分析報告。
分析結果:最熱的 C++ 程式碼路徑
自動生成的報告識別出三條熱點 C++ 程式碼路徑,每條路徑都標註了佔總 CPU 時間的百分比和完整的呼叫鏈:
第一名:ggml_compute_forward_mul_mat——佔 CPU 時間的 21.1%
最熱的程式碼路徑指向 ggml.c 中的 ggml_compute_forward_mul_mat。這是 ggml 庫中的通用矩陣乘法(GEMM)核心——它是 Transformer 推理中注意力機制和前饋層背後的核心運算。而其上一級呼叫它的函式 ggml_graph_compute_thread 負責進行單個執行緒的計算:
點選 More(更多)展開詳情,可以看到這條程式碼路徑所依據的 CPU 火焰圖。火焰圖以視覺化的方式呈現了完整的呼叫棧,越寬的框表示消耗的 CPU 時間越多:
OpenResty XRay 還會為這條程式碼路徑自動生成解釋說明和最佳化建議。它指出 ggml_compute_forward_mul_mat 計算的是兩個張量的矩陣乘法,並給出了包括並行化、記憶體訪問最佳化,以及使用 BLAS 或 LAPACK 等最佳化庫在內的多種最佳化策略:
其中 BLAS 這條建議在這裡尤其切中要害——回想一下前面 system_info 輸出中的 BLAS = 0,這說明 llama.cpp 用的是自己實現的 GEMM,而不是經過最佳化的 BLAS 庫。在編譯時啟用 OpenBLAS 或 Intel MKL,有望顯著降低這條熱點路徑的 CPU 佔比。
第二名:ggml_vec_dot_q4_K_q8_K——佔 CPU 時間的 17.4%
第二熱的程式碼路徑指向 k_quants.c 中的 ggml_vec_dot_q4_K_q8_K:
這個函式計算兩個量化向量的點積——K 採用 4 位元量化(q4_K),Q 採用 8 位元量化(q8_K)。量化點積正是 llama.cpp 能夠在 CPU 上跑動 7B 模型的關鍵所在——它帶來了速度和記憶體上的巨大節省:
從剖析報告定位到原始碼
OpenResty XRay 會把每個熱點函式對映回它的原始檔和行號。把滑鼠懸停在報告中 ggml_vec_dot_q4_K_q8_K 的函式框上,提示框會顯示確切位置:llama.cpp/k_quants.c 檔案的第 2608 行:
開啟 k_quants.c,按照報告提示框中的指引跳轉到第 2608 行:
我們可以看到這行程式碼使用了 C 語言的位運算來對陣列的元素進行一些操作——從打包成 12 位元組的 scales 表示中解出量化的縮放因子:
在狀態列中可以看到這行程式碼也確實在之前報告裡提到的 ggml_vec_dot_q4_K_q8_K 函式中:
這種精確度——從一個正在執行的程序一路定位到消耗 CPU 的具體原始碼行——正是動態追蹤型剖析工具在分析 LLM 推理這類計算密集型應用的 CPU 去向時的價值所在。
常見問題
llama.cpp 為甚麼消耗這麼多 CPU?
llama.cpp 對大語言模型做推理時,主要的計算就是矩陣乘法和量化向量點積。在我們對 LLaMA 2 7B 執行過程的剖析中,CPU 佔用第一名是 ggml_compute_forward_mul_mat——ggml 庫中的通用矩陣乘法核心;第二名是 ggml_vec_dot_q4_K_q8_K,它計算兩個量化向量的點積。這些運算本身就是計算密集型的,在 CPU 上做推理很容易跑滿多個核心、達到 400% 的佔用。
如何剖析 llama.cpp 的 CPU 佔用?
一種方法是使用像 OpenResty XRay 這樣基於動態追蹤的剖析工具。它可以直接附加到正在執行的、未經修改的 llama.cpp 程序上並生成 CPU 火焰圖。火焰圖能精確揭示哪些 C++ 函式消耗的 CPU 時間最多——一直細化到原始檔和行號——而無需修改或插樁正在執行的應用程式。
llama.cpp 中最熱的 C++ 函式是哪些?
在我們對執行量化 LLaMA 2 7B 模型的 llama.cpp 的分析中,第一熱點程式碼路徑是 ggml_compute_forward_mul_mat(佔 CPU 時間的 21.1%),由 ggml_graph_compute_thread 呼叫;第二熱點路徑是 k_quants.c(第 2608 行)中的 ggml_vec_dot_q4_K_q8_K(佔 17.4%),它對量化陣列元素做位運算。加上第三條路徑(佔 13.4%),這三條程式碼路徑合計佔據了一半以上的 CPU 時間。
關於 OpenResty XRay
OpenResty XRay 是一個動態追蹤產品,它可以自動分析執行中的應用程式,以解決效能問題、行為問題和安全漏洞,並提供可行的建議。在底層實現上,OpenResty XRay 由我們的 Y 語言驅動,可以在不同環境下支援多種不同的執行時,如 Stap+、eBPF+、GDB 和 ODB。
關於本文和關聯影片
本文和相關聯的影片都是完全由我們的 OpenResty Showman 產品從一個簡單的劇本檔案自動生成的。
關於作者
章亦春是開源 OpenResty® 專案創始人兼 OpenResty Inc. 公司 CEO 和創始人。
章亦春(Github ID: agentzh),生於中國江蘇,現定居美國灣區。他是中國早期開源技術和文化的倡導者和領軍人物,曾供職於多家國際知名的高科技企業,如 Cloudflare、雅虎、阿里巴巴, 是 “邊緣計算“、”動態追蹤 “和 “機器程式設計 “的先驅,擁有超過 22 年的程式設計及 16 年的開源經驗。作為擁有超過 4000 萬全球域名使用者的開源專案的領導者。他基於其 OpenResty® 開源專案打造的高科技企業 OpenResty Inc. 位於美國矽谷中心。其主打的兩個產品 OpenResty XRay(利用動態追蹤技術的非侵入式的故障剖析和排除工具)和 OpenResty Edge(最適合微服務和分散式流量的全能型閘道器軟體),廣受全球眾多上市及大型企業青睞。在 OpenResty 以外,章亦春為多個開源專案貢獻了累計超過百萬行程式碼,其中包括,Linux 核心、Nginx、LuaJIT、GDB、SystemTap、LLVM、Perl 等,並編寫過 60 多個開源軟體庫。
關注我們
如果您喜歡本文,歡迎關注我們 OpenResty Inc. 公司的部落格網站 。也歡迎掃碼關注我們的微信公眾號:
翻譯
我們提供了英文版原文和中譯版(本文)。我們也歡迎讀者提供其他語言的翻譯版本,只要是全文翻譯不帶省略,我們都將會考慮採用,非常感謝!
































