什么是鍵值緩存?讓 LLM 閃電般快速

一、為什么 LLMs 需要 KV 緩存?

大語言模型(LLMs)的文本生成遵循 “自回歸” 模式 —— 每次僅輸出一個 token(如詞語、字符或子詞),再將該 token 與歷史序列拼接,作為下一輪輸入,直到生成完整文本。這種模式的核心計算成本集中在注意力機制上:每個 token 的輸出都依賴于它與所有歷史 token 的關聯,而注意力機制的計算復雜度會隨序列長度增長而急劇上升。

以生成一個長度為 n 的序列為例,若不做優化,每生成第 m 個 token 時,模型需要重新計算前 m 個 token 的 “查詢(Q)、鍵(K)、值(V)” 矩陣,導致重復計算量隨 m 的增長呈平方級增加(時間復雜度 O (n2))。當 n 達到數千(如長文本生成),這種重復計算會讓推理速度變得極慢。KV 緩存(Key-Value Caching)正是為解決這一問題而生 —— 通過 “緩存” 歷史計算的 K 和 V,避免重復計算,將推理效率提升數倍,成為 LLMs 實現實時交互的核心技術之一。

二、注意力機制:KV 緩存優化的 “靶心”

要理解 KV 緩存的作用,需先明確注意力機制的計算邏輯。在 Transformer 架構中,注意力機制的核心公式為:

\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

其中:

  • Q(查詢矩陣):維度為(n \times d_k),代表當前 token 對 “需要關注什么” 的查詢;
  • K(鍵矩陣):維度為(n \times d_k),代表歷史 token 的 “特征標識”;
  • V(值矩陣):維度為(n \times d_v),代表歷史 token 的 “特征值”(通常d_v = d_k);
  • d_k是Q和K的維度(由模型維度d_{\text{model}}和注意力頭數決定,如d_k = \frac{d_{\text{model}}}{\text{num\_heads}});
  • QK^T會生成一個(n \times n)的注意力分數矩陣,描述每個 token 與其他所有 token 的關聯強度;
  • 經過 softmax 歸一化后與V相乘,最終得到每個 token 的注意力輸出(維度(n \times d_v))。

三、KV 緩存的核心原理:“記住” 歷史,避免重復計算

自回歸生成的痛點在于:每輪生成新 token 時,歷史 token 的 K 和 V 會被重復計算。例如:

  • 生成第 3 個 token 時,輸入序列是[t_1, t_2],已計算過t_1t_2K_1, K_2V_1, V_2
  • 生成第 4 個 token 時,輸入序列變為[t_1, t_2, t_3],若不優化,模型會重新計算t_1, t_2, t_3的K和V—— 其中t_1, t_2的K、V與上一輪完全相同,屬于無效重復。

KV 緩存的解決方案極其直接:

  1. 緩存歷史 K 和 V:每生成一個新 token 后,將其K和V存入緩存,與歷史緩存的K、V拼接;
  2. 僅計算新 token 的 K 和 V:下一輪生成時,無需重新計算所有 token 的K、V,只需為新 token 計算K_{\text{new}}V_{\text{new}},再與緩存拼接,直接用于注意力計算。

這一過程將每輪迭代的計算量從 “重新計算 n 個 token 的 K、V” 減少到 “計算 1 個新 token 的 K、V”,時間復雜度從O(n2)優化為接近O(n),尤其在生成長文本時,效率提升會非常顯著。

四、代碼實現:從 “無緩存” 到 “有緩存” 的對比

以下用 PyTorch 代碼模擬單頭注意力機制,直觀展示 KV 緩存的作用(假設模型維度d_{\text{model}}=64d_k=64):

