Spaces:
Sleeping
Sleeping
Publish Cache Atlas static site
Browse files- .gitattributes +3 -0
- .gitignore +30 -0
- .vscode/extensions.json +4 -0
- .vscode/launch.json +11 -0
- README.md +26 -3
- animations/scenes/minicache_intro.py +159 -0
- astro.config.mjs +10 -0
- package-lock.json +0 -0
- package.json +23 -0
- public/favicon.ico +0 -0
- public/favicon.svg +9 -0
- public/media/minicache-depth-axis.mp4 +3 -0
- public/media/minicache-layer-merge.mp4 +3 -0
- public/media/minicache-retention.mp4 +3 -0
- research/FIRST_PAPER_DECISION.md +125 -0
- research/blog-patterns.md +63 -0
- src/components/CacheBudgetDemo.tsx +85 -0
- src/layouts/Layout.astro +287 -0
- src/pages/index.astro +126 -0
- src/pages/notes/index.astro +74 -0
- src/pages/notes/minicache-paper-notes.mdx +134 -0
- src/pages/notes/why-kv-cache-papers-matter.mdx +221 -0
- tsconfig.json +14 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
public/media/minicache-depth-axis.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
public/media/minicache-layer-merge.mp4 filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
public/media/minicache-retention.mp4 filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# build output
|
| 2 |
+
dist/
|
| 3 |
+
|
| 4 |
+
# generated types
|
| 5 |
+
.astro/
|
| 6 |
+
|
| 7 |
+
# dependencies
|
| 8 |
+
node_modules/
|
| 9 |
+
|
| 10 |
+
# logs
|
| 11 |
+
npm-debug.log*
|
| 12 |
+
yarn-debug.log*
|
| 13 |
+
yarn-error.log*
|
| 14 |
+
pnpm-debug.log*
|
| 15 |
+
|
| 16 |
+
# environment variables
|
| 17 |
+
.env
|
| 18 |
+
.env.production
|
| 19 |
+
|
| 20 |
+
# macOS-specific files
|
| 21 |
+
.DS_Store
|
| 22 |
+
__pycache__/
|
| 23 |
+
*.pyc
|
| 24 |
+
|
| 25 |
+
# jetbrains setting folder
|
| 26 |
+
.idea/
|
| 27 |
+
|
| 28 |
+
# internal planning notes
|
| 29 |
+
PROJECT_DIRECTION.md
|
| 30 |
+
research/
|
.vscode/extensions.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"recommendations": ["astro-build.astro-vscode"],
|
| 3 |
+
"unwantedRecommendations": []
|
| 4 |
+
}
|
.vscode/launch.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"version": "0.2.0",
|
| 3 |
+
"configurations": [
|
| 4 |
+
{
|
| 5 |
+
"command": "./node_modules/.bin/astro dev",
|
| 6 |
+
"name": "Development server",
|
| 7 |
+
"request": "launch",
|
| 8 |
+
"type": "node-terminal"
|
| 9 |
+
}
|
| 10 |
+
]
|
| 11 |
+
}
|
README.md
CHANGED
|
@@ -1,10 +1,33 @@
|
|
| 1 |
---
|
| 2 |
title: Cache Atlas
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
colorTo: indigo
|
| 6 |
sdk: static
|
|
|
|
|
|
|
| 7 |
pinned: false
|
|
|
|
| 8 |
---
|
| 9 |
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
title: Cache Atlas
|
| 3 |
+
emoji: 🧠
|
| 4 |
+
colorFrom: blue
|
| 5 |
colorTo: indigo
|
| 6 |
sdk: static
|
| 7 |
+
app_build_command: npm run build
|
| 8 |
+
app_file: dist/index.html
|
| 9 |
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
---
|
| 12 |
|
| 13 |
+
# Cache Atlas
|
| 14 |
+
|
| 15 |
+
Public notes and demos for learning modern inference systems by implementing the core pieces.
|
| 16 |
+
|
| 17 |
+
This repo holds:
|
| 18 |
+
|
| 19 |
+
- paper notes written as implementation writeups
|
| 20 |
+
- diagrams and Manim renders
|
| 21 |
+
- inline demos embedded in articles
|
| 22 |
+
- links to standalone implementation repos
|
| 23 |
+
- reproduction notes for the code paths I build
|
| 24 |
+
|
| 25 |
+
Current paper track:
|
| 26 |
+
|
| 27 |
+
1. <https://arxiv.org/abs/2405.14366> — MiniCache
|
| 28 |
+
2. <https://arxiv.org/abs/2412.03409> — PrefixKV
|
| 29 |
+
|
| 30 |
+
## Commands
|
| 31 |
+
|
| 32 |
+
- `npm run dev`
|
| 33 |
+
- `npm run build`
|
animations/scenes/minicache_intro.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from manim import *
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
config.background_color = BLACK
|
| 5 |
+
|
| 6 |
+
INK = "#E7EDF4"
|
| 7 |
+
MUTED = "#9AA6B2"
|
| 8 |
+
ACCENT = "#79D2FF"
|
| 9 |
+
GREEN = "#7DF0C8"
|
| 10 |
+
RED = "#FF8B84"
|
| 11 |
+
CARD = "#0B0E12"
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def box(width, height, stroke=INK, fill=CARD, opacity=1.0):
|
| 15 |
+
return RoundedRectangle(
|
| 16 |
+
width=width,
|
| 17 |
+
height=height,
|
| 18 |
+
corner_radius=0.08,
|
| 19 |
+
stroke_color=stroke,
|
| 20 |
+
stroke_width=2,
|
| 21 |
+
fill_color=fill,
|
| 22 |
+
fill_opacity=opacity,
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class MiniCacheDepthAxis(Scene):
|
| 27 |
+
def construct(self):
|
| 28 |
+
title = Text("KV cache papers attack different axes", color=INK, font_size=40)
|
| 29 |
+
title.to_edge(UP)
|
| 30 |
+
|
| 31 |
+
left_frame = box(4.8, 3.8, stroke=ACCENT)
|
| 32 |
+
right_frame = box(4.8, 3.8, stroke=GREEN)
|
| 33 |
+
frames = VGroup(left_frame, right_frame).arrange(RIGHT, buff=0.5).shift(DOWN * 0.15)
|
| 34 |
+
|
| 35 |
+
left_title = Text("token-axis", color=ACCENT, font_size=26).next_to(left_frame, UP, buff=0.18)
|
| 36 |
+
right_title = Text("depth-axis", color=GREEN, font_size=26).next_to(right_frame, UP, buff=0.18)
|
| 37 |
+
|
| 38 |
+
token_grid = VGroup()
|
| 39 |
+
for _ in range(5):
|
| 40 |
+
row = VGroup(*[Square(side_length=0.38, stroke_color=ACCENT, fill_color=ACCENT, fill_opacity=0.08) for _ in range(7)])
|
| 41 |
+
row.arrange(RIGHT, buff=0.04)
|
| 42 |
+
token_grid.add(row)
|
| 43 |
+
token_grid.arrange(DOWN, buff=0.06).move_to(left_frame)
|
| 44 |
+
|
| 45 |
+
keep = SurroundingRectangle(VGroup(token_grid[0], token_grid[1], token_grid[2]), color=ACCENT, buff=0.08)
|
| 46 |
+
drop = Cross(VGroup(token_grid[3], token_grid[4]), stroke_color=RED, stroke_width=4).scale(1.1)
|
| 47 |
+
|
| 48 |
+
layers = VGroup()
|
| 49 |
+
for idx in range(6):
|
| 50 |
+
rect = box(3.4, 0.38, stroke=GREEN, fill=GREEN, opacity=0.1)
|
| 51 |
+
rect.add(Text(f"layer {idx + 1}", color=INK, font_size=18).move_to(rect))
|
| 52 |
+
layers.add(rect)
|
| 53 |
+
layers.arrange(DOWN, buff=0.12).move_to(right_frame)
|
| 54 |
+
|
| 55 |
+
merge_a = SurroundingRectangle(VGroup(layers[2], layers[3]), color=GREEN, buff=0.08)
|
| 56 |
+
merge_b = SurroundingRectangle(VGroup(layers[4], layers[5]), color=GREEN, buff=0.08)
|
| 57 |
+
arrow = Arrow(LEFT * 0.9, RIGHT * 0.9, color=GREEN).move_to(right_frame.get_bottom() + UP * 0.38)
|
| 58 |
+
note = Text("MiniCache compresses across depth", color=MUTED, font_size=24).to_edge(DOWN)
|
| 59 |
+
|
| 60 |
+
self.play(Write(title))
|
| 61 |
+
self.play(FadeIn(frames), FadeIn(left_title), FadeIn(right_title))
|
| 62 |
+
self.play(LaggedStart(*[FadeIn(row, shift=UP * 0.08) for row in token_grid], lag_ratio=0.08))
|
| 63 |
+
self.play(Create(keep), Create(drop))
|
| 64 |
+
self.play(LaggedStart(*[FadeIn(layer, shift=RIGHT * 0.08) for layer in layers], lag_ratio=0.08))
|
| 65 |
+
self.play(Create(merge_a), Create(merge_b), GrowArrow(arrow))
|
| 66 |
+
self.play(FadeIn(note))
|
| 67 |
+
self.wait(1)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
class MiniCacheLayerMerge(Scene):
|
| 71 |
+
def construct(self):
|
| 72 |
+
title = Text("Middle and deep layers may be redundant", color=INK, font_size=40)
|
| 73 |
+
title.to_edge(UP)
|
| 74 |
+
|
| 75 |
+
layer_stack = VGroup()
|
| 76 |
+
colors = [ACCENT, ACCENT, GREEN, GREEN, GREEN, GREEN]
|
| 77 |
+
for idx, color in enumerate(colors):
|
| 78 |
+
rect = box(4.4, 0.46, stroke=color, fill=color, opacity=0.12)
|
| 79 |
+
rect.add(Text(f"layer {idx + 1}", color=INK, font_size=18).move_to(rect))
|
| 80 |
+
layer_stack.add(rect)
|
| 81 |
+
layer_stack.arrange(DOWN, buff=0.16).shift(LEFT * 1.7 + DOWN * 0.15)
|
| 82 |
+
|
| 83 |
+
similar_a = SurroundingRectangle(VGroup(layer_stack[2], layer_stack[3]), color=GREEN, buff=0.08)
|
| 84 |
+
similar_b = SurroundingRectangle(VGroup(layer_stack[4], layer_stack[5]), color=GREEN, buff=0.08)
|
| 85 |
+
|
| 86 |
+
compressed = VGroup()
|
| 87 |
+
for label in ["compressed pair", "compressed pair"]:
|
| 88 |
+
rect = box(2.8, 0.62, stroke=GREEN, fill=GREEN, opacity=0.12)
|
| 89 |
+
rect.add(Text(label, color=INK, font_size=18).move_to(rect))
|
| 90 |
+
compressed.add(rect)
|
| 91 |
+
compressed.arrange(DOWN, buff=0.36).shift(RIGHT * 2.4)
|
| 92 |
+
|
| 93 |
+
arrows = VGroup(
|
| 94 |
+
Arrow(similar_a.get_right(), compressed[0].get_left(), color=GREEN, buff=0.2),
|
| 95 |
+
Arrow(similar_b.get_right(), compressed[1].get_left(), color=GREEN, buff=0.2),
|
| 96 |
+
)
|
| 97 |
+
|
| 98 |
+
memory_before = Text("memory before", color=MUTED, font_size=20).next_to(layer_stack, DOWN, buff=0.28)
|
| 99 |
+
memory_after = Text("memory after", color=MUTED, font_size=20).next_to(compressed, DOWN, buff=0.28)
|
| 100 |
+
bars_before = VGroup(*[Rectangle(width=0.42, height=0.18, stroke_width=0, fill_color=ACCENT, fill_opacity=1) for _ in range(6)]).arrange(RIGHT, buff=0.06).next_to(memory_before, DOWN, buff=0.16)
|
| 101 |
+
bars_after = VGroup(*[Rectangle(width=0.42, height=0.18, stroke_width=0, fill_color=GREEN, fill_opacity=1) for _ in range(4)]).arrange(RIGHT, buff=0.06).next_to(memory_after, DOWN, buff=0.16)
|
| 102 |
+
|
| 103 |
+
note = Text("compress the cache without only dropping tokens", color=MUTED, font_size=24).to_edge(DOWN)
|
| 104 |
+
|
| 105 |
+
self.play(Write(title))
|
| 106 |
+
self.play(LaggedStart(*[FadeIn(layer, shift=UP * 0.08) for layer in layer_stack], lag_ratio=0.08))
|
| 107 |
+
self.play(Create(similar_a), Create(similar_b))
|
| 108 |
+
self.play(GrowArrow(arrows[0]), FadeIn(compressed[0]))
|
| 109 |
+
self.play(GrowArrow(arrows[1]), FadeIn(compressed[1]))
|
| 110 |
+
self.play(FadeIn(memory_before), FadeIn(bars_before))
|
| 111 |
+
self.play(FadeIn(memory_after), FadeIn(bars_after))
|
| 112 |
+
self.play(FadeIn(note))
|
| 113 |
+
self.wait(1)
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
class MiniCacheRetention(Scene):
|
| 117 |
+
def construct(self):
|
| 118 |
+
title = Text("Retention keeps the sharp mismatches", color=INK, font_size=40)
|
| 119 |
+
title.to_edge(UP)
|
| 120 |
+
|
| 121 |
+
tokens = VGroup()
|
| 122 |
+
fills = [GREEN, GREEN, GREEN, RED, GREEN, RED, GREEN, GREEN]
|
| 123 |
+
labels = ["0.98", "0.97", "0.99", "0.71", "0.96", "0.68", "0.98", "0.99"]
|
| 124 |
+
for fill, label in zip(fills, labels):
|
| 125 |
+
square = RoundedRectangle(
|
| 126 |
+
width=0.78,
|
| 127 |
+
height=0.78,
|
| 128 |
+
corner_radius=0.08,
|
| 129 |
+
stroke_color=fill,
|
| 130 |
+
stroke_width=2,
|
| 131 |
+
fill_color=fill,
|
| 132 |
+
fill_opacity=0.12,
|
| 133 |
+
)
|
| 134 |
+
number = Text(label, color=INK, font_size=18).move_to(square)
|
| 135 |
+
tokens.add(VGroup(square, number))
|
| 136 |
+
tokens.arrange(RIGHT, buff=0.14).shift(UP * 0.35)
|
| 137 |
+
|
| 138 |
+
caption = Text("cross-layer similarity per token", color=MUTED, font_size=24).next_to(tokens, UP, buff=0.24)
|
| 139 |
+
threshold = DashedLine(
|
| 140 |
+
start=tokens.get_left() + DOWN * 0.85,
|
| 141 |
+
end=tokens.get_right() + DOWN * 0.85,
|
| 142 |
+
color=MUTED,
|
| 143 |
+
dash_length=0.1,
|
| 144 |
+
)
|
| 145 |
+
threshold_label = Text("similar enough -> merge", color=GREEN, font_size=22).next_to(threshold, DOWN, buff=0.16)
|
| 146 |
+
|
| 147 |
+
kept = VGroup(
|
| 148 |
+
SurroundingRectangle(tokens[3], color=RED, buff=0.08),
|
| 149 |
+
SurroundingRectangle(tokens[5], color=RED, buff=0.08),
|
| 150 |
+
)
|
| 151 |
+
kept_label = Text("retain the unusually distinct pairs", color=RED, font_size=24).to_edge(DOWN)
|
| 152 |
+
|
| 153 |
+
self.play(Write(title))
|
| 154 |
+
self.play(FadeIn(caption))
|
| 155 |
+
self.play(LaggedStart(*[FadeIn(token, shift=UP * 0.08) for token in tokens], lag_ratio=0.08))
|
| 156 |
+
self.play(Create(threshold), FadeIn(threshold_label))
|
| 157 |
+
self.play(Create(kept[0]), Create(kept[1]))
|
| 158 |
+
self.play(FadeIn(kept_label))
|
| 159 |
+
self.wait(1)
|
astro.config.mjs
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// @ts-check
|
| 2 |
+
import { defineConfig } from 'astro/config';
|
| 3 |
+
|
| 4 |
+
import mdx from '@astrojs/mdx';
|
| 5 |
+
import react from '@astrojs/react';
|
| 6 |
+
|
| 7 |
+
// https://astro.build/config
|
| 8 |
+
export default defineConfig({
|
| 9 |
+
integrations: [mdx(), react()]
|
| 10 |
+
});
|
package-lock.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "cache-atlas",
|
| 3 |
+
"type": "module",
|
| 4 |
+
"version": "0.0.1",
|
| 5 |
+
"engines": {
|
| 6 |
+
"node": ">=22.12.0"
|
| 7 |
+
},
|
| 8 |
+
"scripts": {
|
| 9 |
+
"dev": "astro dev",
|
| 10 |
+
"build": "astro build",
|
| 11 |
+
"preview": "astro preview",
|
| 12 |
+
"astro": "astro"
|
| 13 |
+
},
|
| 14 |
+
"dependencies": {
|
| 15 |
+
"@astrojs/mdx": "^5.0.4",
|
| 16 |
+
"@astrojs/react": "^5.0.4",
|
| 17 |
+
"@types/react": "^19.2.14",
|
| 18 |
+
"@types/react-dom": "^19.2.3",
|
| 19 |
+
"astro": "^6.1.9",
|
| 20 |
+
"react": "^19.2.5",
|
| 21 |
+
"react-dom": "^19.2.5"
|
| 22 |
+
}
|
| 23 |
+
}
|
public/favicon.ico
ADDED
|
|
public/favicon.svg
ADDED
|
|
public/media/minicache-depth-axis.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:7ccd98f2c8dc35b850e72befd292cba69cb3a340345fbeb658e95dbb6bcda3fa
|
| 3 |
+
size 175526
|
public/media/minicache-layer-merge.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:730416da0386dc6627faea6fad19c81c314c717aaba29c4f424842499be22207
|
| 3 |
+
size 165670
|
public/media/minicache-retention.mp4
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:48d94ebcd3c115cd0e52e3408780f2b721b00cbc663bf4a6b0fdf960b7e489ba
|
| 3 |
+
size 131083
|
research/FIRST_PAPER_DECISION.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# First Paper Decision
|
| 2 |
+
|
| 3 |
+
## Decision
|
| 4 |
+
|
| 5 |
+
We should **write generally first, implement narrowly first**.
|
| 6 |
+
|
| 7 |
+
That means:
|
| 8 |
+
|
| 9 |
+
## First post
|
| 10 |
+
|
| 11 |
+
**Why KV cache papers matter**
|
| 12 |
+
|
| 13 |
+
This is the right first post because it does three things:
|
| 14 |
+
|
| 15 |
+
1. explains the space before we commit to one paper
|
| 16 |
+
2. gives us a reusable framing for later posts
|
| 17 |
+
3. supports the first interactive demo naturally
|
| 18 |
+
|
| 19 |
+
It should answer:
|
| 20 |
+
|
| 21 |
+
- what the KV cache is
|
| 22 |
+
- why decode becomes memory-bound
|
| 23 |
+
- why people keep proposing compression / eviction / budget allocation
|
| 24 |
+
- why this repo is focusing on cache-efficiency papers
|
| 25 |
+
|
| 26 |
+
## First implementation
|
| 27 |
+
|
| 28 |
+
**MiniCache**
|
| 29 |
+
|
| 30 |
+
## Why MiniCache first
|
| 31 |
+
|
| 32 |
+
MiniCache is not the flashiest option, but it is the best first implementation target.
|
| 33 |
+
|
| 34 |
+
Reasons:
|
| 35 |
+
|
| 36 |
+
1. **Cleaner scope**
|
| 37 |
+
- training-free
|
| 38 |
+
- no heavy VLM integration needed on day one
|
| 39 |
+
- easier to isolate the core method
|
| 40 |
+
|
| 41 |
+
2. **Better odds of shipping**
|
| 42 |
+
- more self-contained than PrefixKV
|
| 43 |
+
- less adapter pain
|
| 44 |
+
- easier to make a concise repo that feels complete
|
| 45 |
+
|
| 46 |
+
3. **Good visuals anyway**
|
| 47 |
+
- cross-layer redundancy
|
| 48 |
+
- kept vs compressed cache state
|
| 49 |
+
- depth-wise compression
|
| 50 |
+
- memory / quality tradeoffs
|
| 51 |
+
|
| 52 |
+
4. **Sets up the rest of the series**
|
| 53 |
+
- once we have one clean cache-efficiency implementation, later papers like PrefixKV and CAKE become easier to explain
|
| 54 |
+
|
| 55 |
+
## Why not PrefixKV first
|
| 56 |
+
|
| 57 |
+
PrefixKV is still a strong paper.
|
| 58 |
+
|
| 59 |
+
But it is better as the **second** project, not the first.
|
| 60 |
+
|
| 61 |
+
Reasons:
|
| 62 |
+
|
| 63 |
+
- more adapter complexity
|
| 64 |
+
- more tied to vision-language model internals
|
| 65 |
+
- higher chance of getting stuck in model integration before the repo identity is established
|
| 66 |
+
|
| 67 |
+
PrefixKV is still the better paper if the top priority becomes:
|
| 68 |
+
|
| 69 |
+
- image-based demos
|
| 70 |
+
- VLM-specific cache allocation
|
| 71 |
+
- a stronger visual public artifact
|
| 72 |
+
|
| 73 |
+
But for the first clean implementation repo, MiniCache has better odds.
|
| 74 |
+
|
| 75 |
+
## Recommended sequence
|
| 76 |
+
|
| 77 |
+
### Step 1
|
| 78 |
+
|
| 79 |
+
Write:
|
| 80 |
+
|
| 81 |
+
- `Why KV cache papers matter`
|
| 82 |
+
|
| 83 |
+
### Step 2
|
| 84 |
+
|
| 85 |
+
Implement:
|
| 86 |
+
|
| 87 |
+
- `MiniCache`
|
| 88 |
+
|
| 89 |
+
### Step 3
|
| 90 |
+
|
| 91 |
+
Write:
|
| 92 |
+
|
| 93 |
+
- `MiniCache from first principles`
|
| 94 |
+
|
| 95 |
+
### Step 4
|
| 96 |
+
|
| 97 |
+
Then move to:
|
| 98 |
+
|
| 99 |
+
- `PrefixKV`
|
| 100 |
+
|
| 101 |
+
That gives the project both:
|
| 102 |
+
|
| 103 |
+
- one clean systems implementation first
|
| 104 |
+
- one more visual VLM-oriented paper second
|
| 105 |
+
|
| 106 |
+
## What to build with MiniCache
|
| 107 |
+
|
| 108 |
+
For the implementation repo:
|
| 109 |
+
|
| 110 |
+
- minimal standalone cache-compression module
|
| 111 |
+
- one benchmark script
|
| 112 |
+
- one toy memory simulator
|
| 113 |
+
- one clean README
|
| 114 |
+
|
| 115 |
+
For the blog:
|
| 116 |
+
|
| 117 |
+
- one diagram showing depth-wise redundancy
|
| 118 |
+
- one memory budget chart
|
| 119 |
+
- one inline demo showing how cache size changes under different compression settings
|
| 120 |
+
|
| 121 |
+
## Current call
|
| 122 |
+
|
| 123 |
+
If we start now, the best immediate move is:
|
| 124 |
+
|
| 125 |
+
> finish the first post and build MiniCache first
|
research/blog-patterns.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Blog and repo patterns
|
| 2 |
+
|
| 3 |
+
Internal note. This file is intentionally hidden from the public repo.
|
| 4 |
+
|
| 5 |
+
## References checked
|
| 6 |
+
|
| 7 |
+
- `mni-ml`
|
| 8 |
+
- Distill
|
| 9 |
+
- `lucidrains/x-transformers`
|
| 10 |
+
- `huggingface/ml-intern`
|
| 11 |
+
- Lil'Log
|
| 12 |
+
|
| 13 |
+
## What to borrow
|
| 14 |
+
|
| 15 |
+
### mni-ml
|
| 16 |
+
|
| 17 |
+
- extremely sparse home page
|
| 18 |
+
- curriculum / table-of-contents structure
|
| 19 |
+
- article-first navigation
|
| 20 |
+
- short explanatory paragraphs
|
| 21 |
+
- direct, not academic, tone
|
| 22 |
+
|
| 23 |
+
### Distill
|
| 24 |
+
|
| 25 |
+
- visuals do explanatory work, not decorative work
|
| 26 |
+
- interaction appears exactly where the reader needs it
|
| 27 |
+
- one section, one mental model
|
| 28 |
+
- explanations progress from intuition to mechanism
|
| 29 |
+
|
| 30 |
+
### lucidrains
|
| 31 |
+
|
| 32 |
+
- README is the product
|
| 33 |
+
- install and usage appear immediately
|
| 34 |
+
- small runnable examples beat long prose
|
| 35 |
+
- public package surface stays focused
|
| 36 |
+
|
| 37 |
+
### ml-intern
|
| 38 |
+
|
| 39 |
+
- repo structure is disciplined
|
| 40 |
+
- setup path is explicit
|
| 41 |
+
- use `uv` and make local development obvious
|
| 42 |
+
|
| 43 |
+
For this project, borrow the discipline, not the agent architecture.
|
| 44 |
+
|
| 45 |
+
### Lil'Log
|
| 46 |
+
|
| 47 |
+
- table of contents helps long posts
|
| 48 |
+
- strong use of sectioning and references
|
| 49 |
+
- good for survey-style notes
|
| 50 |
+
|
| 51 |
+
## Practical synthesis
|
| 52 |
+
|
| 53 |
+
### Hub repo
|
| 54 |
+
|
| 55 |
+
- `mni-ml` home page
|
| 56 |
+
- Distill-style inline demos
|
| 57 |
+
- concise system writing
|
| 58 |
+
|
| 59 |
+
### Implementation repos
|
| 60 |
+
|
| 61 |
+
- lucidrains-style README
|
| 62 |
+
- `ml-intern`-style setup discipline
|
| 63 |
+
- tight public API
|
src/components/CacheBudgetDemo.tsx
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { type CSSProperties, useMemo, useState } from "react";
|
| 2 |
+
|
| 3 |
+
export default function CacheBudgetDemo() {
|
| 4 |
+
const [layers, setLayers] = useState(24);
|
| 5 |
+
const [prefix, setPrefix] = useState(256);
|
| 6 |
+
const [tokenCost, setTokenCost] = useState(2.4);
|
| 7 |
+
|
| 8 |
+
const totalMb = useMemo(() => {
|
| 9 |
+
return (layers * prefix * tokenCost) / 1024;
|
| 10 |
+
}, [layers, prefix, tokenCost]);
|
| 11 |
+
|
| 12 |
+
return (
|
| 13 |
+
<div style={styles.card}>
|
| 14 |
+
<div style={styles.label}>inline demo</div>
|
| 15 |
+
<p style={styles.copy}>
|
| 16 |
+
Tiny proxy for why cache-budget papers exist at all. Push layer count, kept prefix length, or per-token memory cost,
|
| 17 |
+
and the memory bill climbs fast.
|
| 18 |
+
</p>
|
| 19 |
+
|
| 20 |
+
<div style={styles.grid}>
|
| 21 |
+
<label style={styles.control}>
|
| 22 |
+
<span>layers</span>
|
| 23 |
+
<strong>{layers}</strong>
|
| 24 |
+
<input type="range" min="8" max="48" step="4" value={layers} onChange={(e) => setLayers(Number(e.target.value))} />
|
| 25 |
+
</label>
|
| 26 |
+
<label style={styles.control}>
|
| 27 |
+
<span>kept prefix</span>
|
| 28 |
+
<strong>{prefix}</strong>
|
| 29 |
+
<input type="range" min="64" max="1024" step="64" value={prefix} onChange={(e) => setPrefix(Number(e.target.value))} />
|
| 30 |
+
</label>
|
| 31 |
+
<label style={styles.control}>
|
| 32 |
+
<span>mb / token / layer</span>
|
| 33 |
+
<strong>{tokenCost.toFixed(1)}</strong>
|
| 34 |
+
<input type="range" min="0.5" max="4" step="0.1" value={tokenCost} onChange={(e) => setTokenCost(Number(e.target.value))} />
|
| 35 |
+
</label>
|
| 36 |
+
</div>
|
| 37 |
+
|
| 38 |
+
<div style={styles.result}>
|
| 39 |
+
<span>estimated cache memory</span>
|
| 40 |
+
<strong>{totalMb.toFixed(1)} MB</strong>
|
| 41 |
+
</div>
|
| 42 |
+
</div>
|
| 43 |
+
);
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
const styles: Record<string, CSSProperties> = {
|
| 47 |
+
card: {
|
| 48 |
+
border: "1px solid rgba(231,237,244,0.14)",
|
| 49 |
+
background: "rgba(11,14,18,0.92)",
|
| 50 |
+
padding: "18px",
|
| 51 |
+
margin: "24px 0",
|
| 52 |
+
},
|
| 53 |
+
label: {
|
| 54 |
+
color: "#9aa6b2",
|
| 55 |
+
fontSize: "12px",
|
| 56 |
+
textTransform: "uppercase",
|
| 57 |
+
},
|
| 58 |
+
copy: {
|
| 59 |
+
color: "#9aa6b2",
|
| 60 |
+
lineHeight: 1.8,
|
| 61 |
+
},
|
| 62 |
+
grid: {
|
| 63 |
+
display: "grid",
|
| 64 |
+
gridTemplateColumns: "repeat(auto-fit, minmax(180px, 1fr))",
|
| 65 |
+
gap: "12px",
|
| 66 |
+
marginTop: "12px",
|
| 67 |
+
},
|
| 68 |
+
control: {
|
| 69 |
+
display: "grid",
|
| 70 |
+
gap: "8px",
|
| 71 |
+
border: "1px solid rgba(231,237,244,0.14)",
|
| 72 |
+
padding: "12px",
|
| 73 |
+
background: "rgba(8,10,12,0.92)",
|
| 74 |
+
color: "#e7edf4",
|
| 75 |
+
},
|
| 76 |
+
result: {
|
| 77 |
+
display: "grid",
|
| 78 |
+
gap: "6px",
|
| 79 |
+
marginTop: "14px",
|
| 80 |
+
padding: "12px",
|
| 81 |
+
border: "1px solid rgba(231,237,244,0.14)",
|
| 82 |
+
background: "rgba(8,10,12,0.92)",
|
| 83 |
+
color: "#e7edf4",
|
| 84 |
+
},
|
| 85 |
+
};
|
src/layouts/Layout.astro
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
const { title = "Cache Atlas" } = Astro.props;
|
| 3 |
+
const path = Astro.url.pathname;
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
<!doctype html>
|
| 7 |
+
<html lang="en">
|
| 8 |
+
<head>
|
| 9 |
+
<meta charset="UTF-8" />
|
| 10 |
+
<meta name="viewport" content="width=device-width" />
|
| 11 |
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
| 12 |
+
<link rel="icon" href="/favicon.ico" />
|
| 13 |
+
<meta name="generator" content={Astro.generator} />
|
| 14 |
+
<title>{title}</title>
|
| 15 |
+
</head>
|
| 16 |
+
<body>
|
| 17 |
+
<header class="site-header">
|
| 18 |
+
<div class="header-inner">
|
| 19 |
+
<a class="brand" href="/">Cache Atlas</a>
|
| 20 |
+
<nav>
|
| 21 |
+
<a class:list={{ active: path === "/" }} href="/">Home</a>
|
| 22 |
+
<a class:list={{ active: path.startsWith("/notes") }} href="/notes">Notes</a>
|
| 23 |
+
</nav>
|
| 24 |
+
</div>
|
| 25 |
+
</header>
|
| 26 |
+
<slot />
|
| 27 |
+
</body>
|
| 28 |
+
</html>
|
| 29 |
+
|
| 30 |
+
<style>
|
| 31 |
+
:root {
|
| 32 |
+
color-scheme: dark;
|
| 33 |
+
font-family: "IBM Plex Mono", "SF Mono", Menlo, monospace;
|
| 34 |
+
--bg: #000;
|
| 35 |
+
--ink: #e7edf4;
|
| 36 |
+
--muted: #9aa6b2;
|
| 37 |
+
--line: rgba(231, 237, 244, 0.14);
|
| 38 |
+
--card: rgba(11, 14, 18, 0.92);
|
| 39 |
+
--accent: #79d2ff;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
* {
|
| 43 |
+
box-sizing: border-box;
|
| 44 |
+
}
|
| 45 |
+
|
| 46 |
+
html,
|
| 47 |
+
body {
|
| 48 |
+
margin: 0;
|
| 49 |
+
width: 100%;
|
| 50 |
+
min-height: 100%;
|
| 51 |
+
background: var(--bg);
|
| 52 |
+
color: var(--ink);
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
a {
|
| 56 |
+
color: inherit;
|
| 57 |
+
text-decoration: none;
|
| 58 |
+
}
|
| 59 |
+
|
| 60 |
+
body {
|
| 61 |
+
font-size: 16px;
|
| 62 |
+
}
|
| 63 |
+
|
| 64 |
+
.site-header {
|
| 65 |
+
position: sticky;
|
| 66 |
+
top: 0;
|
| 67 |
+
z-index: 10;
|
| 68 |
+
border-bottom: 1px solid var(--line);
|
| 69 |
+
background: rgba(0, 0, 0, 0.9);
|
| 70 |
+
backdrop-filter: blur(14px);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
.header-inner {
|
| 74 |
+
display: flex;
|
| 75 |
+
align-items: center;
|
| 76 |
+
justify-content: space-between;
|
| 77 |
+
gap: 16px;
|
| 78 |
+
width: min(1040px, calc(100% - 32px));
|
| 79 |
+
margin: 0 auto;
|
| 80 |
+
padding: 18px 0;
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
.brand {
|
| 84 |
+
font-weight: 600;
|
| 85 |
+
letter-spacing: 0;
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
nav {
|
| 89 |
+
display: flex;
|
| 90 |
+
align-items: center;
|
| 91 |
+
gap: 14px;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
nav a {
|
| 95 |
+
color: var(--muted);
|
| 96 |
+
font-size: 12px;
|
| 97 |
+
text-transform: uppercase;
|
| 98 |
+
}
|
| 99 |
+
|
| 100 |
+
nav a.active,
|
| 101 |
+
nav a:hover {
|
| 102 |
+
color: var(--ink);
|
| 103 |
+
}
|
| 104 |
+
|
| 105 |
+
:global(main.page) {
|
| 106 |
+
width: min(980px, calc(100% - 32px));
|
| 107 |
+
margin: 0 auto;
|
| 108 |
+
padding: 48px 0 44px;
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
:global(main.article-shell) {
|
| 112 |
+
width: min(900px, calc(100% - 32px));
|
| 113 |
+
margin: 0 auto;
|
| 114 |
+
padding: 38px 0 42px;
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
:global(.eyebrow),
|
| 118 |
+
:global(.label) {
|
| 119 |
+
color: var(--muted);
|
| 120 |
+
font-size: 12px;
|
| 121 |
+
text-transform: uppercase;
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
:global(h1) {
|
| 125 |
+
margin: 12px 0 20px;
|
| 126 |
+
font-size: clamp(40px, 7vw, 82px);
|
| 127 |
+
line-height: 0.96;
|
| 128 |
+
font-weight: 600;
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
:global(.article-shell h1) {
|
| 132 |
+
max-width: 860px;
|
| 133 |
+
font-size: clamp(34px, 5vw, 62px);
|
| 134 |
+
}
|
| 135 |
+
|
| 136 |
+
:global(h2) {
|
| 137 |
+
margin: 40px 0 14px;
|
| 138 |
+
font-size: clamp(24px, 3vw, 38px);
|
| 139 |
+
line-height: 1.02;
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
:global(p),
|
| 143 |
+
:global(li) {
|
| 144 |
+
color: var(--muted);
|
| 145 |
+
line-height: 1.8;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
:global(.lede) {
|
| 149 |
+
max-width: 820px;
|
| 150 |
+
font-size: 19px;
|
| 151 |
+
color: var(--ink);
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
:global(blockquote) {
|
| 155 |
+
margin: 22px 0;
|
| 156 |
+
padding: 14px 18px;
|
| 157 |
+
border-left: 2px solid var(--accent);
|
| 158 |
+
background: rgba(11, 14, 18, 0.92);
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
:global(code) {
|
| 162 |
+
font-family: inherit;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
:global(pre) {
|
| 166 |
+
overflow-x: auto;
|
| 167 |
+
padding: 16px;
|
| 168 |
+
border: 1px solid var(--line);
|
| 169 |
+
background: var(--card);
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
:global(.note-card) {
|
| 173 |
+
margin: 22px 0;
|
| 174 |
+
padding: 18px;
|
| 175 |
+
border: 1px solid var(--line);
|
| 176 |
+
background: var(--card);
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
:global(.meta-grid) {
|
| 180 |
+
display: grid;
|
| 181 |
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
| 182 |
+
gap: 12px;
|
| 183 |
+
margin: 20px 0 26px;
|
| 184 |
+
}
|
| 185 |
+
|
| 186 |
+
:global(.meta-cell) {
|
| 187 |
+
padding: 14px;
|
| 188 |
+
border: 1px solid var(--line);
|
| 189 |
+
background: var(--card);
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
:global(.meta-cell strong) {
|
| 193 |
+
display: block;
|
| 194 |
+
margin-bottom: 6px;
|
| 195 |
+
font-size: 12px;
|
| 196 |
+
color: var(--muted);
|
| 197 |
+
text-transform: uppercase;
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
:global(.source-list),
|
| 201 |
+
:global(.bullet-list) {
|
| 202 |
+
padding-left: 18px;
|
| 203 |
+
}
|
| 204 |
+
|
| 205 |
+
:global(.source-list a),
|
| 206 |
+
:global(.inline-link) {
|
| 207 |
+
color: var(--accent);
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
:global(.category-list) {
|
| 211 |
+
display: grid;
|
| 212 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 213 |
+
gap: 12px;
|
| 214 |
+
margin: 14px 0 0;
|
| 215 |
+
padding: 0;
|
| 216 |
+
list-style: none;
|
| 217 |
+
}
|
| 218 |
+
|
| 219 |
+
:global(.category-list li) {
|
| 220 |
+
padding: 14px;
|
| 221 |
+
border: 1px solid var(--line);
|
| 222 |
+
background: var(--card);
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
:global(.category-list strong) {
|
| 226 |
+
display: block;
|
| 227 |
+
margin-bottom: 4px;
|
| 228 |
+
color: var(--ink);
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
:global(.article-nav) {
|
| 232 |
+
display: grid;
|
| 233 |
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
| 234 |
+
gap: 12px;
|
| 235 |
+
margin-top: 34px;
|
| 236 |
+
padding-top: 18px;
|
| 237 |
+
border-top: 1px solid var(--line);
|
| 238 |
+
}
|
| 239 |
+
|
| 240 |
+
:global(.article-nav a) {
|
| 241 |
+
display: block;
|
| 242 |
+
min-height: 86px;
|
| 243 |
+
padding: 14px;
|
| 244 |
+
border: 1px solid var(--line);
|
| 245 |
+
background: var(--card);
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
:global(.article-nav span) {
|
| 249 |
+
display: block;
|
| 250 |
+
margin-bottom: 6px;
|
| 251 |
+
color: var(--muted);
|
| 252 |
+
font-size: 12px;
|
| 253 |
+
text-transform: uppercase;
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
:global(.article-nav strong) {
|
| 257 |
+
color: var(--ink);
|
| 258 |
+
line-height: 1.35;
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
:global(.video-figure) {
|
| 262 |
+
margin: 24px 0;
|
| 263 |
+
}
|
| 264 |
+
|
| 265 |
+
:global(.video-figure video) {
|
| 266 |
+
display: block;
|
| 267 |
+
width: 100%;
|
| 268 |
+
border: 1px solid var(--line);
|
| 269 |
+
background: #050607;
|
| 270 |
+
}
|
| 271 |
+
|
| 272 |
+
:global(.video-figure figcaption) {
|
| 273 |
+
margin-top: 10px;
|
| 274 |
+
color: var(--muted);
|
| 275 |
+
}
|
| 276 |
+
|
| 277 |
+
@media (max-width: 860px) {
|
| 278 |
+
:global(.meta-grid) {
|
| 279 |
+
grid-template-columns: 1fr;
|
| 280 |
+
}
|
| 281 |
+
|
| 282 |
+
:global(.category-list),
|
| 283 |
+
:global(.article-nav) {
|
| 284 |
+
grid-template-columns: 1fr;
|
| 285 |
+
}
|
| 286 |
+
}
|
| 287 |
+
</style>
|
src/pages/index.astro
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
import Layout from "../layouts/Layout.astro";
|
| 3 |
+
---
|
| 4 |
+
|
| 5 |
+
<Layout title="Cache Atlas">
|
| 6 |
+
<main class="page">
|
| 7 |
+
<div class="eyebrow">research implementation lab</div>
|
| 8 |
+
<h1>KV-cache and inference papers, studied through code.</h1>
|
| 9 |
+
<p class="lede">
|
| 10 |
+
Cache Atlas is my public notebook for learning modern inference systems by implementing the core mechanics.
|
| 11 |
+
Each note explains what I read, what I built, and how to reproduce the experiment instead of treating the paper
|
| 12 |
+
as a black box.
|
| 13 |
+
</p>
|
| 14 |
+
|
| 15 |
+
<section class="toc">
|
| 16 |
+
<div class="label">notes</div>
|
| 17 |
+
<ol>
|
| 18 |
+
<li>
|
| 19 |
+
<a href="/notes/why-kv-cache-papers-matter">Why KV cache papers matter</a>
|
| 20 |
+
<p>A map of the memory problem that motivated the first implementation.</p>
|
| 21 |
+
</li>
|
| 22 |
+
<li>
|
| 23 |
+
<a href="/notes/minicache-paper-notes">MiniCache paper notes</a>
|
| 24 |
+
<p>Depth-axis compression, the implementation boundary, and the pieces I reproduced in PyTorch.</p>
|
| 25 |
+
</li>
|
| 26 |
+
</ol>
|
| 27 |
+
</section>
|
| 28 |
+
|
| 29 |
+
<section class="toc">
|
| 30 |
+
<div class="label">categories</div>
|
| 31 |
+
<ul class="category-list">
|
| 32 |
+
<li>
|
| 33 |
+
<strong>KV-cache memory</strong>
|
| 34 |
+
<p>Cache growth, compression axes, retention policies, and decode-time memory pressure.</p>
|
| 35 |
+
</li>
|
| 36 |
+
<li>
|
| 37 |
+
<strong>Paper reproductions</strong>
|
| 38 |
+
<p>Small implementation tracks that turn one paper mechanism into runnable code.</p>
|
| 39 |
+
</li>
|
| 40 |
+
<li>
|
| 41 |
+
<strong>Visual demos</strong>
|
| 42 |
+
<p>Animations and interactive components that make the systems behavior easier to inspect.</p>
|
| 43 |
+
</li>
|
| 44 |
+
<li>
|
| 45 |
+
<strong>Benchmarks</strong>
|
| 46 |
+
<p>Minimal scripts that measure the implemented path before scaling up the experiment.</p>
|
| 47 |
+
</li>
|
| 48 |
+
</ul>
|
| 49 |
+
</section>
|
| 50 |
+
|
| 51 |
+
<section class="toc">
|
| 52 |
+
<div class="label">repos</div>
|
| 53 |
+
<ul>
|
| 54 |
+
<li>
|
| 55 |
+
<a href="https://github.com/rishabhsai/minicache-pytorch" target="_blank" rel="noreferrer">minicache-pytorch</a>
|
| 56 |
+
<p>Standalone PyTorch package with clean-room primitives, tests, examples, and benchmark scripts.</p>
|
| 57 |
+
</li>
|
| 58 |
+
<li>
|
| 59 |
+
<strong>prefixkv-pytorch</strong>
|
| 60 |
+
<p>Planned next track for token and layer budget allocation in vision-language generation.</p>
|
| 61 |
+
</li>
|
| 62 |
+
</ul>
|
| 63 |
+
</section>
|
| 64 |
+
|
| 65 |
+
<section class="toc">
|
| 66 |
+
<div class="label">next note</div>
|
| 67 |
+
<p>
|
| 68 |
+
The next note should be a reproduction report for <strong>minicache-pytorch</strong>: the API, the tensor
|
| 69 |
+
tests, a small benchmark result, and the exact commands needed to reproduce the implementation locally.
|
| 70 |
+
</p>
|
| 71 |
+
</section>
|
| 72 |
+
</main>
|
| 73 |
+
</Layout>
|
| 74 |
+
|
| 75 |
+
<style>
|
| 76 |
+
h1 {
|
| 77 |
+
margin: 12px 0 20px;
|
| 78 |
+
max-width: 900px;
|
| 79 |
+
font-size: clamp(40px, 7vw, 82px);
|
| 80 |
+
line-height: 0.96;
|
| 81 |
+
font-weight: 600;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
.lede,
|
| 85 |
+
.card p {
|
| 86 |
+
color: var(--muted);
|
| 87 |
+
line-height: 1.8;
|
| 88 |
+
}
|
| 89 |
+
|
| 90 |
+
.lede {
|
| 91 |
+
max-width: 820px;
|
| 92 |
+
font-size: 19px;
|
| 93 |
+
color: var(--ink);
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
+
.toc {
|
| 97 |
+
margin-top: 28px;
|
| 98 |
+
padding-top: 18px;
|
| 99 |
+
border-top: 1px solid var(--line);
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
.toc ol,
|
| 103 |
+
.toc ul {
|
| 104 |
+
margin: 12px 0 0;
|
| 105 |
+
padding-left: 20px;
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
.toc li {
|
| 109 |
+
margin: 0 0 14px;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
.toc a,
|
| 113 |
+
.toc strong {
|
| 114 |
+
color: var(--ink);
|
| 115 |
+
}
|
| 116 |
+
|
| 117 |
+
.toc a {
|
| 118 |
+
text-decoration: underline;
|
| 119 |
+
text-decoration-color: rgba(121, 210, 255, 0.45);
|
| 120 |
+
text-underline-offset: 3px;
|
| 121 |
+
}
|
| 122 |
+
|
| 123 |
+
.toc p {
|
| 124 |
+
margin: 6px 0 0;
|
| 125 |
+
}
|
| 126 |
+
</style>
|
src/pages/notes/index.astro
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
import Layout from "../../layouts/Layout.astro";
|
| 3 |
+
---
|
| 4 |
+
|
| 5 |
+
<Layout title="Notes - Cache Atlas">
|
| 6 |
+
<main class="page">
|
| 7 |
+
<div class="eyebrow">notes</div>
|
| 8 |
+
<h1>Paper notes and implementation writeups.</h1>
|
| 9 |
+
<p class="lede">
|
| 10 |
+
These notes track my learning process in public: one mechanism at a time, with enough implementation detail,
|
| 11 |
+
visuals, and reproduction notes to make the code path inspectable.
|
| 12 |
+
</p>
|
| 13 |
+
|
| 14 |
+
<section class="toc">
|
| 15 |
+
<ol>
|
| 16 |
+
<li>
|
| 17 |
+
<a href="/notes/why-kv-cache-papers-matter">Why KV cache papers matter</a>
|
| 18 |
+
<p>The opening map of the memory problem behind modern inference serving.</p>
|
| 19 |
+
</li>
|
| 20 |
+
<li>
|
| 21 |
+
<a href="/notes/minicache-paper-notes">MiniCache paper notes</a>
|
| 22 |
+
<p>The first paper-specific implementation note, centered on <a href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">arXiv:2405.14366</a>.</p>
|
| 23 |
+
</li>
|
| 24 |
+
</ol>
|
| 25 |
+
</section>
|
| 26 |
+
|
| 27 |
+
<section class="toc">
|
| 28 |
+
<div class="label">categories</div>
|
| 29 |
+
<ul class="category-list">
|
| 30 |
+
<li>
|
| 31 |
+
<strong>KV-cache memory</strong>
|
| 32 |
+
<p>Cache footprint, decode bottlenecks, and compression strategies.</p>
|
| 33 |
+
</li>
|
| 34 |
+
<li>
|
| 35 |
+
<strong>Implementation notes</strong>
|
| 36 |
+
<p>Reproducible code paths with tests, examples, and benchmark commands.</p>
|
| 37 |
+
</li>
|
| 38 |
+
</ul>
|
| 39 |
+
</section>
|
| 40 |
+
|
| 41 |
+
<section class="toc">
|
| 42 |
+
<div class="label">next note</div>
|
| 43 |
+
<p>
|
| 44 |
+
Next up: a short reproduction report for <strong>minicache-pytorch</strong>, including the public API,
|
| 45 |
+
the current test coverage, and a first benchmark table.
|
| 46 |
+
</p>
|
| 47 |
+
</section>
|
| 48 |
+
</main>
|
| 49 |
+
</Layout>
|
| 50 |
+
|
| 51 |
+
<style>
|
| 52 |
+
.toc {
|
| 53 |
+
margin-top: 28px;
|
| 54 |
+
padding-top: 18px;
|
| 55 |
+
border-top: 1px solid var(--line);
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
.toc ol {
|
| 59 |
+
margin: 12px 0 0;
|
| 60 |
+
padding-left: 20px;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
.toc li {
|
| 64 |
+
margin: 0 0 14px;
|
| 65 |
+
}
|
| 66 |
+
|
| 67 |
+
.toc a {
|
| 68 |
+
color: var(--ink);
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
.toc p {
|
| 72 |
+
margin: 6px 0 0;
|
| 73 |
+
}
|
| 74 |
+
</style>
|
src/pages/notes/minicache-paper-notes.mdx
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
layout: ../../layouts/Layout.astro
|
| 3 |
+
title: MiniCache paper notes - Cache Atlas
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
<main class="article-shell">
|
| 7 |
+
|
| 8 |
+
<div class="eyebrow">note 02</div>
|
| 9 |
+
|
| 10 |
+
# MiniCache paper notes
|
| 11 |
+
|
| 12 |
+
The first implementation target is:
|
| 13 |
+
|
| 14 |
+
> <a class="inline-link" href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">MiniCache: KV Cache Compression in Depth Dimension for Large Language Models</a>
|
| 15 |
+
|
| 16 |
+
The paper is interesting for one simple reason: it attacks the cache along a less crowded axis.
|
| 17 |
+
|
| 18 |
+
Most cache papers make an argument about **which tokens** to keep. MiniCache instead starts from the observation that adjacent middle-to-deep layers can carry highly similar KV state, then asks whether that redundancy can be compressed directly.
|
| 19 |
+
|
| 20 |
+
<div class="meta-grid">
|
| 21 |
+
<div class="meta-cell">
|
| 22 |
+
<strong>arxiv</strong>
|
| 23 |
+
<a class="inline-link" href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">2405.14366</a>
|
| 24 |
+
</div>
|
| 25 |
+
<div class="meta-cell">
|
| 26 |
+
<strong>official project</strong>
|
| 27 |
+
<a class="inline-link" href="https://minicache.vmv.re/" target="_blank" rel="noreferrer">minicache.vmv.re</a>
|
| 28 |
+
</div>
|
| 29 |
+
<div class="meta-cell">
|
| 30 |
+
<strong>official repo</strong>
|
| 31 |
+
<a class="inline-link" href="https://github.com/AkideLiu/MiniCache" target="_blank" rel="noreferrer">AkideLiu/MiniCache</a>
|
| 32 |
+
</div>
|
| 33 |
+
</div>
|
| 34 |
+
|
| 35 |
+
## Paper snapshot
|
| 36 |
+
|
| 37 |
+
From the abstract, the public claim is:
|
| 38 |
+
|
| 39 |
+
- KV cache states show high similarity between adjacent layers in the middle-to-deep part of the network
|
| 40 |
+
- disentangling magnitude and direction makes merging easier
|
| 41 |
+
- a token retention strategy can avoid merging the most distinct pairs
|
| 42 |
+
- the method is training-free and complementary to quantization and sparsity
|
| 43 |
+
|
| 44 |
+
The specific abstract lines that matter for implementation are in the paper itself:
|
| 45 |
+
|
| 46 |
+
- <a class="inline-link" href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">arXiv:2405.14366</a>
|
| 47 |
+
|
| 48 |
+
For this reproduction, I am not rebuilding the entire official evaluation stack. I am isolating the core tensor behavior so the method is easy to read, test, and extend.
|
| 49 |
+
|
| 50 |
+
## What I implemented first
|
| 51 |
+
|
| 52 |
+
The first pass keeps the scope tight instead of recreating the full paper stack at once.
|
| 53 |
+
|
| 54 |
+
`minicache-pytorch` focuses on:
|
| 55 |
+
|
| 56 |
+
- magnitude / direction decomposition
|
| 57 |
+
- adjacent-layer direction interpolation
|
| 58 |
+
- reconstruction with preserved magnitude
|
| 59 |
+
- a simple token-retention primitive based on inter-layer similarity
|
| 60 |
+
- tight unit tests around those behaviors
|
| 61 |
+
- one benchmark script for the pairwise compression path
|
| 62 |
+
|
| 63 |
+
That is already enough to make the method inspectable.
|
| 64 |
+
|
| 65 |
+
<figure class="video-figure">
|
| 66 |
+
<video autoPlay loop muted playsInline controls preload="metadata">
|
| 67 |
+
<source src="/media/minicache-layer-merge.mp4" type="video/mp4" />
|
| 68 |
+
</video>
|
| 69 |
+
<figcaption>
|
| 70 |
+
The merge intuition: if nearby layers are partially redundant, the compression path can live between layers rather than only across tokens.
|
| 71 |
+
</figcaption>
|
| 72 |
+
</figure>
|
| 73 |
+
|
| 74 |
+
## What we are adding beyond the official repo
|
| 75 |
+
|
| 76 |
+
There is already an official MiniCache repo. That means the standalone implementation needs a different job.
|
| 77 |
+
|
| 78 |
+
The added value is:
|
| 79 |
+
|
| 80 |
+
- smaller surface area
|
| 81 |
+
- easier install and packaging
|
| 82 |
+
- a public API instead of only evaluation glue
|
| 83 |
+
- tests around the math primitives
|
| 84 |
+
- examples that fit in a README
|
| 85 |
+
- diagrams and animations that explain the method
|
| 86 |
+
|
| 87 |
+
That is the same pattern that makes a lot of lucidrains repos useful: not necessarily beating the official codebase, but turning an idea into something easier to inspect and reuse.
|
| 88 |
+
|
| 89 |
+
## Retention is where the method gets more interesting
|
| 90 |
+
|
| 91 |
+
The part that makes MiniCache feel less like “just average layers” is the retention step.
|
| 92 |
+
|
| 93 |
+
If two adjacent layers are already similar for a token, merging them should be cheap. If they diverge sharply for a token, blindly merging them is where quality loss is most likely to appear.
|
| 94 |
+
|
| 95 |
+
That makes the core retention primitive:
|
| 96 |
+
|
| 97 |
+
1. compute a similarity score between adjacent layer states
|
| 98 |
+
2. keep a mask for the highly distinct token positions
|
| 99 |
+
3. only merge the easy cases
|
| 100 |
+
|
| 101 |
+
That gives the implementation repo something concrete and testable to grow around.
|
| 102 |
+
|
| 103 |
+
<figure class="video-figure">
|
| 104 |
+
<video autoPlay loop muted playsInline controls preload="metadata">
|
| 105 |
+
<source src="/media/minicache-retention.mp4" type="video/mp4" />
|
| 106 |
+
</video>
|
| 107 |
+
<figcaption>
|
| 108 |
+
A simple retention picture: tokens with unusually low cross-layer similarity are kept out of the merge path.
|
| 109 |
+
</figcaption>
|
| 110 |
+
</figure>
|
| 111 |
+
|
| 112 |
+
## Sources
|
| 113 |
+
|
| 114 |
+
<ul class="source-list">
|
| 115 |
+
<li><a href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">MiniCache paper (arXiv:2405.14366)</a></li>
|
| 116 |
+
<li><a href="https://minicache.vmv.re/" target="_blank" rel="noreferrer">MiniCache project page</a></li>
|
| 117 |
+
<li><a href="https://github.com/AkideLiu/MiniCache" target="_blank" rel="noreferrer">Official MiniCache GitHub repo</a></li>
|
| 118 |
+
<li><a href="https://mni-ml.github.io/" target="_blank" rel="noreferrer">mni-ml</a></li>
|
| 119 |
+
<li><a href="https://distill.pub/2020/communicating-with-interactive-articles/" target="_blank" rel="noreferrer">Distill: Communicating with Interactive Articles</a></li>
|
| 120 |
+
<li><a href="https://github.com/lucidrains/x-transformers" target="_blank" rel="noreferrer">lucidrains/x-transformers</a></li>
|
| 121 |
+
</ul>
|
| 122 |
+
|
| 123 |
+
<nav class="article-nav" aria-label="Article navigation">
|
| 124 |
+
<a href="/notes/why-kv-cache-papers-matter">
|
| 125 |
+
<span>Previous</span>
|
| 126 |
+
<strong>Why KV cache papers matter</strong>
|
| 127 |
+
</a>
|
| 128 |
+
<a href="https://github.com/rishabhsai/minicache-pytorch" target="_blank" rel="noreferrer">
|
| 129 |
+
<span>Next</span>
|
| 130 |
+
<strong>Open minicache-pytorch</strong>
|
| 131 |
+
</a>
|
| 132 |
+
</nav>
|
| 133 |
+
|
| 134 |
+
</main>
|
src/pages/notes/why-kv-cache-papers-matter.mdx
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
layout: ../../layouts/Layout.astro
|
| 3 |
+
title: Why KV cache papers matter - Cache Atlas
|
| 4 |
+
---
|
| 5 |
+
|
| 6 |
+
import CacheBudgetDemo from "../../components/CacheBudgetDemo";
|
| 7 |
+
|
| 8 |
+
<main class="article-shell">
|
| 9 |
+
|
| 10 |
+
<div class="eyebrow">note 01</div>
|
| 11 |
+
|
| 12 |
+
# Why KV cache papers matter
|
| 13 |
+
|
| 14 |
+
The important shift is this:
|
| 15 |
+
|
| 16 |
+
> as context windows grow, cache memory becomes a product constraint, not just a systems detail
|
| 17 |
+
|
| 18 |
+
That is why the last stretch of serving papers keeps circling the same family of ideas:
|
| 19 |
+
|
| 20 |
+
- compress the cache
|
| 21 |
+
- evict part of the cache
|
| 22 |
+
- allocate the cache unevenly across layers
|
| 23 |
+
- specialize the policy for vision-language models
|
| 24 |
+
|
| 25 |
+
I started with this map because the individual papers make more sense once the cache itself is treated as a product constraint.
|
| 26 |
+
|
| 27 |
+
<div class="meta-grid">
|
| 28 |
+
<div class="meta-cell">
|
| 29 |
+
<strong>first implementation</strong>
|
| 30 |
+
MiniCache
|
| 31 |
+
</div>
|
| 32 |
+
<div class="meta-cell">
|
| 33 |
+
<strong>paper</strong>
|
| 34 |
+
<a class="inline-link" href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">arXiv:2405.14366</a>
|
| 35 |
+
</div>
|
| 36 |
+
<div class="meta-cell">
|
| 37 |
+
<strong>next note</strong>
|
| 38 |
+
<a class="inline-link" href="/notes/minicache-paper-notes">MiniCache paper notes</a>
|
| 39 |
+
</div>
|
| 40 |
+
</div>
|
| 41 |
+
|
| 42 |
+
<figure class="video-figure">
|
| 43 |
+
<video autoPlay loop muted playsInline controls preload="metadata">
|
| 44 |
+
<source src="/media/minicache-depth-axis.mp4" type="video/mp4" />
|
| 45 |
+
</video>
|
| 46 |
+
<figcaption>
|
| 47 |
+
One way to read the space: most cache work compresses or drops tokens along sequence length, while MiniCache asks what can be compressed across depth.
|
| 48 |
+
</figcaption>
|
| 49 |
+
</figure>
|
| 50 |
+
|
| 51 |
+
## The KV cache is not optional
|
| 52 |
+
|
| 53 |
+
Autoregressive decoding without a cache is the obvious baseline and the wrong product system.
|
| 54 |
+
|
| 55 |
+
Every generated token would force the model to recompute key and value state for the entire existing prefix. That makes decode cost grow with sequence length even when almost all of the old state is unchanged.
|
| 56 |
+
|
| 57 |
+
The cache fixes that by storing old key and value tensors so later decode steps mainly append new state instead of rebuilding the past. The result is the modern serving stack:
|
| 58 |
+
|
| 59 |
+
- prefill builds cache state from the prompt
|
| 60 |
+
- decode reuses that state one token at a time
|
| 61 |
+
|
| 62 |
+
The catch is that the cache itself gets expensive fast.
|
| 63 |
+
|
| 64 |
+
## Why the memory bill gets ugly
|
| 65 |
+
|
| 66 |
+
Cache size grows with several things at once:
|
| 67 |
+
|
| 68 |
+
- number of layers
|
| 69 |
+
- number of heads or KV groups
|
| 70 |
+
- hidden dimensions
|
| 71 |
+
- sequence length
|
| 72 |
+
- batch size
|
| 73 |
+
|
| 74 |
+
That is why serving teams keep running into the same practical problem:
|
| 75 |
+
|
| 76 |
+
> the model still fits, but throughput collapses because memory traffic and cache footprint dominate decode
|
| 77 |
+
|
| 78 |
+
This is also why there is not one single “KV cache paper.” There is a whole cluster of them.
|
| 79 |
+
|
| 80 |
+
## The main paper buckets
|
| 81 |
+
|
| 82 |
+
The easiest way to organize the space is by the axis they attack.
|
| 83 |
+
|
| 84 |
+
### 1. Token-axis compression and eviction
|
| 85 |
+
|
| 86 |
+
These papers ask:
|
| 87 |
+
|
| 88 |
+
> which old tokens are worth keeping?
|
| 89 |
+
|
| 90 |
+
Examples:
|
| 91 |
+
|
| 92 |
+
- <a class="inline-link" href="https://arxiv.org/abs/2412.03409" target="_blank" rel="noreferrer">PrefixKV</a>
|
| 93 |
+
- <a class="inline-link" href="https://arxiv.org/abs/2503.12491" target="_blank" rel="noreferrer">CAKE</a>
|
| 94 |
+
|
| 95 |
+
This is especially natural for long prompts and vision-language models, where different parts of the prefix are not equally valuable.
|
| 96 |
+
|
| 97 |
+
### 2. Depth-axis compression
|
| 98 |
+
|
| 99 |
+
These papers ask:
|
| 100 |
+
|
| 101 |
+
> how much redundancy exists across layers?
|
| 102 |
+
|
| 103 |
+
This is the lane that made MiniCache interesting enough to start with. Instead of only asking which tokens to keep, it asks whether nearby layers carry overlapping information that can be compressed more directly.
|
| 104 |
+
|
| 105 |
+
### 3. Architecture-specific cache policies
|
| 106 |
+
|
| 107 |
+
These papers ask:
|
| 108 |
+
|
| 109 |
+
> if the model is multimodal or has uneven layer behavior, should the cache budget be allocated differently?
|
| 110 |
+
|
| 111 |
+
That is why PrefixKV is compelling even though it is not my first implementation target. It sits right at the intersection of cache policy and vision-language generation.
|
| 112 |
+
|
| 113 |
+
## Why I started with MiniCache
|
| 114 |
+
|
| 115 |
+
MiniCache is a good first implementation target because the core mechanic can be isolated without reproducing an entire serving stack.
|
| 116 |
+
|
| 117 |
+
The paper:
|
| 118 |
+
|
| 119 |
+
- <a class="inline-link" href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">MiniCache: KV Cache Compression in Depth Dimension for Large Language Models</a>
|
| 120 |
+
|
| 121 |
+
Supporting links:
|
| 122 |
+
|
| 123 |
+
- <a class="inline-link" href="https://minicache.vmv.re/" target="_blank" rel="noreferrer">official project page</a>
|
| 124 |
+
- <a class="inline-link" href="https://github.com/AkideLiu/MiniCache" target="_blank" rel="noreferrer">official GitHub repo</a>
|
| 125 |
+
|
| 126 |
+
Why it works as a first reproduction:
|
| 127 |
+
|
| 128 |
+
- cleaner scope than PrefixKV
|
| 129 |
+
- does not require starting in VLM adapter hell
|
| 130 |
+
- easier to isolate the method itself
|
| 131 |
+
- still rich enough for diagrams, demos, and benchmarks
|
| 132 |
+
|
| 133 |
+
Tradeoffs:
|
| 134 |
+
|
| 135 |
+
- it is less visually flashy than PrefixKV
|
| 136 |
+
- it is not the strongest “image demo” paper
|
| 137 |
+
|
| 138 |
+
That tradeoff is acceptable for this project because the goal is to publish code that is readable, testable, and easy to extend.
|
| 139 |
+
|
| 140 |
+
<figure class="video-figure">
|
| 141 |
+
<video autoPlay loop muted playsInline controls preload="metadata">
|
| 142 |
+
<source src="/media/minicache-layer-merge.mp4" type="video/mp4" />
|
| 143 |
+
</video>
|
| 144 |
+
<figcaption>
|
| 145 |
+
The implementation intuition: if middle and deep layers are partially redundant, there is room to compress cache state across depth instead of only pruning tokens.
|
| 146 |
+
</figcaption>
|
| 147 |
+
</figure>
|
| 148 |
+
|
| 149 |
+
## What the public artifacts add
|
| 150 |
+
|
| 151 |
+
The explanation site and implementation package have different jobs.
|
| 152 |
+
|
| 153 |
+
### Hub repo: Cache Atlas
|
| 154 |
+
|
| 155 |
+
Cache Atlas adds:
|
| 156 |
+
|
| 157 |
+
- the explanation
|
| 158 |
+
- the diagrams
|
| 159 |
+
- the animation
|
| 160 |
+
- the interactive demo
|
| 161 |
+
- the paper comparison layer
|
| 162 |
+
|
| 163 |
+
### Standalone repo: minicache-pytorch
|
| 164 |
+
|
| 165 |
+
`minicache-pytorch` adds:
|
| 166 |
+
|
| 167 |
+
- a clean-room reference implementation
|
| 168 |
+
- a usable API
|
| 169 |
+
- tight tests
|
| 170 |
+
- benchmark scripts
|
| 171 |
+
- a README that reads like a good lucidrains repo, not like a paper appendix
|
| 172 |
+
- enough structure to grow cleanly, borrowing the packaging discipline of repos like `ml-intern` without copying its agent architecture
|
| 173 |
+
|
| 174 |
+
That split keeps the notes readable while keeping the package focused on code, tests, and reproduction.
|
| 175 |
+
|
| 176 |
+
## Example interactive demo
|
| 177 |
+
|
| 178 |
+
The first demo does not need to be perfect. It just needs to make the memory problem obvious.
|
| 179 |
+
|
| 180 |
+
<CacheBudgetDemo client:load />
|
| 181 |
+
|
| 182 |
+
## What comes after this
|
| 183 |
+
|
| 184 |
+
After MiniCache, the next paper track is PrefixKV.
|
| 185 |
+
|
| 186 |
+
That gives the overall project a clean progression:
|
| 187 |
+
|
| 188 |
+
1. general note on why cache papers matter
|
| 189 |
+
2. depth-axis compression with MiniCache
|
| 190 |
+
3. token / layer budget allocation with PrefixKV
|
| 191 |
+
|
| 192 |
+
That order gives the project both:
|
| 193 |
+
|
| 194 |
+
- a clean systems implementation first
|
| 195 |
+
- a more visual VLM-oriented paper second
|
| 196 |
+
|
| 197 |
+
## Sources
|
| 198 |
+
|
| 199 |
+
<ul class="source-list">
|
| 200 |
+
<li><a href="https://arxiv.org/abs/2405.14366" target="_blank" rel="noreferrer">MiniCache paper (arXiv:2405.14366)</a></li>
|
| 201 |
+
<li><a href="https://minicache.vmv.re/" target="_blank" rel="noreferrer">MiniCache project page</a></li>
|
| 202 |
+
<li><a href="https://github.com/AkideLiu/MiniCache" target="_blank" rel="noreferrer">MiniCache GitHub repo</a></li>
|
| 203 |
+
<li><a href="https://arxiv.org/abs/2412.03409" target="_blank" rel="noreferrer">PrefixKV paper (arXiv:2412.03409)</a></li>
|
| 204 |
+
<li><a href="https://arxiv.org/abs/2503.12491" target="_blank" rel="noreferrer">CAKE paper (arXiv:2503.12491)</a></li>
|
| 205 |
+
<li><a href="https://distill.pub/" target="_blank" rel="noreferrer">Distill</a> for article structure and visual explanation style</li>
|
| 206 |
+
<li><a href="https://mni-ml.github.io/articles/inference/" target="_blank" rel="noreferrer">mni-ml inference article</a> for compact systems writing</li>
|
| 207 |
+
<li><a href="https://github.com/lucidrains" target="_blank" rel="noreferrer">lucidrains GitHub profile</a> for implementation-repo discipline and README style</li>
|
| 208 |
+
</ul>
|
| 209 |
+
|
| 210 |
+
<nav class="article-nav" aria-label="Article navigation">
|
| 211 |
+
<a href="/notes">
|
| 212 |
+
<span>Previous</span>
|
| 213 |
+
<strong>All notes</strong>
|
| 214 |
+
</a>
|
| 215 |
+
<a href="/notes/minicache-paper-notes">
|
| 216 |
+
<span>Next</span>
|
| 217 |
+
<strong>MiniCache paper notes</strong>
|
| 218 |
+
</a>
|
| 219 |
+
</nav>
|
| 220 |
+
|
| 221 |
+
</main>
|
tsconfig.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"extends": "astro/tsconfigs/strict",
|
| 3 |
+
"include": [
|
| 4 |
+
".astro/types.d.ts",
|
| 5 |
+
"**/*"
|
| 6 |
+
],
|
| 7 |
+
"exclude": [
|
| 8 |
+
"dist"
|
| 9 |
+
],
|
| 10 |
+
"compilerOptions": {
|
| 11 |
+
"jsx": "react-jsx",
|
| 12 |
+
"jsxImportSource": "react"
|
| 13 |
+
}
|
| 14 |
+
}
|