本記事は DeepSeek-V2: A Strong, Economical, and Efficient Mixture-of-Experts Language Model (arXiv:2405.04434) の解説記事です。
論文概要(Abstract)
DeepSeek-V2は、236Bパラメータ(トークンあたり21Bアクティブ)のMixture-of-Experts(MoE)言語モデルである。著者らが提案するMulti-Head Latent Attention(MLA)は、KeyとValueを低ランクの潜在ベクトルに圧縮してキャッシュすることで、標準的なMHA(Multi-Head Attention)比で93.3%のKVキャッシュ削減を達成した。DeepSeek 67Bと比較して、学習コスト42.5%削減、推論スループット5.76倍を報告している。
この記事は Zenn記事: Attention機構の全史 Bahdanauから FlashAttention4・MLAまでの数学と実装 の深掘りです。
情報源
- arXiv ID: 2405.04434
- URL: https://arxiv.org/abs/2405.04434
- 著者: DeepSeek-AI(156名以上の共同研究チーム)
- 発表年: 2024年5月(最終改訂: 2024年6月)
- 分野: cs.CL, cs.AI, cs.LG
背景と動機(Background & Motivation)
LLMの推論において、KVキャッシュのメモリ消費は深刻なボトルネックとなっている。標準的なMHA(Multi-Head Attention)では、各トークンに対して全ヘッドのKey・Value対を保持する必要があり、モデルサイズとコンテキスト長に比例してメモリが増大する。
GQA(Grouped-Query Attention)はKVヘッド数を削減するアプローチだが、これは本質的に情報を「捨てる」操作である。ヘッド数を減らすほどKVキャッシュは小さくなるが、各ヘッドの表現力が制限される。
DeepSeek-V2の著者らは、情報を捨てるのではなく「圧縮して保持する」という異なるアプローチを提案した。低ランクの潜在ベクトルにKVを圧縮し、使用時に復元することで、品質劣化を最小限に抑えつつKVキャッシュを大幅に削減する。
主要な貢献(Key Contributions)
- 貢献1: Multi-Head Latent Attention(MLA)の提案。低ランクKV圧縮により、MHA比で93.3%のKVキャッシュ削減を達成
- 貢献2: DeepSeekMoEアーキテクチャの改良。236Bパラメータのうち21Bのみ活性化し、計算効率を大幅に向上
- 貢献3: 学習コスト42.5%削減と推論スループット5.76倍という、経済性と性能の両立
技術的詳細(Technical Details)
MLAの圧縮・復元メカニズム
MLAの核心は、KVの低ランク共同圧縮(low-rank joint compression)である。以下に数式の詳細を示す。
ステップ1: ダウンプロジェクション(圧縮)
入力の隠れ状態 $h_t \in \mathbb{R}^{d_{model}}$ を低次元の潜在ベクトル $c_t^{KV}$ に圧縮する。
\[c_t^{KV} = W^{DKV} h_t\]ここで、
- $h_t$: 第 $t$ トークンの隠れ状態(次元 $d_{model}$)
- $W^{DKV} \in \mathbb{R}^{d_c \times d_{model}}$: ダウンプロジェクション行列
- $c_t^{KV} \in \mathbb{R}^{d_c}$: 圧縮された潜在ベクトル(次元 $d_c$)
- $d_c \ll d_{model}$: 圧縮次元(DeepSeek-V2では $d_c = 512$、$d_{model} = 5120$)
KVキャッシュに保存するのは $c_t^{KV}$ のみである。これにより1トークンあたりのキャッシュサイズは $d_c = 512$ 次元に削減される。
ステップ2: アッププロジェクション(復元)
アテンション計算時に、潜在ベクトルからKey・Valueを復元する。
\[K_t = W^{UK} c_t^{KV}, \quad V_t = W^{UV} c_t^{KV}\]ここで、
- $W^{UK} \in \mathbb{R}^{(n_h \cdot d_k) \times d_c}$: Key用アッププロジェクション行列
- $W^{UV} \in \mathbb{R}^{(n_h \cdot d_v) \times d_c}$: Value用アッププロジェクション行列
- $n_h$: ヘッド数
ステップ3: Queryの圧縮(オプション)
MLAではQueryに対しても同様の圧縮を適用している。
\[c_t^Q = W^{DQ} h_t, \quad Q_t = W^{UQ} c_t^Q\]Query圧縮次元は $d_c’ = 1536$ に設定されている(論文Section 3.1より)。
Decoupled RoPE方式
RoPE(Rotary Position Embedding)との統合は、MLAの実装上の重要な課題である。RoPEは位置情報をKey・Queryに回転行列として適用するが、低ランク圧縮とRoPEを単純に組み合わせると、行列吸収テクニック(後述)が適用できなくなる。
著者らはDecoupled RoPE方式を提案し、位置依存成分と内容依存成分を分離する。
\[K_t = [K_t^{content}; K_t^{RoPE}], \quad K_t^{RoPE} = \text{RoPE}(W^{KR} h_t)\]$K_t^{RoPE}$ は別途計算されKVキャッシュに追加される(次元 $d_R$、論文では$d_R = 64$)。
行列吸収テクニック
推論時の計算効率を最大化するため、著者らは行列吸収(matrix absorption)テクニックを導入している。
通常のアテンション計算:
\[O = \text{softmax}\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V\]MLAの圧縮表現に展開すると:
\[Q K^\top = (W^{UQ} c^Q)(W^{UK} c^{KV})^\top = c^Q (W^{UQ})^\top W^{UK} c^{KV \top}\]ここで $\hat{W}^Q = (W^{UQ})^\top W^{UK}$ を事前計算しておくことで、推論時にはKVキャッシュの $c^{KV}$ のみを使って計算を完結できる。
MoE(Mixture-of-Experts)アーキテクチャ
DeepSeek-V2は、各Transformerブロックのフィードフォワード層にMoEを適用している。
- 全パラメータ数: 236B
- アクティブパラメータ数: 21B(トークンあたり)
- エキスパート数: 160(うち6をルーティングで活性化)
- 共有エキスパート: 2(全トークンで共有)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# MLA + MoEの概念的な実装構造
import torch
import torch.nn as nn
class MultiHeadLatentAttention(nn.Module):
def __init__(
self,
d_model: int = 5120,
n_heads: int = 128,
d_c: int = 512,
d_c_q: int = 1536,
d_rope: int = 64,
):
super().__init__()
self.d_k = d_model // n_heads
self.n_heads = n_heads
# ダウンプロジェクション(圧縮)
self.w_dkv = nn.Linear(d_model, d_c, bias=False)
self.w_dq = nn.Linear(d_model, d_c_q, bias=False)
# アッププロジェクション(復元)
self.w_uk = nn.Linear(d_c, n_heads * self.d_k, bias=False)
self.w_uv = nn.Linear(d_c, n_heads * self.d_k, bias=False)
self.w_uq = nn.Linear(d_c_q, n_heads * self.d_k, bias=False)
# Decoupled RoPE
self.w_kr = nn.Linear(d_model, d_rope, bias=False)
self.w_qr = nn.Linear(d_c_q, d_rope, bias=False)
def forward(
self,
h: torch.Tensor,
kv_cache: torch.Tensor | None = None,
) -> tuple[torch.Tensor, torch.Tensor]:
batch, seq_len, _ = h.shape
# 圧縮: h -> 潜在ベクトル
c_kv = self.w_dkv(h) # (B, T, d_c)
c_q = self.w_dq(h) # (B, T, d_c_q)
# 復元: 潜在ベクトル -> Q, K, V
q = self.w_uq(c_q) # (B, T, n_heads * d_k)
k = self.w_uk(c_kv) # (B, T, n_heads * d_k)
v = self.w_uv(c_kv) # (B, T, n_heads * d_k)
# KVキャッシュは c_kv のみ保存(93.3%削減の核心)
if kv_cache is not None:
c_kv = torch.cat([kv_cache, c_kv], dim=1)
k = self.w_uk(c_kv)
v = self.w_uv(c_kv)
# Scaled Dot-Product Attention
q = q.view(batch, -1, self.n_heads, self.d_k).transpose(1, 2)
k = k.view(batch, -1, self.n_heads, self.d_k).transpose(1, 2)
v = v.view(batch, -1, self.n_heads, self.d_k).transpose(1, 2)
scores = torch.matmul(q, k.transpose(-2, -1)) / (self.d_k ** 0.5)
attn = torch.softmax(scores, dim=-1)
output = torch.matmul(attn, v)
output = output.transpose(1, 2).contiguous().view(batch, seq_len, -1)
return output, c_kv # c_kv をKVキャッシュとして返す
実装のポイント(Implementation)
KVキャッシュの削減効果: DeepSeek-V2のMLA設定($d_c = 512$, $d_{model} = 5120$, $n_h = 128$, $d_k = 128$)では、1トークンあたりのKVキャッシュサイズは以下のように計算される。
- MHA: $2 \times n_h \times d_k = 2 \times 128 \times 128 = 32,768$ 要素
- MLA: $d_c + d_R = 512 + 64 = 576$ 要素
- 削減率: $1 - 576/32768 = 98.2\%$(論文では93.3%と報告。層ごとの設定の違いによる)
行列吸収の事前計算: 推論開始前に $\hat{W}^Q$ と $\hat{W}^V$ を事前計算しておくことが、推論レイテンシの最適化に重要である。
RoPE統合の注意点: Decoupled RoPEの $K_t^{RoPE}$ 成分は、潜在ベクトル $c_t^{KV}$ とは別にキャッシュする必要がある。この設計により、行列吸収テクニックとRoPEの位置エンコーディングを両立している。
Production Deployment Guide
AWS実装パターン(コスト最適化重視)
MLA搭載LLMの推論システムをAWSに構築する場合の構成を示す。
| 規模 | 月間リクエスト | 推奨構成 | 月額コスト概算 | 主要サービス |
|---|---|---|---|---|
| Small | ~3,000 (100/日) | API Gateway + Bedrock | $100-300 | Bedrock (Claude) + API Gateway |
| Medium | ~30,000 (1,000/日) | SageMaker Endpoint | $3,000-6,000 | SageMaker (g5.12xlarge) |
| Large | 300,000+ (10,000/日) | EKS + vLLM | $10,000-25,000 | EKS + p5 (H100) × 2-4 |
Small構成の詳細(月額$100-300):
- Amazon Bedrock: Claude/Llama系モデル利用(MLA相当の最適化はプロバイダ側で実施)
- API Gateway: RESTエンドポイント($5/月)
- DynamoDB: リクエストログ/キャッシュ($10/月)
Large構成の詳細(月額$10,000-25,000):
- EKS + p5.48xlarge(H100×8): vLLMでDeepSeek-V2をサーブ
- MLA対応のvLLM設定によりKVキャッシュメモリを大幅削減
- Karpenter: GPUノード自動スケーリング(Spot優先で最大70%削減)
コスト試算の注意事項: 上記は2026年4月時点のAWS東京リージョン料金に基づく概算値。GPU Spotの可用性により大幅に変動する。
Terraformインフラコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "mla-inference-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
enable_dns_hostnames = true
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "mla-inference"
cluster_version = "1.31"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
enable_cluster_creator_admin_permissions = true
}
resource "kubectl_manifest" "karpenter_gpu" {
yaml_body = <<-YAML
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-mla-inference
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["p5.48xlarge", "g5.48xlarge"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
limits:
nvidia.com/gpu: "16"
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 120s
YAML
}
運用・監視設定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import boto3
cloudwatch = boto3.client('cloudwatch')
# KVキャッシュメモリ使用率の監視
cloudwatch.put_metric_alarm(
AlarmName='kv-cache-memory-high',
ComparisonOperator='GreaterThanThreshold',
EvaluationPeriods=2,
MetricName='GPUMemoryUtilization',
Namespace='Custom/vLLM',
Period=300,
Statistic='Average',
Threshold=85.0,
AlarmDescription='GPU メモリ使用率85%超過: KVキャッシュ圧縮設定の確認を推奨'
)
コスト最適化チェックリスト
- MLA対応モデル使用(DeepSeek-V2/V3/R1)でKVキャッシュメモリ削減
- vLLMの
--kv-cache-dtype fp8でさらにKVキャッシュを圧縮 - GPU Spotインスタンス優先(最大70%削減)
- Karpenterでアイドル時ゼロスケール
- Continuous Batching有効化でスループット最大化
- プロンプトキャッシュでBedrock利用コスト削減
- AWS Budgets月額予算アラート設定
- CloudWatch GPU メモリ/使用率アラーム設定
- Cost Anomaly Detection有効化
- 開発環境のGPUインスタンス夜間停止
- Savings Plans(1年コミット)検討
実験結果(Results)
著者らが報告しているベンチマーク結果を以下にまとめる(論文Table 3, Table 8より)。
| ベンチマーク | DeepSeek 67B (MHA) | DeepSeek-V2 (MLA) | 備考 |
|---|---|---|---|
| MMLU | 71.3 | 78.5 | +7.2pt |
| GSM8K | 63.4 | 79.2 | +15.8pt |
| HumanEval | 73.8 | 81.1 | +7.3pt |
KVキャッシュ削減: 著者らは、MLAにより1トークンあたりのKVキャッシュサイズを標準MHAの1/11.9に削減したと報告している(93.3%削減)。
推論スループット: DeepSeek 67B比で5.76倍のスループット向上を達成(論文Section 5.2より)。
学習コスト: 8.1兆トークンの学習データで560万GPU時間。DeepSeek 67B比で42.5%のコスト削減(論文Section 4.1より)。
制約事項: MLAの低ランク圧縮は情報の損失を伴う可能性がある。著者らはベンチマークでMHAと同等以上の性能を示しているが、圧縮次元 $d_c$ の選択がモデル品質に影響するため、タスクに応じたチューニングが必要である。
実運用への応用(Practical Applications)
MLAの実運用上の最大の価値は、同一GPUメモリでより長いコンテキストを処理できる点にある。標準MHAで128Kトークンのコンテキストを処理する際にKVキャッシュだけで数十GBを消費するケースでも、MLAであれば数GBに収まる。
DeepSeek-V3(2024年12月)およびDeepSeek-R1(2025年1月)もMLAを採用しており、この手法は実運用で検証済みのアプローチである。vLLMやSGLangなどの推論フレームワークもMLA対応を進めている。
ただし、MLAの実装は標準MHAへのドロップイン置換が困難であり、Decoupled RoPEや行列吸収テクニックの正確な実装が求められる。既存モデルのファインチューニングでMLAを後付けすることは難しく、事前学習時からMLAを組み込む設計が必要である。
関連研究(Related Work)
- GQA (Grouped-Query Attention) (Ainslie et al., 2023): KVヘッド数を削減するアプローチ。MLAとは異なり「情報を捨てる」方式であり、品質と圧縮率のトレードオフがある
- MQA (Multi-Query Attention) (Shazeer, 2019): 全ヘッドでKVを共有。GQAの極端なケースに相当
- DeepSeek-V3 (DeepSeek-AI, 2024): MLAを継承しつつMoEの設計を改良。671Bパラメータ
まとめと今後の展望
DeepSeek-V2で提案されたMLAは、低ランク圧縮によるKVキャッシュ削減という新しいアプローチで、従来のGQA/MQAとは異なる設計思想を示した。93.3%のKVキャッシュ削減と同時にMHAと同等以上の性能を維持した点は注目に値する。
今後の方向性として、MLAとFlashAttentionの統合最適化、動的な圧縮率調整(タスク難易度に応じた$d_c$の適応的変更)、および他のアーキテクチャ(SSMハイブリッド等)との組み合わせが考えられる。
参考文献
- arXiv: https://arxiv.org/abs/2405.04434
- DeepSeek-V3: https://arxiv.org/abs/2412.19437
- Related Zenn article: https://zenn.dev/0h_n0/articles/b03b57bf327edf