兩週前,我們發布了 jina-embeddings-v4 的 GGUF 格式,這是一個用於多模態多語言檢索的通用向量模型,並提供各種量化版本。我們的動機很簡單:由於 jina-embeddings-v4 是一個 3.75B 參數的模型,其原始 Transformer 版本在我們的 GCP G2 (L4 GPU) API 實例上擴展性不佳,因此我們希望使用這些更小、更快的 GGUF 版本來加速推理。在我們的實驗中,我們在轉換和運行 GGUF 向量模型時發現了一些有趣的結果。由於大多數 llama.cpp
社群都專注於大模型,我們認為從向量模型提供者的角度分享這些資訊會很有價值。
特別相關的是,現今的向量模型幾乎與大模型相同 —— 例如,jina-embeddings-v4 是基於 Qwen2.5-VL-3B-instruct
,而 jina-reranker-m0 則是基於 Qwen2-VL-2B
。 唯一真正的區別在於輸出:大模型是生成式的,而向量模型和重排器是判別式的。 這帶來了機會和挑戰:一方面,我們可以利用 llama.cpp
的高效實現(例如 ubatch_size
)來提供向量模型/重排器模型的服務;另一方面,llama.cpp
的向量模型實作主要針對較舊的僅編碼器架構(如基於 RoBERTa 的模型)開發,尚未完全趕上現代的僅解碼器向量模型/重排器模型。本文分享了我們在調整現代向量模型以使用 GGUF 格式和 llama.cpp
工具(例如 llama-embedding
和 llama-serving
)時所學到的知識。
tagBase 和 Quantized GGUFs
jina-embeddings-v4 是基於 Qwen2.5-VL-3B-instruct
,並具有三個 LoRA 適配器:retrieval
(針對檢索任務進行優化)、text-matching
(針對句子相似度任務進行優化)和 code
(針對程式碼檢索任務進行優化)。它也經過大量視覺文件檢索和後期互動風格多向量輸出的訓練。所以這裡的想法是利用 llama.cpp
現有的 Qwen2.5-VL-3B
圖形實作,並使用 llama-embedding
進行推理。
然而,我們首先注意到的是 llama.cpp 中 mmproj
或視覺 Transformer 實作中的錯誤行為,這導致在給定相同圖像輸入的情況下,相對於 Qwen2.5-VL-3B
的 Torch 實作產生不同的向量模型。在我們 在我們的分支中 解決這個問題的同時,我們決定暫時從 GGUF 版本中排除視覺 tower。您可以在這裡找到關於這個討論的更多細節。
多向量向量模型輸出 也不是開箱即用的,但它不像視覺 Transformer 那樣是個大問題。多向量輸出來自最後一個 Transformer 區塊中經過訓練的 MLP,因此在最壞的情況下,我們總是可以將這個 MLP 單獨匯出到 NumPy,並在從 llama.cpp
獲得詞元層級的向量模型後應用它 —— 這就是我們對 jina-reranker-m0-GGUF
所做的。 當然,這不是很有效率,但它可以在不必修改和重新編譯 llama.cpp
的情況下工作。
我們去除了視覺 Transformer 和多向量投影器,並獲得了三個 F16 中的基本 GGUF 模型。
因此,為了完全符合 llama.cpp
現有的 Qwen2.5-VL-3B
圖形實作,我們去除了視覺 Transformer 和最後一個 Transformer 區塊中的多向量投影器,並將所有 LoRA 適配器合併回基本語言模型。這給了我們三個特定任務的 v4 模型,每個模型有 3.09B 參數 —— 低於原始 v4 的 3.75B 參數:
HuggingFace Repo | Task |
---|---|
jinaai/jina-embeddings-v4-text-retrieval-GGUF |
文字檢索 |
jinaai/jina-embeddings-v4-text-code-GGUF |
程式碼檢索 |
jinaai/jina-embeddings-v4-text-matching-GGUF |
句子相似度 |
然後我們使用 calibration_data_v5_rc.txt
(可以在 這裡 找到,並且是 Unsloth 推薦的)來校準所有三個基本 GGUF 模型,並獲得三個 imatrix
檔案,然後使用帶有 imatrix
的 llama-quantize
將模型從 float16 量化如下:
# build imatrix
llama-imatrix -m jina-embeddings-v4-text-retrieval-F16.gguf -f calibration_data_v5_rc.txt -ngl 99 --no-ppl -o imatrix-retrieval-512.dat
# quantize
./quantize.sh jina-embeddings-v4-text-retrieval-F16.gguf retrieval-i3 imatrix-retrieval-512.dat jinaai/jina-embeddings-v4-text-retrieval-GGUF
quantize.sh
腳本如下所示:
#!/bin/bash
F16_MODEL_FILE="$1"
OUTPUT_DIR="$2"
IMATRIX="$3"
HF_REPO="$4"
FILENAME="$(basename "$F16_MODEL_FILE")"
BASE_NAME="${FILENAME%-F16.gguf}"
BASE_NAME="${BASE_NAME%.gguf}"
mkdir -p "$OUTPUT_DIR"
# Array of quantization types
QUANT_TYPES=("IQ1_S" "IQ1_M" "IQ2_XXS" "IQ2_M" "Q2_K" "IQ4_NL" "IQ4_XS" "IQ3_XXS" "IQ3_S" "IQ3_M" "IQ3_XS" "Q3_K_M" "Q4_K_M" "Q5_K_S" "Q5_K_M" "Q6_K" "Q8_0")
for quant_type in "${QUANT_TYPES[@]}"; do
llama-quantize --imatrix "${IMATRIX}" "$F16_MODEL_FILE" "${OUTPUT_DIR}/${BASE_NAME}-${quant_type}.gguf" $quant_type 8
done
最終,我們將所有量化模型上傳到 HuggingFace。
量化 | BPW | 檔案大小 (GB) |
---|---|---|
IQ1_S | 2.04 | 0.73 |
IQ1_M | 2.19 | 0.79 |
IQ2_XXS | 2.44 | 0.88 |
IQ2_M | 2.94 | 1.06 |
Q2_K | 3.29 | 1.18 |
IQ3_XXS | 3.31 | 1.19 |
IQ3_XS | 3.59 | 1.29 |
IQ3_S | 3.76 | 1.35 |
IQ3_M | 3.84 | 1.38 |
Q3_K_M | 4.11 | 1.48 |
IQ4_NL | 4.72 | 1.69 |
IQ4_XS | 4.49 | 1.61 |
Q4_K_M | 4.99 | 1.79 |
Q5_K_S | 5.61 | 2.02 |
Q5_K_M | 5.75 | 2.07 |
Q6_K | 6.56 | 2.36 |
Q8_0 | 8.50 | 3.05 |
F16 | 16.00 | 5.75 |
v3 (Transformers) | 16.00 | 1.10 |
v4 (Transformers) | 16.00 | 7.40 |