import torch
import torch.nn.functional as F# 1. 定義基礎參數與注意力函數
d_model = 64  # 模型維度
d_k = d_model  # 單頭注意力中Q、K的維度
batch_size = 1  # 批量大小def scaled_dot_product_attention(Q, K, V):"""計算縮放點積注意力"""# 步驟1:計算注意力分數 (n×d_k) @ (d_k×n) → (n×n)scores = torch.matmul(Q, K.transpose(-2, -1))  # 轉置K的最后兩維,實現矩陣乘法scores = scores / torch.sqrt(torch.tensor(d_k, dtype=torch.float32))  # 縮放# 步驟2:softmax歸一化,得到注意力權重 (n×n)attn_weights = F.softmax(scores, dim=-1)  # 沿最后一維歸一化# 步驟3:加權求和 (n×n) @ (n×d_k) → (n×d_k)output = torch.matmul(attn_weights, V)return output, attn_weights# 2. 模擬輸入數據:歷史序列與新token
# 歷史序列(已生成3個token)的嵌入向量:shape=(batch_size, seq_len, d_model)
prev_embeds = torch.randn(batch_size, 3, d_model)  # 1×3×64
# 新生成的第4個token的嵌入向量:shape=(1, 1, 64)
new_embed = torch.randn(batch_size, 1, d_model)# 3. 模型中用于計算K、V的權重矩陣(假設已訓練好)
Wk = torch.randn(d_model, d_k)  # 用于從嵌入向量映射到K:64×64
Wv = torch.randn(d_model, d_k)  # 用于從嵌入向量映射到V:64×64# 場景1:無KV緩存——重復計算所有token的K、V
full_embeds_no_cache = torch.cat([prev_embeds, new_embed], dim=1)  # 拼接為1×4×64
# 重新計算4個token的K和V(包含前3個的重復計算)
K_no_cache = torch.matmul(full_embeds_no_cache, Wk)  # 1×4×64(前3個與歷史重復)
V_no_cache = torch.matmul(full_embeds_no_cache, Wv)  # 1×4×64(前3個與歷史重復)
# 計算注意力(Q使用當前序列的嵌入向量,此處簡化為與K相同)
output_no_cache, _ = scaled_dot_product_attention(K_no_cache, K_no_cache, V_no_cache)# 場景2:有KV緩存——僅計算新token的K、V,復用歷史緩存
# 緩存前3個token的K、V(上一輪已計算,無需重復)
K_cache = torch.matmul(prev_embeds, Wk)  # 1×3×64(歷史緩存)
V_cache = torch.matmul(prev_embeds, Wv)  # 1×3×64(歷史緩存)# 僅計算新token的K、V
new_K = torch.matmul(new_embed, Wk)  # 1×1×64(新計算)
new_V = torch.matmul(new_embed, Wv)  # 1×1×64(新計算)# 拼接緩存與新K、V,得到完整的K、V矩陣(與無緩存時結果一致)
K_with_cache = torch.cat([K_cache, new_K], dim=1)  # 1×4×64
V_with_cache = torch.cat([V_cache, new_V], dim=1)  # 1×4×64# 計算注意力(結果與無緩存完全相同,但計算量減少)
output_with_cache, _ = scaled_dot_product_attention(K_with_cache, K_with_cache, V_with_cache)# 驗證:兩種方式的輸出是否一致(誤差在浮點精度范圍內)
print(torch.allclose(output_no_cache, output_with_cache, atol=1e-6))  # 輸出:True

代碼中,“有緩存” 模式通過復用前 3 個 token 的 K、V,僅計算新 token 的 K、V,就得到了與 “無緩存” 模式完全一致的結果,但計算量減少了 3/4(對于 4 個 token 的序列)。當序列長度增至 1000,這種優化會讓每輪迭代的計算量從 1000 次矩陣乘法減少到 1 次,效率提升極其顯著。

五、權衡:內存與性能的平衡

KV 緩存雖能提升速度,但需面對 “內存占用隨序列長度線性增長” 的問題:

  • 緩存的 K 和 V 矩陣維度為(n \times d_k),當序列長度 n 達到 10000,且d_k=64時,單頭注意力的緩存大小約為10000 \times 64 \times 2(K 和 V 各一份)=1.28 \times 10^6個參數,若模型有 12 個注意力頭,總緩存會增至約 150 萬參數,對顯存(尤其是 GPU)是不小的壓力。

為解決這一問題,實際應用中會采用以下優化策略:

  • 滑動窗口緩存:僅保留最近的k個 token 的 K、V(如 k=2048),超過長度則丟棄最早的緩存,適用于對長距離依賴要求不高的場景;
  • 動態緩存管理:根據輸入序列長度自動調整緩存策略,在短序列時全量緩存,長序列時啟用滑動窗口;
  • 量化緩存:將 K、V 從 32 位浮點(float32)量化為 16 位(float16)或 8 位(int8),以犧牲少量精度換取內存節省,目前主流 LLMs(如 GPT-3、LLaMA)均采用此方案。

六、實際應用:KV 緩存如何支撐 LLMs 的實時交互?