tag使用方式和注意事項
現在,我們可以使用 llama-server
和 llama-embedding
來提供 GGUF 的向量模型服務。與 transformer 函式庫不同,在 transformer 函式庫中,我們可以彈性地編寫自訂的輸入前處理程式碼,我們必須手動處理這部分(除非我們想要重新編譯 llama-server
和 llama-embedding
)。具體來說,為了獲得與使用 AutoModel.from_pretrained("jinaai/jina-embeddings-v4")...
完全一致的結果,您需要非常小心前綴,並手動將它們添加到您的 GGUF 模型輸入中。以下是一個參考表格:
任務 | Transformer 實作中的 prompt_name |
模型的實際輸入 |
---|---|---|
retrieval |
query (預設) |
Query: {original_text} |
retrieval |
passage |
Passage: {original_text} |
text-matching |
query (預設) |
Query: {original_text} |
text-matching |
passage |
Query: {original_text} ⚠️ |
code |
query (預設) |
Query: {original_text} |
code |
passage |
Passage: {original_text} |
有些使用者可能會覺得 ⚠️ 令人驚訝,當在原始的 AutoModel.from_pretrained("jinaai/jina-embeddings-v4")....
中使用 text-matching
時,prompt_name='passage'
會被覆寫為 "Query: "
。但這實際上是有道理的,因為 text-matching
是一個句子相似度任務,沒有左右角色——輸入是對稱的。
tag透過 llama-server
安裝 llama.cpp
後,您可以執行 llama-server
來將向量模型託管為與 OpenAI API 相容的 HTTP 伺服器。例如,要將 text-matching
與 F16
一起使用,您可以執行:
llama-server -hf jinaai/jina-embeddings-v4-text-matching-GGUF:F16 --embedding --pooling mean -ub 8192
--pooling mean
是必需的,因為 v4 是平均池化向量模型。
然後透過以下方式發送請求:
curl -X POST "http://127.0.0.1:8080/v1/embeddings" \
-H "Content-Type: application/json" \
-d '{
"input": [
"Query: A beautiful sunset over the beach",
"Query: Un beau coucher de soleil sur la plage",
"Query: 海滩上美丽的日落",
"Query: 浜辺に沈む美しい夕日"
]
}'
當使用 retrieval
和 code
模型時,請在輸入前面新增 Query:
或 Passage:
,如下所示:
curl -X POST "http://127.0.0.1:8080/v1/embeddings" \
-H "Content-Type: application/json" \
-d '{
"input": [
"Query: A beautiful sunset over the beach",
"Query: Un beau coucher de soleil sur la plage",
"Passage: 海滩上美丽的日落",
"Passage: 浜辺に沈む美しい夕日"
]
}'
tag透過 llama-embedding
為了快速進行健全性檢查,您也可以使用預先編譯的 llama-embedding
進行一次性向量模型提取。我們不建議將其用於大量向量模型提取,因為它存在一些效能問題,我們將在下一節中討論:
llama-embedding -hf jinaai/jina-embeddings-v4-text-matching-GGUF:F16 --pooling mean -p "Query: jina is awesome" --embd-output-format json 2>/dev/null
請閱讀下一節,以了解使用我們建構的 llama-embedding
進行更高效能的大量向量模型提取,並進行一些修正和改進。
tag注意事項摘要
在轉向效能更高的實作之前,讓我們先總結一下 GGUF 模型的注意事項:
- 您必須在文字輸入前面手動新增
Query:
或Passage:
。 - 它們目前無法處理圖像輸入,因為我們從 GGUF 模型中移除了視覺 transformer。我們必須移除它們,因為 llama.cpp 的視覺 transformer/
mmproj
實作中存在錯誤,該實作基於Qwen2.5-vl-3b
,我們正在 與上游合作修復。 - 它們無法輸出多向量向量模型,因為它不是
llama.cpp
的Qwen2.5-vl-3b
圖形實作的一部分。無需重新編譯llama.cpp
的最簡單解決方法是在llama-embedding
中設定--pooling none
,以在取得詞元層級向量模型後,單獨匯出並執行 MLP。 - v4 是使用 Matryoshka 表示學習訓練的,轉換為 GGUF 會保留此功能。如果您獲得形狀為
NxD
的向量模型,您可以簡單地使用embeddings[:, :truncate_dim]
來獲得較小的截斷向量模型。但是,並非每個維度都經過訓練。對於 v4,我們針對這些特定值訓練了truncate_dim
:[128, 256, 512, 1024, 2048]
。這表示embeddings[:, :131]
的品質不會是embeddings[:, :128]
和embeddings[:, :256]
品質之間的一些插值,而是會明顯低於 128 維或 256 維向量模型,因為 131 維沒有經過訓練。 - 延遲分塊仍然可以作為後處理的一部分工作,在透過
--pooling none
取得詞元層級向量模型後進行。就像我們將 MLP 與llama.cpp
圖形分離一樣,這不是很有效率,但不需要重新編譯。但是,還有另一個注意事項:由於 v4 是一個因果模型,延遲分塊將不再是雙向的 - 較早的分塊向量模型不會包含來自後續分塊的上下文資訊。請記住,在 v3 中,每個分塊向量模型都具有全域上下文資訊,因為我們在 transformer 區塊中使用了雙向注意力遮罩。在內部,我們討論了因果關係是否會使延遲分塊過時:有些人認為「上下文也是因果關係」 - 意味著讀者從左到右處理文字,因此解釋句子的上下文應該來自前面的文字。其他人則說,將延遲分塊限制為單向會阻礙分塊之間的上下文共享。無論如何,延遲分塊在 v4 中的有效性仍然值得懷疑,需要進一步研究。
tag透過 llama-embedding
進行高效向量模型提取
llama-embedding
是一個相對簡單的 C++ 包裝器,位於 llama.cpp
之上,用於提取具有非常乾淨的 I/O:stdin、stdout 的文字向量模型。我們目前專注於改進這個,而不是 llama-server
,因為還有許多其他問題,例如網路佇列、負載平衡、多租戶和序列化,我們認為這些問題目前不在範圍內。我們的問題很簡單:我們可以從 L4 24GB GPU 獲得多少速度,以及提取長文件的峰值 VRAM 使用量是多少?
但為什麼是 L4?主要是因為 GCP 在其上提供了非常方便的 Cloud Run 函式,並且它是您可以獲得的用於無伺服器推論 API 的最廣泛可用和經濟的 GPU 類型。GCP 確實按要求在 Cloud Run 上提供 A100 和 H100,而且 GCP 團隊也確實不時向我們推銷使用更好的 GPU。但我們的理念很簡單:如果我們需要 A100/H100 來提供 3B 模型服務,那顯然是我們的技術問題。
作為一些背景知識,在 llama.cpp 中,邏輯批次大小 (-b
)代表在單次評估呼叫中提交給模型的最大詞元數。當處理長輸入時,它們會被分割成不超過此大小的區塊。**物理批次大小**(-ub
)是在硬體上一次正向傳遞中同時處理的實際詞元數,受可用記憶體的限制。KV 快取會在每個物理批次完成後更新。**上下文視窗**(-c
)是模型一次可以「看到」的詞元數量的硬性限制 - 對於 v4 模型,這是 32,000 個詞元,代表模型的最長注意力範圍。所有詞元都必須在這個上下文視窗內,才能在整個序列中保持連貫的注意力。下圖說明了它們之間的關係。

tag我們的修正
在我們上面的分支中,我們進行了幾項最佳化,以提高 llama-embedding
的效率:
- 簡化的批次處理:我們自動將
-b
設定為等於-c
,實際上使這個參數變得多餘。使用者不再需要指定-b
,因為我們始終利用模型的完整上下文長度進行邏輯批次處理。 - 靈活的記憶體控制:與原始實作中
-ub
被強制等於-b
不同(因為他們假設向量模型不能是因果關係),我們允許使用者獨立設定-ub
。這可以在編碼長上下文時,對峰值 VRAM 使用量進行細粒度控制 - 由於 KV 快取的實作,您可以使用小的 512 詞元物理批次處理 32K 上下文,以保持在 VRAM 限制內。請注意,此變更僅適用於因果向量模型,如 jina-embeddings-v4 - 對於僅編碼器架構(如 v3),這將是錯誤的實作。 - 修正的均值池化:我們修正了當
ub < b
時,向量的均值池化計算,這在原始實作中先前已損壞。
此變更使得在有效管理記憶體限制的同時,使用長上下文僅解碼器向量模型變得更加容易。使用者現在只需要配置兩個參數:
-c
:最大上下文長度(向量模型可以處理多少個詞元)-ub
:物理批次大小(GPU 一次處理多少個詞元)
因此,在 L4 上執行我們分支的確切程式碼如下:
# Compile
git clone https://github.com/hanxiao/llama.cpp.git
cd llama.cpp
cmake -B build -DGGML_CUDA=ON
cmake --build build --config Release -j 8
# Run
INPUT_PREFIX="Query: " # or "Passage: "
cat big_input.txt | sed "s/^/${INPUT_PREFIX}/" | \
./llama.cpp/build/bin/llama-embedding -f /dev/stdin \
-hf "jinaai/jina-embeddings-v4-text-retrieval-GGUF:FP16" \
--pooling mean \
--no-escape \
--embd-output-format array \
--ubatch-size 512 \
--ctx-size 8192 \
--flash-attn \
-ngl 99 \
> "embeddings.txt" 2> "error.log"
big_input.txt
中的每一行都是要嵌入的句子。應設定 --no-escape
以防止句子中的 \n
被解釋為分隔符。應設定 --flash-attn
和 -ngl 99
以在 L4 GPU 上獲得最佳效能。
tag基準測試
我們希望透過基準測試了解以下問題:
- 與原始 v4 Float16 相比,我們的量化效果如何?它在什麼時候會降級到我們最好使用 v3 向量模型的程度?
- 每種量化在 L4 上可以多快執行,以及峰值 VRAM 使用量是多少?
-ub
物理批次大小和-c
上下文長度如何影響速度和峰值 VRAM?
我們在基準測試中使用的資料集是:
任務 | 文件 | 查詢 | 相關配對 | 平均文件長度 | 最大文件長度 | 平均查詢長度 |
---|---|---|---|---|---|---|
NanoHotpotQA | 5,090 | 50 | 100 | 57.3 | 345 | 14.9 |
NanoSciFact | 2,919 | 50 | 56 | 205.8 | 1524 | 13.5 |
NanoArguAna | 3,635 | 50 | 50 | 164.5 | 1058 | 193.0 |
NanoNFCorpus | 2,953 | 50 | 2,518 | 223.3 | 1460 | 3.3 |
NanoFiQA2018 | 4,598 | 50 | 123 | 159.1 | 1882 | 10.2 |
我們使用了我們自訂建置的 llama-embedding
進行基準測試。
tag量化品質
效能最佳的量化版本是 IQ3_M
(3.84 BPW) - 低於 2 位的量化效能比 v3 差,因此使用它們沒有什麼意義。