在實際部署中,KV 緩存是 LLMs 實現 “秒級響應” 的關鍵。例如:

  • 聊天機器人(如 ChatGPT)生成每句話時,通過 KV 緩存避免重復計算歷史對話的 K、V,讓長對話仍能保持流暢響應;
  • 代碼生成工具(如 GitHub Copilot)在補全長代碼時,緩存已輸入的代碼 token 的 K、V,確保補全速度與輸入長度無關;
  • 語音轉文本實時生成(如實時字幕)中,KV 緩存能讓模型隨語音輸入逐詞生成文本,延遲控制在數百毫秒內。

可以說,沒有 KV 緩存,當前 LLMs 的 “實時交互” 體驗幾乎無法實現 —— 它是平衡模型性能與推理效率的 “隱形支柱”。

總結

KV 緩存通過復用歷史 token 的 K 和 V 矩陣,從根本上解決了 LLMs 自回歸生成中的重復計算問題,將時間復雜度從O(n2)優化為接近O(n)。其核心邏輯簡單卻高效:“記住已經算過的,只算新的”。盡管需要在內存與性能間做權衡,但通過滑動窗口、量化等策略,KV 緩存已成為現代 LLMs 推理不可或缺的技術,支撐著從聊天機器人到代碼生成的各類實時交互場景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/92147.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/92147.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/92147.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

16.Home-懶加載指令優化

問題1:邏輯書寫位置不合理問題2:重復監聽問題已經加載完畢但是還在監聽

Day116 若依融合mqtt

MQTT 1.MQTT協議概述MQTT是一種基于發布/訂閱模式的輕量級消息傳輸協議,設計用于低帶寬、高延遲或不穩定的網絡環境,廣泛應用于物聯網領域1.1 MQTT協議的應用場景1.智能家居、車聯網、工業物聯網:MQTT可以用于連接各種家電設備和傳感器&#…

PyTorch + PaddlePaddle 語音識別

PyTorch PaddlePaddle 語音識別 目錄 概述環境配置基礎理論數據預處理模型架構設計完整實現案例模型訓練與評估推理與部署性能優化技巧總結 語音識別(ASR, Automatic Speech Recognition)是將音頻信號轉換為文本的技術。結合PyTorch和PaddlePaddle的…

施耐德 Easy Altivar ATV310 變頻器:高效電機控制的理想選擇(含快速調試步驟及常見故障代碼)

施耐德 Easy Altivar ATV310 變頻器:高效電機控制的理想選擇(含快速調試步驟)在工業自動化領域,變頻器作為電機控制的核心設備,其性能與可靠性直接影響整個生產系統的效率。施耐德電氣推出的 Easy Altivar ATV310 變頻…

搭建郵件服務器概述

一、電子郵件應用解析標準郵件服務器(qq郵箱):1)提供電子郵箱(lvbuqq.com)及存儲空間2)為客戶端向外發送郵件給其他郵箱(diaochan163.com)3)接收/投遞其他郵箱…

day28-NFS

1.每日復盤與今日內容1.1復盤Rsync:本地模式、遠程模式🍟🍟🍟🍟🍟、遠程守護模式🍟🍟🍟🍟🍟安裝、配置Rsync啟動、測試服務備份案例1.2今日內容NFS優缺點NFS服…

二叉搜索樹--通往高階數據結構的基石

目錄 前言: 1、二叉搜索樹的概念 2、二叉搜索樹性能分析 3、二叉搜索樹的實現 BinarySelectTree.h test.cpp 4、key 和 key / value( map 和 set 的鋪墊 ) 前言: 又回到數據結構了,這次我們將要學習一些復雜的…

Profinet轉Ethernet IP網關接入五軸車床上下料機械手控制系統的配置實例

本案例為西門子1200PLC借助PROFINET轉EtherNet/IP網關與搬運機器人進行連接的配置案例。所需設備包括:西門子1200PLC、Profinet轉EtherNet/IP網關以及發那科(Fanuc)機器人。開啟在工業自動化控制領域廣泛應用、功能強大且專業的西門子博圖配置…

專題二_滑動窗口_長度最小的子數組

引入:滑動窗口首先,這是滑動窗口的第一道題,所以簡短的說一下滑動窗口的思路:當我們題目要求找一個滿足要求的區間的時候,且這個區間的left和right指針,都只需要同向移動的時候,就可以使用滑動窗…

解鎖高效開發:AWS 前端 Web 與移動應用解決方案詳解