Quantization | NanoHotpotQA | NanoFiQA2018 | NanoArguAna | NanoNFCorpus | NanoSciFact |
---|---|---|---|---|---|
IQ1_S | 0.6369 | 0.3178 | 0.3798 | 0.2933 | 0.5934 |
IQ1_M | 0.6316 | 0.3313 | 0.5167 | 0.3256 | 0.6114 |
IQ2_XXS | 0.7236 | 0.4582 | 0.4584 | 0.4067 | 0.7392 |
IQ2_M | 0.7427 | 0.5869 | 0.5090 | 0.4468 | 0.7880 |
Q2_K | 0.7683 | 0.5744 | 0.5168 | 0.4183 | 0.7546 |
IQ3_XXS | 0.7780 | 0.5991 | 0.4811 | 0.4267 | 0.7610 |
IQ3_XS | 0.7727 | 0.5615 | 0.5195 | 0.4439 | 0.7726 |
IQ3_S | 0.8002 | 0.5505 | 0.4886 | 0.4381 | 0.7690 |
IQ3_M | 0.8106 | 0.5387 | 0.5091 | 0.4462 | 0.7760 |
Q3_K_M | 0.7567 | 0.5267 | 0.4486 | 0.4092 | 0.7775 |
IQ4_NL | 0.7930 | 0.5598 | 0.4911 | 0.4285 | 0.7794 |
IQ4_XS | 0.7979 | 0.5627 | 0.4947 | 0.4258 | 0.7789 |
Q4_K_M | 0.8029 | 0.5569 | 0.4883 | 0.4226 | 0.7877 |
Q5_K_S | 0.7969 | 0.5581 | 0.4721 | 0.4288 | 0.7842 |
Q5_K_M | 0.7927 | 0.5601 | 0.4745 | 0.4247 | 0.7873 |
Q6_K | 0.7951 | 0.5636 | 0.4822 | 0.4337 | 0.7846 |
Q8_0 | 0.7938 | 0.5687 | 0.4784 | 0.4335 | 0.7851 |
F16 | 0.7940 | 0.5610 | 0.4931 | 0.4343 | 0.7963 |
v3 (Transformers) | 0.7393 | 0.5144 | 0.4600 | 0.4068 | 0.7820 |
v4 (Transformers) | 0.7977 | 0.5571 | 0.4844 | 0.4351 | 0.7963 |
tag速度與 VRAM
現在我們將基準測試資料集固定為 NanoHotpotQA,並繪製所有量化版本的每權重位元數與速度(以每秒詞元數衡量)和 VRAM 消耗的關係圖。我們發現 GGUF 版本在 FP16 時比原始版本稍快(2023 與 1865 個詞元/秒)。大多數量化版本都集中在 2000-2100 個詞元/秒附近。啟用 Flash Attention 後,所有量化版本的速度都提高了約 77%(3000+ 與 2000+ 個詞元/秒)。然而,性能最佳的量化版本 Q8_0
約為每秒 3700 個詞元,仍然遠遠落後於原始 v3(572M 參數),後者可達到每秒 16000 個詞元。量化版本節省了大量的 VRAM,並且幾乎達到 IQ3 的 v3 FP16 模型的水準。

Quantization | BPW | File Size (GB) | Peak VRAM (GB) | Token/s w FA | Token/s w/o FA |
---|---|---|---|---|---|
IQ1_S | 2.04 | 0.73 | 4.04 | 3625 | 2050 |
IQ1_M | 2.19 | 0.79 | 4.09 | 3349 | 1997 |
IQ2_XXS | 2.44 | 0.88 | 4.19 | 3701 | 2071 |
IQ2_M | 2.94 | 1.06 | 4.37 | 3407 | 1989 |
Q2_K | 3.29 | 1.18 | 4.49 | 3173 | 1905 |
IQ3_XXS | 3.31 | 1.19 | 4.50 | 3668 | 2067 |
IQ3_XS | 3.59 | 1.29 | 4.60 | 3604 | 2053 |
IQ3_S | 3.76 | 1.35 | 4.66 | 3599 | 2049 |
IQ3_M | 3.84 | 1.38 | 4.69 | 3603 | 2053 |
Q3_K_M | 4.11 | 1.48 | 4.78 | 3450 | 2008 |
IQ4_NL | 4.72 | 1.69 | 5.00 | 3571 | 2039 |
IQ4_XS | 4.49 | 1.61 | 4.92 | 3585 | 2046 |
Q4_K_M | 4.99 | 1.79 | 5.10 | 3558 | 2045 |
Q5_K_S | 5.61 | 2.02 | 5.32 | 3567 | 2044 |
Q5_K_M | 5.75 | 2.07 | 5.38 | 3528 | 2034 |
Q6_K | 6.56 | 2.36 | 5.66 | 3334 | 1981 |
Q8_0 | 8.50 | 3.05 | 6.36 | 3767 | 2101 |
F16 | 16.00 | 5.75 | 9.70 | 3399 | 2023 |
v3 (Transformers) | 16.00 | 1.10 | 2.82 | 16505 | |
v4 (Transformers) | 16.00 | 7.40 | 14.45 | 1865 |
點擊以展開系統資訊
load_tensors: 正在載入模型 tensors,這可能需要一些時間... (mmap = true)
load_tensors: 正在將 36 個重複層卸載到 GPU
load_tensors: 正在將輸出層卸載到 GPU
load_tensors: 已將 37/37 層卸載到 GPU
load_tensors: CUDA0 模型緩衝區大小 = 3127.61 MiB
load_tensors: CPU_Mapped 模型緩衝區大小 = 315.30 MiB
...................................................................................
llama_context: 正在建構 llama_context
llama_context: n_seq_max = 1
llama_context: n_ctx = 4096
llama_context: n_ctx_per_seq = 4096
llama_context: n_batch = 4096
llama_context: n_ubatch = 4096
llama_context: causal_attn = 1
llama_context: flash_attn = 1 // 表格中有 FA 時為 1;沒有 FA 時為 0
llama_context: kv_unified = true
llama_context: freq_base = 1000000.0
llama_context: freq_scale = 1
llama_context: n_ctx_per_seq (4096) < n_ctx_train (128000) -- 模型的完整容量將不會被利用
llama_context: CUDA_Host 輸出緩衝區大小 = 0.59 MiB
llama_kv_cache_unified: CUDA0 KV 緩衝區大小 = 144.00 MiB
llama_kv_cache_unified: size = 144.00 MiB (4096 cells, 36 layers, 1/1 seqs), K (f16): 72.00 MiB, V (f16): 72.00 MiB
llama_context: CUDA0 計算緩衝區大小 = 2470.16 MiB
llama_context: CUDA_Host 計算緩衝區大小 = 96.17 MiB
llama_context: graph nodes = 1234
llama_context: graph splits = 2
common_init_from_params: added <|endoftext|> logit bias = -inf
common_init_from_params: added <|im_end|> logit bias = -inf
common_init_from_params: added <|fim_pad|> logit bias = -inf
common_init_from_params: added <|repo_name|> logit bias = -inf
common_init_from_params: added <|file_sep|> logit bias = -inf
common_init_from_params: setting dry_penalty_last_n to ctx_size = 4096
common_init_from_params: warming up the model with an empty run - please wait ... (--no-warmup to disable)
system_info: n_threads = 4 (n_threads_batch = 4) / 8 | CUDA : ARCHS = 890 | USE_GRAPHS = 1 | PEER_MAX_BATCH_SIZE = 128 | CPU : SSE3 = 1 | SSSE3 = 1 | AVX = 1 | AVX2 = 1 | F16C = 1 | FMA = 1 | BMI2 = 1 | AVX512 = 1 | AVX512_VNNI = 1 | LLAMAFILE = 1 | OPENMP = 1 | REPACK = 1 |
main: n_tokens in batch = 0
main: number of embeddings = 5090
tag最佳物理批次大小和上下文大小
我們現在將量化類型固定為 IQ3_S
,並檢驗物理批次大小 (-ub
) 和上下文大小 (-c
) 如何影響速度和 VRAM。L4 GPU 上的結果顯示,-ub=512
搭配 -c=2048
提供了最佳配置,在消耗 2,025MB VRAM 的同時,傳輸了 4,143 個詞元/秒。結論很直觀:當您知道輸入中單個文件的最大長度時,請使用足夠覆蓋它的小上下文大小。對於物理批次大小,512 個詞元似乎是 L4 GPU 上的最佳點。