告別繁雜的部署與運維,AWS 讓前端開發者的精力真正聚焦于創造卓越用戶體驗。在當今快速迭代的數字環境中,Web 與移動應用已成為企業與用戶交互的核心。然而,前端開發者常常面臨諸多挑戰:用戶認證的復雜性、后端 API 的集成難題、跨…

北京JAVA基礎面試30天打卡04

1. 單例模式的實現方式及線程安全 單例模式(Singleton Pattern)確保一個類只有一個實例,并提供一個全局訪問點。以下是常見的單例模式實現方式,以及如何保證線程安全: 單例模式的實現方式餓漢式(Eager Init…

Redis 緩存三大核心問題:穿透、擊穿與雪崩的深度解析

引言在現代互聯網架構中,緩存是提升系統性能、降低數據庫壓力的核心手段之一。而 Redis 作為高性能的內存數據庫,憑借其豐富的數據結構、靈活的配置選項以及高效的網絡模型,已經成為緩存領域的首選工具。本文將從 Redis 的基本原理出發&#…

耘瞳科技國產化點云處理軟件,開啟智能化三維測量新時代

在現代工業制造領域,三維點云數據已成為推動生產效率提升、質量控制優化以及智能制造轉型的關鍵技術之一。三維點云數據能夠提供高精度的物體表面信息,廣泛應用于制造零件的質量檢測;通過點云數據與CAD模型的對比分析,可以快速檢測…

RabbitMQ面試精講 Day 8:死信隊列與延遲隊列實現

【RabbitMQ面試精講 Day 8】死信隊列與延遲隊列實現 文章標簽 RabbitMQ,消息隊列,死信隊列,延遲隊列,面試技巧,分布式系統 文章簡述 本文是"RabbitMQ面試精講"系列第8天,深入講解死信隊列與延遲隊列的實現原理與實戰應用。文章詳細解析死信隊列的觸發…

團結引擎 1.5.0 版本發布:Android App View 功能詳解

核心亮點 原生安卓應用支持 2D & 3D 雙形態呈現 編輯器全流程集成 靈活調控功能 多應用并行展示 智能座艙應用示例 快速入門指南 開發說明 功能支持 實驗性功能 資源鏈接 團結引擎 1.5.0 版本已于 4 月 14 日正式上線。本次更新中,車機版引入了一項突…

基于SpringBoot的OA辦公系統的設計與實現

文章目錄前言詳細視頻演示具體實現截圖后端框架SpringBoot持久層框架MyBaits成功系統案例:代碼參考數據庫源碼獲取前言 博主介紹:CSDN特邀作者、985高校計算機專業畢業、現任某互聯網大廠高級全棧開發工程師、Gitee/掘金/華為云/阿里云/GitHub等平臺持續輸出高質量…

知識隨記-----用 Qt 打造優雅的密碼輸入框:添加右側眼睛圖標切換顯示

Qt 技巧:通過 QLineEdit 右側眼睛圖標實現密碼可見性切換 文章目錄Qt 技巧:通過 QLineEdit 右側眼睛圖標實現密碼可見性切換概要整體架構流程技術名詞解釋技術細節實現效果展示概要 本文介紹如何使用 Qt 框架為 QLineEdit 控件添加一個右側的眼睛圖標&a…

Unity里的對象旋轉數值跳轉問題的原理與解決方案

文章目錄1. 問題描述2. 問題原因3. 解決方案3.1通過多個父子關系從而控制旋轉(推薦)3.2 使用四元數進行旋轉1. 問題描述 我們現在寫一個3D的Unity程序,我們現在設置了一個物體后,我們想旋轉使其改為我們想要的情況。但是我們如果…

為什么現代 C++ (C++11 及以后) 推薦使用 constexpr和模板 (Templates) 作為宏 (#define) 的替代品??

我們用現實世界的比喻來深入理解??為什么 C 中的宏 (#define) 要謹慎使用,以及為什么現代 C (C11 及以后) 推薦使用 constexpr 和模板 (Templates) 作為替代品。??🧩 ??核心問題:宏 (#define) 是文本替換??想象宏是一個 ??“無腦的…

PyCharm vs. VSCode 到底哪個更好用

在 Python 開發者中,關于 PyCharm 和 VSCode 的討論從未停止。一個是功能齊備的集成開發環境(IDE),另一個是輕快靈活的代碼編輯器。它們代表了兩種不同的開發哲學,選擇哪個,往往取決于你的項目需求、個人習…