每秒詞元效能
ubatch_size | ctx_size=64 | ctx_size=128 | ctx_size=256 | ctx_size=512 |
---|---|---|---|---|
64 | 2233 | 2093 | 2128 | 2125 |
128 | N/A | 2866 | 2821 | 2877 |
256 | N/A | N/A | 3287 | 3349 |
512 | N/A | N/A | N/A | 3469 |
ubatch_size | ctx_size=2048 | ctx_size=4096 | ctx_size=8192 | ctx_size=16384 |
---|---|---|---|---|
256 | 3971 | 3630 | 3593 | 2766 |
512 | 4143 | 3797 | 3758 | 2852 |
1024 | 4059 | 3742 | 3707 | 2822 |
2048 | 3957 | 3631 | 3603 | 2762 |
4096 | N/A | 3450 | 3410 | 2625 |
峰值 VRAM 使用量 (MB)
ubatch_size | ctx_size=64 | ctx_size=128 | ctx_size=256 | ctx_size=512 |
---|---|---|---|---|
64 | 1691 | 1689 | 1689 | 1697 |
128 | N/A | 1729 | 1727 | 1737 |
256 | N/A | N/A | 1803 | 1811 |
512 | N/A | N/A | N/A | 1963 |
ubatch_size | ctx_size=2048 | ctx_size=4096 | ctx_size=8192 | ctx_size=16384 |
---|---|---|---|---|
256 | 1885 | 1947 | 2099 | 2409 |
512 | 2025 | 2101 | 2257 | 2577 |
1024 | 2329 | 2407 | 2571 | 2917 |
2048 | 2933 | 3025 | 3203 | 3597 |
4096 | N/A | 4285 | 4497 | 4985 |
tag結論
對於想要在低預算 GPU 上有效執行量化 GGUF 的 v4 使用者,請選擇 IQ3_S
或 IQ3_M
以及我們自訂建置的 llama-embedding
- 這應該可以在常規資料集(其中句子長度 <2048 個詞元)上提供 4000 個詞元/秒。為了嵌入更長的文件,請增加上下文大小 -c
並控制物理批次大小 -ub
以減少 VRAM 佔用空間。透過我們的自訂建置,您可以僅使用 3GB VRAM 編碼超長文件(>32K 個詞元),方法是將 -ub
設置為一個較小的數字,例如 1024 - 這在原始實作或 vanilla transformers 中是不可能實現的。
對速度優化的追求永無止境。始終有空間可以實現更快、更精簡且具有更高吞吐量的實作。4000 個詞元/秒可能不是我們的上限 - 還有很多工作要做。除了修復 llama.cpp
中的 qwen2.5-vl-3b
mmproj/vision transformer 實作之外,我們還在探索更深入的 llama.graph 和 KV-快取層級優化,改進 llama-serving
批次邏輯,並將串流選項添加到 embedding API。我們的目標是使 llama.cpp
原生支援現代僅解碼器多模態 embeddings,以用於我們目前和未來的 reranker 版本。