Study · Model anatomy

RoPE: sixty-four dials on every attention head RoPE: 모든 attention head에 달린 64개의 다이얼

Rotary position embeddings never touch the values and never add anything to the residual stream — they spin each query/key channel pair by an angle proportional to the token's position, at d/2 geometrically spaced speeds. This page locates the exact insertion point in the attention path, hangs all 64 dials on one wall, composes per-band cosines into attention logits, and shows how PI, NTK-aware scaling, YaRN and base-scaling each edit the same dial ladder for long context — every number from the cited papers, official configs, or a worked example labeled as derived. Rotary position embedding은 value를 건드리지 않고 residual stream에 아무것도 더하지 않는다 — 각 query/key channel pair를 token position에 비례한 각도로, d/2개의 기하급수 간격 속도로 회전시킬 뿐이다. 이 페이지는 attention 경로에서 RoPE가 꽂히는 정확한 지점을 찾고, 64개의 다이얼을 한 벽에 걸고, band별 cosine이 attention logit으로 합성되는 과정을 본 뒤, PI·NTK-aware·YaRN· base-scaling이 같은 다이얼 사다리를 long context를 위해 어떻게 다르게 수정하는지 살핀다 — 모든 수치는 인용 논문·공식 config, 혹은 유도임을 표기한 계산에서 나온다.

Before you start. This page assumes you know how one attention layer works — queries, keys, values, softmax(qkᵀ)·V — and that decoders keep a KV cache during generation. If any of that is hazy, read the attention-head anatomy page first; the hybrid-attention page covers stacks where only some layers use this machinery. No prior exposure to position embeddings is needed — that story starts from zero in §1. 시작하기 전에. 이 페이지는 attention layer 하나의 동작 — query, key, value, softmax(qkᵀ)·V — 과 decoder가 생성 중 KV cache를 유지한다는 사실을 안다고 가정한다. 흐릿하다면 attention-head anatomy 페이지를 먼저 읽는 것이 좋다. 일부 layer만 이 기계를 쓰는 stack은 hybrid-attention 페이지가 다룬다. position embedding에 대한 사전 지식은 필요 없다 — 그 이야기는 §1에서 0부터 시작한다.
Verified references used on this page (papers / official config.json / library source): 이 페이지에서 사용하는 검증된 근거 (논문 / 공식 config.json / 라이브러리 소스): RoFormer — Eq. 14–16, 34 Qwen3-8B — θ 1,000,000 · head_dim 128 · full rotary Llama-3-8B — θ 500,000 YaRN — α = 1 · β = 32 Barbero et al. 2410.06205 — Gemma bands

§1 The itch — attention cannot see order 가려운 곳 — attention은 순서를 보지 못한다

An attention layer scores every pair of tokens with a dot product and takes a weighted average. Nothing in that recipe mentions where a token sits: shuffle the input and the outputs shuffle along with it, unchanged. To a bare attention layer, "the dog bit the man" and "the man bit the dog" are the same bag of tokens and produce the same pair-score table. Word order carries most of the meaning in language — a model that literally cannot see it cannot do the job. attention layer는 모든 token pair를 dot product로 점수 매기고 가중 평균을 낸다. 이 레시피 어디에도 token이 어디 있는지는 등장하지 않는다: 입력을 섞으면 출력도 그대로 따라 섞일 뿐이다. 맨몸의 attention layer에게 "개가 사람을 물었다"와 "사람이 개를 물었다"는 같은 token 주머니이고, 같은 pair-score 표를 만든다. 언어에서 의미의 대부분은 어순이 나른다 — 어순을 아예 보지 못하는 모델은 언어를 할 수 없다.

the dog bit the man the man bit the dog bare attention identical pair scores a dot product between two token vectors has no idea which one came first

The problem this whole page exists to solve: position must be injected into attention from outside. Every mainstream open-weight LLM today — Llama, Qwen, Gemma, DeepSeek — injects it with the same trick, rotary position embeddings, and the choice of how echoes everywhere: how far a model can read, and what its cached bytes physically contain. 이 페이지 전체가 풀려는 문제: position은 밖에서 attention에 주입되어야 한다. 오늘날 주류 open-weight LLM — Llama, Qwen, Gemma, DeepSeek — 은 전부 같은 트릭, rotary position embedding으로 주입하며, 그 주입 방식의 선택이 모든 곳에 메아리친다: 모델이 얼마나 멀리 읽을 수 있는지, cache된 byte에 물리적으로 무엇이 담기는지까지.

Order must be injected — but injected how, and where? 어순을 주입해야 한다 — 그런데 어떻게, 어디에 주입하나?

§2 Foundations — from added positions to rotated ones 기초 — 더하는 position에서 돌리는 position으로

The first fix is the obvious one: give every index its own vector. Learn a table of position embeddings, add entry m to the m-th token's embedding, done — GPT-2 worked this way, and the original Transformer's sinusoidal variant merely swaps the learned table for fixed waves. But adding cracks in two places. First, a learned table simply ends: a model trained with 2,048 rows has no row 2,049 — positions past the trained length do not exist. Second, and deeper: what language mostly needs is relative structure. "The adjective three tokens back" is the same relationship at index 10 and at index 1,847 — but an absolute code gives those two situations completely different position vectors, and the model must re-learn every relationship at every index it might occur. 첫 번째 해법은 뻔한 쪽이다: index마다 vector를 하나씩 준다. position embedding 표를 학습하고, m번째 token embedding에 m번째 행을 더하면 끝 — GPT-2가 이렇게 동작했고, 원조 Transformer의 sinusoidal 방식은 학습된 표를 고정된 파동으로 바꿨을 뿐이다. 그런데 "더하기"는 두 군데서 갈라진다. 첫째, 학습된 표는 그냥 끝난다: 2,048행으로 학습한 모델에 2,049번째 행은 없다 — 학습 길이 밖의 position은 존재하지 않는다. 둘째, 더 깊은 균열: 언어에 주로 필요한 것은 상대적 구조다. "세 token 앞의 형용사"는 index 10에서도 index 1,847에서도 같은 관계다 — 그러나 절대 좌표는 이 두 상황에 완전히 다른 position vector를 주고, 모델은 나타날 수 있는 모든 index에서 모든 관계를 다시 배워야 한다.

So state what we actually want: the attention logit between positions m and n should depend on n − m, not on m and n separately. Now the rotation idea has a reason to exist. Encode position not as something you add to the content vector but as an angle you turn it by. A rotation never changes a vector's length — the content is untouched — and the dot product of two rotated vectors depends only on the angle between them. Turn q by m·ω and k by n·ω, and their score can only see (n − m)·ω: relative position, by construction. That is the whole trick. RoFormer (2021) built it into transformers and named it RoPE. 그러니 원하는 것을 정확히 적자: position m과 n 사이의 attention logit이 m, n 각각이 아니라 n − m에 의존해야 한다. 이제 회전이라는 발상이 존재할 이유가 생긴다. position을 내용 vector에 더하는 무언가가 아니라, 내용을 돌리는 각도로 encode하는 것이다. 회전은 vector의 길이를 절대 바꾸지 않는다 — 내용은 손대지 않는다 — 그리고 회전된 두 vector의 dot product는 오직 둘 사이의 각도에만 의존한다. q를 m·ω만큼, k를 n·ω만큼 돌리면 score는 (n − m)·ω만 볼 수 있다: 구조적으로 상대 position이다. 트릭의 전부가 이것이다. RoFormer(2021)가 이를 transformer에 심고 RoPE라 이름 붙였다.

add: x + p_m x p_m x + p_m content and position blend into one vector — length changes rotate: R(mω)x x R(mω)x m·ω length preserved — position lives only in the angle

Adding mixes position into the content; rotating keeps them separable — the content is the length and direction pattern, the position is a phase on top. In a dot product between two rotated vectors the absolute phases cancel and only the difference survives. §4 shows this live and §9 checks it to machine precision. 더하기는 position을 내용에 섞어 버리지만, 돌리기는 둘을 분리 가능하게 유지한다 — 내용은 길이와 방향 패턴이고, position은 그 위의 위상이다. 회전된 두 vector의 dot product에서 절대 위상은 상쇄되고 차이만 살아남는다. §4가 이를 실시간으로 보여주고 §9가 machine precision까지 검산한다.

Takeaway핵심 한 줄 Position should enter attention as an angle, not as an added vector — because dot products see only differences of angles, which is exactly the relative structure language needs. position은 attention에 더해지는 vector가 아니라 각도로 들어가야 한다 — dot product는 각도의 차이만 보고, 그것이 정확히 언어에 필요한 상대 구조이기 때문이다.

Where exactly in a real model's forward pass does this rotation get applied — and to which tensors? 실제 모델의 forward pass에서 이 회전은 정확히 어디에, 어떤 tensor에 적용되나?

§3 a · Where the rotation lands — q and k only, after the projections a · 회전이 꽂히는 곳 — projection 뒤의 q와 k에만

§2 gave us the principle: position as an angle on q and k. But a principle is not an implementation — this section pins the rotation to its exact spot in a real model's forward pass, and shows which tensors it touches and, just as importantly, which it never does. §2에서 원리를 얻었다: q와 k 위의 각도로서의 position. 그러나 원리는 구현이 아니다 — 이 section은 실제 모델의 forward pass에서 회전이 꽂히는 정확한 지점을 못 박고, 회전이 만지는 tensor와 — 똑같이 중요하게 — 절대 만지지 않는 tensor를 보여준다.

One attention layer, Qwen3-accurate. Hover every box — the V path has the "why not v?" answer. RoFormer Eq. 14 defines RoPE as R(mθ)·W q — the rotation lands after the linear projections, and after QK-norm where the model has one. attention layer 하나를 Qwen3 기준으로 정확히 그렸다. 모든 box에 hover해 보라 — V 경로에 "왜 v는 아닌가?"의 답이 있다. RoFormer Eq. 14는 RoPE를 R(mθ)·W q로 정의한다: 회전은 linear projection 뒤, 그리고 QK-norm이 있는 모델에서는 그 뒤에 꽂힌다.

h_t — hidden per token W_q 32 h × 128 W_k 8 h × 128 W_v 8 h × 128 q_norm (RMS) Qwen3 · before RoPE k_norm (RMS) Qwen3 · before RoPE R(m) R(n) 64 blocks of 2×2 q — rotated used this step k — rotated → cache K cache stored post-RoPE V cache no RoPE — untouched v is never rotated — hover W_v for why q·kᵀ → softmax depends on n−m softmax · V → output cos/sin: computed once per forward (inv_freq ⊗ position_ids), broadcast to all heads and all layers — standard dense decoders (HF Qwen3; hybrid stacks and MLA differ, see fine print)

RoPE is a rewrite of q and k only — post-projection, post-QK-norm where one exists, applied with the same cos/sin table in every layer and every head of a standard dense decoder. V passes through untouched, and K enters the cache already rotated. Those two facts carry the whole systems story in section f. RoPE는 오직 q와 k만 다시 쓴다 — projection 뒤, QK-norm이 있으면 그 뒤에서, 표준 dense decoder의 모든 layer·모든 head에 같은 cos/sin 테이블로 적용된다. V는 그대로 통과하고, K는 이미 회전된 채 cache에 들어간다. 이 두 사실이 section f의 systems 이야기 전부를 떠받친다.

Note what the diagram does not contain: RoPE models add no position embedding anywhere. Position enters as a phase — block i of every head's q and k is spun by m·ωᵢ — and the only place that phase becomes observable is the q·k dot product, where R(m)ᵀR(n) collapses to R(n−m): rotations compose additively per 2D block, so the absolute angles cancel (RoFormer Eq. 16; section g checks it numerically). That is why the rotation must land on q and k after their projections and nowhere else: the score is the only bilinear meeting point, and v would just carry the spin into the output without creating any relative-position term. In Qwen3-class code the verified order is q_proj → q_norm → RoPE → cache update — QK-norm, where it exists, sits before the rotation. 다이어그램에 없는 것을 보라: RoPE 모델은 어디에도 position embedding을 더하지 않는다. position은 위상으로 들어온다 — 모든 head의 q와 k에서 block i가 m·ωᵢ만큼 돈다 — 그리고 그 위상이 관측 가능해지는 유일한 곳이 q·k dot product다. 2D block마다 회전이 덧셈으로 합성되어 R(m)ᵀR(n)이 R(n−m)으로 붕괴하고, 절대 각도는 상쇄된다 (RoFormer Eq. 16; section g에서 수치로 확인). 회전이 projection 뒤의 q와 k에만 꽂혀야 하는 이유가 이것이다: score가 유일한 bilinear 접점이고, v를 돌리면 상대-position 항은 생기지 않은 채 출력 내용만 돌아간다. Qwen3 계열 코드에서 검증된 순서는 q_proj → q_norm → RoPE → cache update — QK-norm이 있는 모델에서는 norm이 회전보다 먼저다.

Takeaway핵심 한 줄 RoPE rewrites only q and k — after the projections, after QK-norm where one exists. V is never rotated, and every cached K enters the cache already stamped with its write-time position. RoPE는 오직 q와 k만 다시 쓴다 — projection 뒤, QK-norm이 있으면 그 뒤에서. V는 절대 회전되지 않고, cache되는 모든 K는 쓰인 시점의 position이 새겨진 채 cache에 들어간다.

The diagram says R(m) as if it were one thing — what does a single 2×2 block of that rotation actually do as m and n move? 다이어그램은 R(m)을 하나의 덩어리처럼 그렸다 — 그 회전의 2×2 block 하나는 m과 n이 움직일 때 실제로 무엇을 하나?

§4 b · One pair = one dial — the 2×2 block, live b · pair 하나 = 다이얼 하나 — 2×2 block을 실시간으로

We now know where the rotation lands. But §2's central promise — that absolute positions cancel and only n − m survives — was stated, not seen. This section makes it tangible: one 2×2 block, two sliders, and the cancellation happening in front of you. 회전이 어디에 꽂히는지는 알았다. 그러나 §2의 핵심 약속 — 절대 position은 상쇄되고 n − m만 살아남는다 — 은 말로만 했지 아직 눈으로 보지 못했다. 이 section이 그것을 만질 수 있게 만든다: 2×2 block 하나, slider 두 개, 그리고 눈앞에서 일어나는 상쇄.

One (2i, 2i+1) channel pair from the d = 8 worked example (section g). Drag the position sliders: q spins with m, k with n — and the pair score only ever cares about n − m. Click "both +10" to watch both arrows move while the score stands still. d = 8 예제(section g)에서 (2i, 2i+1) channel pair 하나를 떼어 왔다. position slider를 움직여 보라: q는 m을 따라, k는 n을 따라 돌지만 pair score는 오직 n − m에만 반응한다. "both +10"을 누르면 두 화살표는 도는데 score는 멈춰 있는 것을 볼 수 있다.

m (query pos) 3
n (key pos) 7
R(m)q₍ᵢ₎ R(n)k₍ᵢ₎ angle 0 dashed = the pair before rotation (m = n = 0)
R(mω) — live 2×2 block, m = 3, ω = 1 ⎡ cos mω −sin mω ⎤ ⎡ −0.990 −0.141 ⎤ ⎣ sin mω cos mω ⎦ = ⎣ 0.141 −0.990 ⎦
mω = 3.000 rad nω = 7.000 rad Δ = n−m = 4 pair score = 0.7568

pair score = ⟨R(mω)q₍ᵢ₎, R(nω)k₍ᵢ₎⟩ = c·cos(Δω) − s·sin(Δω), where c is the 2D dot and s the 2D cross of the unrotated pair — a function of Δ = n−m only (RoFormer Eq. 16; derivation in section d). pair score = ⟨R(mω)q₍ᵢ₎, R(nω)k₍ᵢ₎⟩ = c·cos(Δω) − s·sin(Δω). c는 회전 전 pair의 2D dot, s는 2D cross — 오직 Δ = n−m만의 함수다 (RoFormer Eq. 16; 유도는 section d).

Pair 0 is the fastest dial: ω = 1 rad/token, so q at m = 3 sits at 3 rad and k at n = 7 at 7 rad. Slide either position and the score moves; shift both together and it does not — the absolute angles cancel inside the dot product, leaving only Δω. pair 0은 가장 빠른 다이얼이다: ω = 1 rad/token이므로 m = 3의 q는 3 rad, n = 7의 k는 7 rad에 있다. 한쪽 position만 움직이면 score가 변하지만, 둘을 같이 밀면 변하지 않는다 — 절대 각도는 dot product 안에서 상쇄되고 Δω만 남는다.

Which channels form a pair? Two conventions, one warning 어떤 channel끼리 pair인가? 두 가지 관례, 한 가지 경고

x₀x₁x₂x₃x₄x₅x₆x₇

Adjacent channels pair: (x₀,x₁)(x₂,x₃)(x₄,x₅)(x₆,x₇). Rotate-vector: (−x₁, x₀, −x₃, x₂, −x₅, x₄, −x₇, x₆) — RoFormer Eq. 34's element-wise form. 인접 channel끼리 pair: (x₀,x₁)(x₂,x₃)(x₄,x₅)(x₆,x₇). rotate-vector는 (−x₁, x₀, −x₃, x₂, −x₅, x₄, −x₇, x₆) — RoFormer Eq. 34의 element-wise 형태다.

x₀x₁x₂x₃x₄x₅x₆x₇

Channel j pairs with j + d/2: (x₀,x₄)(x₁,x₅)(x₂,x₆)(x₃,x₇). Rotate-vector: (−x₄, −x₅, −x₆, −x₇, x₀, x₁, x₂, x₃) — HF's rotate_half. channel j는 j + d/2와 pair: (x₀,x₄)(x₁,x₅)(x₂,x₆)(x₃,x₇). rotate-vector는 (−x₄, −x₅, −x₆, −x₇, x₀, x₁, x₂, x₃) — HF의 rotate_half다.

⚠ Checkpoints don't mix. Both layouts are valid RoPE up to a permutation of which W_q/W_k output channel meets which frequency — but a trained checkpoint has its rows ordered for exactly one of them. Apply the wrong one and every channel pair rotates at the wrong speed. Ground truth: HF's convert_llama_weights_to_hf.py permutes the q/k weights ("permute for sliced rotary") when converting Meta's interleaved checkpoint to the half-split layout, and vLLM exposes is_neox_style per model. (The permutation-equivalence reading is this page's derivation; the two code paths and the converter are verified sources.) ⚠ checkpoint는 섞이지 않는다. 두 배치 모두 "어느 W_q/W_k 출력 channel이 어느 frequency를 만나는가"의 순열 차이일 뿐 유효한 RoPE지만, 학습된 checkpoint의 행 순서는 정확히 한쪽에 맞춰져 있다. 반대쪽을 적용하면 모든 channel pair가 틀린 속도로 회전한다. 근거: HF의 convert_llama_weights_to_hf.py는 Meta의 interleaved checkpoint를 half-split 배치로 바꿀 때 q/k weight를 순열한다("permute for sliced rotary"). vLLM은 모델별로 is_neox_style을 노출한다. (순열-동치 해석은 이 페이지의 유도이고, 두 코드 경로와 변환기는 검증된 출처다.)

Takeaway핵심 한 줄 One channel pair is one dial turning at ω rad/token, and its score depends only on Δ = n − m — move both positions together and nothing changes. Which channels form a pair is a checkpoint-bound convention, not a free choice. channel pair 하나는 ω rad/token으로 도는 다이얼 하나이고, 그 score는 오직 Δ = n − m에만 의존한다 — 두 position을 같이 밀면 아무것도 변하지 않는다. 어떤 channel끼리 pair가 되는지는 checkpoint에 묶인 관례이지 자유로운 선택이 아니다.

A dial forgets after one wavelength — the four chips above already span λ 6.3 to 6,283 tokens. How does a real head's full set of dials divide up all the distances a context can contain? 다이얼은 wavelength 한 바퀴가 지나면 잊는다 — 위의 chip 네 개만 해도 λ 6.3에서 6,283 token까지 걸쳐 있다. 실제 head의 다이얼 전체는 context가 담을 수 있는 모든 거리를 어떻게 나눠 맡나?

§5 c · The dial wall — all 64 speeds at once c · 다이얼 벽 — 64개의 속도를 한눈에

One dial, one speed, one blind spot: it measures distance only modulo its wavelength. RoPE's answer is not a better dial but a ladder of them — 64 per head at head_dim 128, geometrically spaced so that every distance scale finds a dial moving at a useful rate. This is that ladder, on one wall. 다이얼 하나, 속도 하나, 맹점 하나: 거리는 자기 wavelength로 나눈 나머지로만 잰다. RoPE의 답은 더 좋은 다이얼이 아니라 다이얼의 사다리다 — head_dim 128이면 head당 64개, 어느 거리 규모든 쓸모 있는 속도로 도는 다이얼이 존재하도록 기하급수 간격으로 배치된다. 그 사다리를 벽 하나에 걸었다.

Every (2i, 2i+1) pair of a head_dim-128 head is a dial advancing ωᵢ = base^(−2i/128) rad per token — an odometer with geometrically geared hands. Drag the position: the fast dials whirl, the slow ones barely creep. The number under each dial is its wavelength in tokens, λᵢ = 2π/ωᵢ (YaRN Eq. 8). head_dim 128인 head의 (2i, 2i+1) pair 하나하나가 token당 ωᵢ = base^(−2i/128) rad씩 도는 다이얼이다 — 기하급수 기어비의 odometer. position을 끌어 보라: 빠른 다이얼은 팽팽 돌고 느린 다이얼은 거의 기지 않는다. 각 다이얼 아래 숫자는 token 단위 wavelength, λᵢ = 2π/ωᵢ다 (YaRN Eq. 8).

position m 64
base
dials 0–63 · ωᵢ = base^(−2i/128) rad/token · hand = current angle m·ωᵢ (mod 2π) · label = λᵢ in tokens 6.3 7.3 8.4 9.7 11.2 12.9 14.9 17.2 19.9 22.9 26.5 30.6 35.3 40.8 47.1 54.4 62.8 72.6 83.8 96.8 112 129 149 172 199 229 265 306 353 408 471 544 628 726 838 968 1.1K 1.3K 1.5K 1.7K 2K 2.3K 2.6K 3.1K 3.5K 4.1K 4.7K 5.4K 6.3K 7.3K 8.4K 9.7K 11.2K 12.9K 14.9K 17.2K 19.9K 22.9K 26.5K 30.6K 35.3K 40.8K 47.1K 54.4K
m = 64 dial 0: 10.2 full turns dial 63: 0.0074 rad — 0.12% of a turn λ₆₃ = 54,410 tokens
10 100 1K 10K 100K 1M trained ctx 2,048 (LLaMA-era) wavelength λ (tokens, log scale) — dials to the right of the context marker never complete one turn in training

Base 10,000 (RoFormer): the ladder runs from λ₀ = 2π ≈ 6.28 tokens to λ₆₃ = 2π·10000^(126/128) ≈ 54,410 tokens [computed; slightly below the 2π·base ≈ 62,832 approximation]. Dial 0 disambiguates neighbors; the last dials barely move inside any real context — near position-free channels. Switching the base stretches the whole wall at once: that is Llama-3's and Qwen3's train-time long-context route (section e). base 10,000 (RoFormer): 사다리는 λ₀ = 2π ≈ 6.28 token에서 λ₆₃ = 2π·10000^(126/128) ≈ 54,410 token까지 뻗는다 [계산값; 2π·base ≈ 62,832 근사보다 약간 작다]. 다이얼 0은 이웃 token을 구분하고, 마지막 다이얼들은 어떤 실제 context 안에서도 거의 움직이지 않는다 — 사실상 position-free channel이다. base를 바꾸면 벽 전체가 한 번에 늘어난다: 그것이 Llama-3와 Qwen3의 train-time long-context 경로다 (section e).

Takeaway핵심 한 줄 The ladder ωᵢ = base^(−2i/128) spans wavelengths from λ₀ = 2π ≈ 6.28 tokens to λ₆₃ ≈ 54,410 tokens at base 10,000 — and the base is the single knob that stretches the entire wall at once. 사다리 ωᵢ = base^(−2i/128)는 base 10,000에서 wavelength λ₀ = 2π ≈ 6.28 token부터 λ₆₃ ≈ 54,410 token까지 걸친다 — 그리고 base는 벽 전체를 한 번에 늘리는 단 하나의 손잡이다.

Each head carries 64 separate cosines. How do they add up into the one number attention actually uses — the logit? head 하나가 64개의 독립적인 cosine을 지닌다. 이들은 attention이 실제로 쓰는 단 하나의 숫자 — logit — 로 어떻게 합쳐지나?

§6 d · How the bands combine — the logit is a cosine series d · band는 어떻게 합쳐지는가 — logit은 cosine 급수다

We have the wall: 64 dials, each contributing its own cosine of Δωᵢ. But attention does not see 64 numbers — it sees their sum. What that sum can look like, and what trained models actually make it look like, is this section. 벽은 얻었다: 다이얼 64개가 각자 Δωᵢ의 cosine을 기여한다. 그러나 attention은 64개의 숫자를 보지 않는다 — 그 합을 본다. 그 합이 어떤 모양일 수 있고, 학습된 모델이 실제로 어떤 모양으로 만드는지가 이 section이다.

Writing q and k as d/2 two-dim sub-vectors, the attention logit at relative distance Δ is Σᵢ aᵢ·cos(Δωᵢ − φᵢ), where the per-band amplitude aᵢ = ‖q₍ᵢ₎‖·‖k₍ᵢ₎‖ is the product of sub-vector norms [derived on this page, numerically checked; consistent with RoFormer's complex form]. Set the four amplitudes of the d = 8 example (φᵢ = 0 here) and watch the score-vs-distance curve compose. q와 k를 d/2개의 2차원 sub-vector로 쪼개 쓰면, 상대 거리 Δ에서의 attention logit은 Σᵢ aᵢ·cos(Δωᵢ − φᵢ)가 된다. band별 amplitude aᵢ = ‖q₍ᵢ₎‖·‖k₍ᵢ₎‖는 sub-vector norm의 곱이다 [이 페이지의 유도, 수치 검증; RoFormer의 복소수 형태와 일치]. d = 8 예제의 amplitude 네 개를 조절하며 (여기서는 φᵢ = 0) score-vs-distance 곡선이 합성되는 것을 보라.

a₀ · ω=1 · λ 6.3 0.25
a₁ · ω=0.1 · λ 63 0.45
a₂ · ω=0.01 · λ 628 0.70
a₃ · ω=0.001 · λ 6.3K 1.00
+Σaᵢ 0 −Σaᵢ 020406080 relative distance Δ (tokens) thick = Σ (the logit) · thin = individual bands
peak at Δ=0: Σaᵢ = 2.40 fast band re-rings every 6.28 tokens

Low-frequency-heavy — the shape Barbero et al. actually measure in trained Gemma 7B: the largest norms sit on the lowest frequencies, producing a slowly-varying, nearly distance-agnostic envelope; the fast dials only add local texture. Try the other presets: high-freq weights carve a sharp Δ = 0 peak that re-rings every λ₀ = 6.3 tokens, and equal weights show pure interference — a decay-looking envelope with no band actually decaying. low-frequency 우세 — Barbero et al.이 학습된 Gemma 7B에서 실측한 바로 그 형태다: 가장 큰 norm이 가장 낮은 frequency에 실려, 거의 거리-불변인 느린 envelope을 만든다. 빠른 다이얼은 국소적인 결만 더한다. 다른 preset도 눌러 보라: high-freq 가중은 λ₀ = 6.3 token마다 다시 울리는 날카로운 Δ = 0 peak을 깎아 내고, equal 가중은 순수한 간섭을 보여준다 — 어느 band도 감쇠하지 않는데 감쇠처럼 보이는 envelope.

What trained models put on the bands — Barbero et al. (2410.06205) 학습된 모델은 band에 무엇을 싣는가 — Barbero et al. (2410.06205)

Observed: norms pile onto slow dials관측: norm은 느린 다이얼에 쌓인다

In pretrained Gemma 7B, training "has assigned much higher norm on average to the lowest frequencies" — which, by the cosine series above, means they "influence the dot product the most … at each layer"; the authors "suspect they are used to carry semantic information." High-frequency usage appears "especially at the very first and last layers." This is observational analysis of a trained model, not an intervention. pretrained Gemma 7B에서 학습은 "가장 낮은 frequency에 평균적으로 훨씬 높은 norm을 할당"했다 — 위 cosine 급수에 따르면 이는 매 layer에서 dot product에 가장 크게 기여한다는 뜻이고, 저자들은 이 band가 "semantic 정보를 나른다"고 본다. high-frequency 사용은 "특히 첫 layer와 마지막 layer에서" 나타난다. 학습된 모델에 대한 관측 분석이며 개입 실험이 아니다.

Gemma 7B · per-band 2-norm analysis

Observed: fast dials build positional heads관측: 빠른 다이얼은 positional head를 만든다

Gemma 7B "learns to use RoPE to construct robust 'positional' attention patterns by exploiting the highest frequencies": a diagonal head in the last layer (L27 H8, mostly high-frequency by their Fig. 6), a previous-token head in the first layer, and an apostrophe-detector head that is both semantic and positional. Theory to match: a RoPE head can express pure positional selection and diagonal/off-diagonal patterns (Prop. 3.1, Thm 5.3) where a NoPE head cannot (Prop. 5.2) — but with low-but-nonzero frequencies, a head eventually fails to attend robustly to a semantic target as context grows (Thm 6.1): slow-but-moving dials misalign, motivating huge bases or truncation. Gemma 7B는 "가장 높은 frequency를 이용해 견고한 'positional' attention 패턴을 구성하도록 학습"된다: 마지막 layer의 diagonal head(L27 H8, Fig. 6 기준 대부분 high-frequency), 첫 layer의 previous-token head, 그리고 semantic과 positional을 겸하는 apostrophe 검출 head. 이론도 맞물린다: RoPE head는 순수 positional 선택과 diagonal/off-diagonal 패턴을 표현할 수 있지만(Prop. 3.1, Thm 5.3) NoPE head는 불가능하다(Prop. 5.2). 다만 0이 아닌 낮은 frequency는 context가 커지면 semantic 표적에 견고하게 attend하지 못하게 된다(Thm 6.1) — 느리지만 도는 다이얼은 결국 어긋나고, 거대한 base 혹은 truncation의 동기가 된다.

Fig. 5–6 · Prop. 3.1 · Thm 5.3 / 6.1

Scope — read before the table: these are Gemma 2B models retrained from scratch on Wiki/FlanV2 with p-RoPE (keep fraction p of the frequencies, removing the lowest), NOT inference-time truncation of a pretrained model. The paper contains no pretrained-model truncation benchmark. 범위 — 표를 읽기 전에: 아래는 p-RoPE(frequency의 비율 p만 남기고 가장 낮은 쪽을 제거)로 Wiki/FlanV2에서 처음부터 재학습한 Gemma 2B들이다. pretrained 모델의 inference-time truncation이 아니며, 논문에는 그런 벤치마크가 없다.

variantvariant Wiki val ppl FlanV2 val ppl
NoPE4.85946.6429
RoPE · θ = 10k4.46276.4429
RoPE · θ = 500k4.44856.4593
0.75-RoPE (lowest 25% removed)4.44146.4422
0.75-RoPE · reversed4.45926.4683
0.75-RoPE · partial4.45376.4562
0.25-RoPE4.53026.5111

Table 2, Barbero et al.: "truncating the lowest frequencies not only maintains the same performance, but even seems to improve the validation perplexity" — 0.75-RoPE "outperforms simply increasing the wavelength (θ = 500k)"; the rationale is to give the model "robust semantic channels that are distance agnostic." 0.25-RoPE is too aggressive and degrades. (The reversed/partial variant definitions are the paper's labels, reported secondhand.) Barbero et al. Table 2: "가장 낮은 frequency를 잘라내도 성능이 유지될 뿐 아니라 validation perplexity가 오히려 좋아지는 것으로 보인다" — 0.75-RoPE는 "단순히 wavelength를 키우는 것(θ = 500k)보다 낫다". 논거는 모델에게 "거리에 불변인 견고한 semantic channel"을 주자는 것. 0.25-RoPE는 과도해서 성능이 떨어진다. (reversed/partial variant의 정의는 논문의 라벨을 간접 인용한 것이다.)

Read the panel and the Gemma findings together and a head's reach stops being mysterious. High-frequency bands buy sharp local structure — the diagonal and previous-token heads at the first and last layers; low-frequency bands act as nearly distance-agnostic content channels. And RoFormer's famous long-term decay curve should be read as an upper-bound envelope produced by many incommensurate cosines dephasing, not a per-pair guarantee — Barbero et al. explicitly argue decay is "unlikely to be the core reason" RoPE helps. panel과 Gemma 관측을 겹쳐 읽으면 head의 사정거리는 더 이상 신비롭지 않다. high-frequency band는 날카로운 국소 구조를 산다 — 첫·마지막 layer의 diagonal head와 previous-token head. low-frequency band는 거의 거리-불변인 내용 channel로 작동한다. 그리고 RoFormer의 유명한 long-term decay 곡선은 서로 공약수 없는 여러 cosine이 어긋나며 만드는 upper-bound envelope로 읽어야지 pair별 보장이 아니다 — Barbero et al.은 decay가 RoPE가 잘 작동하는 "핵심 이유일 가능성은 낮다"고 명시적으로 반박한다.

Takeaway핵심 한 줄 The attention logit at distance Δ is a cosine series Σᵢ aᵢ·cos(Δωᵢ − φᵢ) whose amplitudes aᵢ = ‖q₍ᵢ₎‖·‖k₍ᵢ₎‖ are chosen by training — and trained models pile the largest amplitudes onto the slowest dials. 거리 Δ에서의 attention logit은 cosine 급수 Σᵢ aᵢ·cos(Δωᵢ − φᵢ)이고, amplitude aᵢ = ‖q₍ᵢ₎‖·‖k₍ᵢ₎‖는 학습이 고른다 — 그리고 학습된 모델은 가장 큰 amplitude를 가장 느린 다이얼에 쌓는다.

Training chose those amplitudes for one context length. What happens when inference must run past it — can the dial speeds themselves be edited after training? 그 amplitude는 하나의 context 길이에 맞춰 학습됐다. inference가 그 길이를 넘어야 한다면 — 다이얼 속도 자체를 학습 후에 수정할 수 있나?

§7 e · Editing the bands — every long-context method on one axis e · band 수정하기 — 모든 long-context 기법을 한 축 위에

This is the hardest section on the page — take it slowly. Four methods with four papers' worth of notation (PI, NTK-aware, YaRN, base-scaling) collapse onto a single picture once you ask the right question: for each of the 64 dials, by what factor does this method multiply its speed? Hold onto that question and every formula below becomes a curve on one plot. 이 페이지에서 가장 어려운 section이다 — 천천히 가라. 논문 네 편 분량의 표기법을 가진 네 기법(PI, NTK-aware, YaRN, base-scaling)이 올바른 질문 하나를 던지는 순간 그림 하나로 접힌다: 64개 다이얼 각각에 대해, 이 기법은 그 속도에 어떤 배율을 곱하는가? 이 질문만 붙들면 아래의 모든 공식이 한 그래프 위의 곡선이 된다.

To stretch a context from L to s·L you must slow some dials down. The whole design space is WHICH dials, by HOW MUCH: the y-axis below is the per-dial frequency multiplier θ′ᵢ/θᵢ — 1 means untouched, 1/s means fully interpolated. Switch methods and scale factors. context를 L에서 s·L로 늘리려면 어떤 다이얼들은 느리게 돌려야 한다. 설계 공간 전체가 "어느 다이얼을, 얼마나"다: 아래 y축은 다이얼별 frequency 배율 θ′ᵢ/θᵢ — 1이면 그대로, 1/s면 완전 interpolation이다. 기법과 scale factor를 바꿔 가며 보라.

s
untouched · r > β=32 blend · γ ramp full interpolation · r < α=1 ×1 ×1/4 dial 0 λ 6.3 dial 16 63 dial 32 628 dial 48 6.3K dial 63 54K x: dial index (wavelength at base 10,000) · y: frequency multiplier θ′ᵢ ÷ θᵢ · r = L/λ counts rotations inside the original context L = 2,048
17 dials untouched · 24 blended · 23 fully interpolated temperature: logits × 0.1·ln s + 1 = 1.139 (s=4) α = 1 · β = 32 (Llama family, YaRN)

YaRN = NTK-by-parts + temperature. Per dial, r = L/λ counts full rotations inside the original context L. Fast dials (r above β = 32) are left untouched; dials whose wavelength exceeds the trained context (r below α = 1) get full interpolation θ/s; the middle is linearly blended (Eq. 8, 10, 11, 13). One extra scalar — logits scaled by 0.1·ln(s) + 1 — rides along for free: HF bakes it into the cos/sin cache as attention_scaling. YaRN = NTK-by-parts + temperature. 다이얼마다 r = L/λ가 원래 context L 안에서의 회전 수를 센다. 빠른 다이얼(r이 β = 32 초과)은 그대로 두고, wavelength가 학습 context보다 긴 다이얼(r이 α = 1 미만)은 완전 interpolation θ/s를 받고, 중간은 선형 blend된다 (Eq. 8, 10, 11, 13). 스칼라 하나가 덤으로 붙는다 — logit에 0.1·ln(s) + 1을 곱하는 temperature인데, HF는 이를 attention_scaling으로 cos/sin cache에 구워 넣는다.

PI Chen et al. 2023 · 2306.15595

Position Interpolation, Eq. 4: f′(x, m) = f(x, m·L/L′) — indices down-scaled, so every dial slows by the same s. Motivation: extrapolating past the trained length can produce "catastrophically high attention scores"; the interpolated perturbation is bounded ≈600× tighter (Thm 2.1, LLaMA constants). Works with ~1,000 fine-tune steps (2048 → 32768). The cost, per YaRN: the uniform rescale "removes the high frequency components of RoPE" — local order blurs, and PI fine-tunes degraded beyond s ≈ 8. Position Interpolation, Eq. 4: f′(x, m) = f(x, m·L/L′) — index를 줄이므로 모든 다이얼이 같은 s만큼 느려진다. 동기는 안전성: 학습 길이 밖으로 extrapolate하면 "파국적으로 높은 attention score"가 나올 수 있고, interpolation의 섭동은 약 600× 더 좁게 bound된다 (Thm 2.1, LLaMA 상수). fine-tune 약 1,000 step이면 된다 (2048 → 32768). 대가는, YaRN의 표현으로, 균일 rescale이 "RoPE의 high frequency 성분을 제거"한다는 것 — 국소 순서가 뭉개지고, PI fine-tune은 s ≈ 8을 넘으면 열화됐다.

every dial ÷ s · fastest λ 6.3 → 6.3·s tokens

NTK-aware formalized in YaRN · Eq. 19–20

Change the base instead: b′ = b·s^(d/(d−2)), designed so "the lowest frequency needs to be scaled as much as linear positional scaling and the highest frequency to stay constant." The result is a geometric tilt of the ladder: dial 0 exactly unchanged, the last dial at exactly θ/s, everything between graded [per-band ratio θ′ᵢ/θᵢ = s^(−2i/(d−2)), derived from the quoted formula]. At s = 4, d = 128: b′ ≈ 40,890. 대신 base를 바꾼다: b′ = b·s^(d/(d−2)). "가장 낮은 frequency는 linear scaling만큼 줄고 가장 높은 frequency는 그대로"가 되도록 설계됐다. 결과는 사다리의 기하급수 기울이기: 다이얼 0은 정확히 그대로, 마지막 다이얼은 정확히 θ/s, 그 사이는 등비로 눕는다 [band별 비율 θ′ᵢ/θᵢ = s^(−2i/(d−2)), 인용 공식에서 유도]. s = 4, d = 128이면 b′ ≈ 40,890.

dial 0 fixed · dial 63 exactly ÷ s

YaRN Peng et al. 2023 · 2309.00071

Make the tilt piecewise and explicit: per dial, r(d) = L/λ_d; γ(r) = 0 below α, 1 above β, linear between; new frequency h(θ) = (1−γ)·θ/s + γ·θ. Recommended α = 1, β = 32 for the Llama family — dials that rotate more than 32 times inside L keep their exact speed; dials that cannot finish one rotation get full PI treatment. Plus the attention temperature √(1/t) = 0.1·ln(s) + 1. 기울이기를 조각별로, 명시적으로: 다이얼마다 r(d) = L/λ_d; γ(r)는 α 아래 0, β 위 1, 사이 선형; 새 frequency는 h(θ) = (1−γ)·θ/s + γ·θ. Llama 계열 권장값 α = 1, β = 32 — L 안에서 32번 넘게 도는 다이얼은 속도를 정확히 지키고, 한 바퀴도 못 도는 다이얼은 완전한 PI 처리를 받는다. 여기에 attention temperature √(1/t) = 0.1·ln(s) + 1이 더해진다.

α=1 · β=32 · γ ramp over r = L/λ

Base-scalingBase-scaling Llama-3 / Qwen3 configs

The pretraining-era route: ship a bigger base from day one. Llama-3-8B: rope_theta = 500,000 (config.json, max_position 8,192); Qwen3-8B: 1,000,000 (max_position 40,960; rope_scaling null). The whole ladder is stretched at train time — Llama-3's slowest dial has wavelength ≈ 2.56M tokens [computed from λ = 2π·base^((d−2)/d)], so slow dials stay near-static over any real context. Barbero et al.: increasing θ prevents tokens "being erroneously misaligned simply due to the large context." pretraining 시절부터의 경로: 처음부터 큰 base로 출시한다. Llama-3-8B: rope_theta = 500,000 (config.json, max_position 8,192); Qwen3-8B: 1,000,000 (max_position 40,960; rope_scaling null). 사다리 전체가 train 시점에 늘어난다 — Llama-3의 가장 느린 다이얼은 wavelength ≈ 2.56M token [λ = 2π·base^((d−2)/d)에서 계산]이라, 느린 다이얼들은 어떤 실제 context에서도 거의 정지 상태다. Barbero et al.: θ를 키우는 것은 token들이 "단지 context가 크다는 이유로 잘못 어긋나는" 것을 막는다.

train-time · no post-hoc ramp

Partial RoPE — dials that never existed Partial RoPE — 처음부터 없는 다이얼

GPT-NeoX-20Bhead_dim 96 · rotary_pct 0.25
24 rotated 72 dims — never rotated · position-free
Qwen3.5-27Bhead_dim 256 · partial_rotary_factor 0.25
64 rotated 192 dims — never rotated · position-free
Qwen3.5 flags: hybrid — full attention every 4th layer mRoPE sections 11/11/10 (multimodal) θ = 10,000,000

Attribution matters here: GPT-NeoX's stated reason for 25% partial rotary is the performance/efficiency balance (following GPT-J). The reading of unrotated dims as a deliberate "distance-agnostic semantic channel" arrives later, with Barbero et al.'s p-RoPE (section d) — which removes the lowest frequencies rather than leaving dims unrotated from the start. 여기서는 attribution이 중요하다: GPT-NeoX가 밝힌 25% partial rotary의 이유는 성능/효율 균형이다 (GPT-J를 따름). 회전되지 않는 차원을 의도적인 "거리-불변 semantic channel"로 읽는 해석은 나중에 Barbero et al.의 p-RoPE(section d)와 함께 온다 — p-RoPE는 처음부터 안 돌리는 게 아니라 가장 낮은 frequency를 제거하는 쪽이다.

On one shared wavelength axis the four routes stop looking like rival tricks and become one decision — which dials to slow, by how much. PI drags every dial down equally and pays with blurred local order; NTK-aware tilts the ladder, pinning the fast end and fully interpolating the slow end; YaRN makes the tilt piecewise with an explicit r = L/λ ramp (α = 1, β = 32) plus a logit temperature; big-base pretraining stretches the ladder before training so nothing needs editing afterwards. Partial RoPE is the limiting edit — a fraction of dials never turn at all. Which dials deserve protection is exactly what the p-RoPE ablation asks from the training side, and there, removing the lowest quarter of frequencies retrained slightly better than protecting them with a bigger base. 하나의 wavelength 축 위에 올려놓으면 네 경로는 경쟁하는 트릭이 아니라 하나의 결정이 된다 — 어느 다이얼을, 얼마나 늦출 것인가. PI는 모든 다이얼을 똑같이 끌어내리고 국소 순서의 흐릿함으로 값을 치른다. NTK-aware는 빠른 끝을 고정하고 느린 끝을 완전 interpolation하며 사다리를 기울인다. YaRN은 그 기울임을 r = L/λ ramp(α = 1, β = 32)로 조각별로 명시하고 logit temperature를 더한다. big-base pretraining은 학습 전에 사다리를 늘려 두어 이후 수정이 필요 없게 만든다. partial RoPE는 극한의 수정이다 — 일부 다이얼은 아예 돌지 않는다. 어느 다이얼을 보호해야 하는가는 p-RoPE ablation이 학습 쪽에서 던진 바로 그 질문인데, 거기서는 가장 낮은 frequency 4분의 1을 제거하고 재학습한 쪽이 더 큰 base로 보호한 쪽보다 근소하게 나았다.

Takeaway핵심 한 줄 Every long-context method is the same edit expressed differently: a per-dial frequency multiplier between 1 and 1/s. PI is a flat line, NTK-aware a geometric tilt, YaRN a piecewise ramp, base-scaling the same stretch bought at training time. 모든 long-context 기법은 같은 수정을 다르게 표기한 것이다: 1과 1/s 사이의 다이얼별 frequency 배율. PI는 수평선, NTK-aware는 기하급수 기울임, YaRN은 조각별 ramp, base-scaling은 같은 늘림을 학습 시점에 산 것이다.

All of this mathematics ends up frozen into the KV cache — what does a rotation baked into cached bytes force on real serving systems? 이 수학 전부가 결국 KV cache 안에 얼어붙는다 — cache된 byte에 구워진 회전은 실제 serving 시스템에 무엇을 강제하나?

§8 f · Systems corner — where the rotation meets the cache f · Systems corner — 회전이 cache를 만나는 곳

Everything so far was mathematics. But §3 planted a systems fact with long consequences: K enters the cache already rotated, so position is physically inside the cached bytes. Here are three published designs that exist because of that one fact. 지금까지는 전부 수학이었다. 그러나 §3이 긴 그림자를 드리우는 systems 사실 하나를 심어 두었다: K는 이미 회전된 채 cache에 들어가고, 따라서 position은 cache된 byte 안에 물리적으로 존재한다. 그 한 사실 때문에 존재하는 공개된 설계 세 가지를 소개한다.

Three published designs that exist because of section a's two facts: K is cached post-RoPE, and position lives only in the q·k score. Published claims only. section a의 두 사실 — K는 post-RoPE로 cache되고, position은 q·k score에만 산다 — 때문에 존재하는 세 가지 공개된 설계. 공개된 주장만 담았다.

Rotate-at-writeRotate-at-write HF transformers

In the standard HF path, apply_rotary_pos_emb runs before past_key_values.update(...) — verified code order in modeling_qwen3.py. Every cached K is therefore stamped with the position it was written at: a cached entry cannot be reused at a different position without un-rotating and re-rotating it. vLLM's rotary layer follows the same rotate-before-write convention (its rotary implementations verified; the cache-write ordering itself is the standard reading). 표준 HF 경로에서 apply_rotary_pos_emb는 past_key_values.update(...)보다 먼저 실행된다 — modeling_qwen3.py에서 검증한 코드 순서다. 따라서 cache된 모든 K에는 쓰인 시점의 position이 새겨져 있다: cache 항목을 다른 position에서 재사용하려면 회전을 풀고 다시 돌려야 한다. vLLM의 rotary layer도 같은 rotate-before-write 관례를 따른다 (rotary 구현은 검증됨; cache 쓰기 순서 자체는 표준적 해석).

q_norm → RoPE → cache update — verified order

MLA — position as a side-channelMLA — side-channel로 옮긴 position DeepSeek-V2 · 2405.04434

Low-rank absorbed keys can't carry RoPE: "W^UK … will be coupled with a position-sensitive RoPE matrix … [and] cannot be absorbed into W^Q any more during inference." DeepSeek-V2's fix is decoupled RoPE: per-head rotary queries plus ONE shared 64-dim rotary key per token (d_h^R = 64), cached alongside the 512-dim latent — position lives only in the 64-dim side-channel; the 512-dim latent is position-free by construction. Full walkthrough in the attention-anatomy deep-dive. low-rank로 흡수된 key는 RoPE를 실을 수 없다: "W^UK는 position에 민감한 RoPE 행렬과 결합되어 … inference에서 더 이상 W^Q에 흡수될 수 없다." DeepSeek-V2의 해법이 decoupled RoPE다: head별 rotary query와, token당 하나의 공유 64-dim rotary key(d_h^R = 64)를 512-dim latent 옆에 cache한다 — position은 64-dim side-channel에만 살고, 512-dim latent는 구조적으로 position-free다. 전체 과정은 attention-anatomy 딥다이브 참고.

cache = 512 position-free + 64 rotated

KVQuant — quantize before the rotationKVQuant — 회전 전에 quantize Hooper et al. · 2401.18079

Published rationale: keys "pre-RoPE exhibit clear outliers in specific channels across different tokens", while "after applying RoPE, the distribution becomes less structured … (this is expected, as RoPE applies a rotation operation between pairs of channels)." Their scheme quantizes keys pre-RoPE and applies the rotation on-the-fly after dequantization with a fused kernel — a claimed 0.82 perplexity improvement on Wikitext-2 for 3-bit LLaMA-7B versus post-RoPE per-channel quantization, "without adding runtime overhead" (their claim). See the KVQuant review. 공개된 논거: key는 "pre-RoPE에서 token이 달라도 특정 channel에 뚜렷한 outlier"를 보이는 반면, "RoPE 적용 후에는 분포가 덜 구조적이 된다 … (RoPE가 channel pair 사이에 회전을 가하므로 예상되는 일이다)." 이들의 방식은 key를 pre-RoPE로 quantize하고, dequantization 후 fused kernel로 회전을 on-the-fly 적용한다 — 3-bit LLaMA-7B에서 post-RoPE per-channel quantization 대비 Wikitext-2 perplexity 0.82 개선을 주장하며, "runtime overhead 추가 없이"라는 것도 저자들의 주장이다. KVQuant 리뷰 참고.

quantize pre-RoPE → dequant → rotate on read

Why the dial board matters for efficient inference 왜 이 다이얼 보드가 효율적 inference에 중요한가

The KV cache stores rotated keys, so position is physically inside the cached bytes: any system that moves, evicts, shares or compresses cached keys inherits the dial board. The three published designs in the systems corner are all responses to that one fact — DeepSeek's MLA carves position into a separate 64-dim side-channel precisely so the other 512 dims stay absorbable; KVQuant quantizes keys before the rotation because the rotation smears the channel-wise outlier structure its quantizer relies on; and every rotate-at-write cache commits each K entry to the position it was written at. Reading rope_theta, partial_rotary_factor and rope_scaling out of a model's config tells you — before any profiling — which dials exist, how fast they turn, and which parts of the cached representation carry position at all. KV cache는 회전된 key를 저장하므로 position은 cache된 byte 안에 물리적으로 들어 있다: cache된 key를 옮기고, 내보내고, 공유하고, 압축하는 모든 시스템이 이 다이얼 보드를 물려받는다. systems corner의 세 공개 설계가 전부 이 한 사실에 대한 응답이다 — DeepSeek의 MLA는 나머지 512개 차원이 계속 흡수 가능하도록 position을 별도 64-dim side-channel로 도려냈고, KVQuant는 회전이 quantizer가 기대는 channel별 outlier 구조를 뭉개기 때문에 회전 전에 quantize하며, rotate-at-write cache는 모든 K 항목을 쓰인 시점의 position에 묶는다. 모델 config에서 rope_theta·partial_rotary_factor·rope_scaling을 읽으면 — profiling 없이도 — 어떤 다이얼이 존재하고, 얼마나 빨리 돌고, cache된 표현의 어느 부분이 position을 나르는지 알 수 있다.

position lives in the cached K bytes MLA: 512 position-free + 64 rotated KVQuant: quantize pre-RoPE, rotate on read
Takeaway핵심 한 줄 Because K is cached post-rotation, every system that touches cached keys inherits the dial board — MLA, KVQuant and rotate-at-write caches are three published shapes of that inheritance. K가 회전된 뒤 cache되기 때문에, cache된 key를 만지는 모든 시스템은 다이얼 보드를 물려받는다 — MLA, KVQuant, rotate-at-write cache가 그 상속의 공개된 세 가지 형태다.

Claims on a page are cheap — do the equations actually hold digit for digit? Time to recompute everything by hand. 지면 위의 주장은 값싸다 — 수식이 정말 자릿수 단위로 성립하나? 이제 전부 손으로 재계산할 시간이다.

§9 g · Worked example — d = 8, check every digit g · 수치 예제 — d = 8, 모든 자릿수를 직접 검산

A derivation you cannot recompute is a rumor. Before leaving the mechanism, shrink it until nothing can hide: d = 8, four dials, one query, one key — every claim from §2 through §6 reduced to arithmetic you can redo on paper. 직접 재계산할 수 없는 유도는 소문일 뿐이다. 메커니즘을 떠나기 전에, 아무것도 숨을 수 없을 만큼 줄여 보자: d = 8, 다이얼 4개, query 하나, key 하나 — §2부터 §6까지의 모든 주장이 종이 위에서 다시 할 수 있는 산수로 환원된다.

The full pipeline at d = 8 (four pairs, base 10,000), small enough to recompute by hand. All values machine-checked [derived on this page]. Step through. d = 8(pair 4개, base 10,000)에서의 전체 파이프라인 — 손으로 재계산할 수 있을 만큼 작다. 모든 값은 기계 검산을 거쳤다 [이 페이지의 유도]. step을 넘겨 보라.

Step 0 / 5 — Setup
q = (1, 0, 0.5, −0.5, 0.2, 0.3, −0.4, 0.1) · k = (0, 1, 0.3, 0.7, −0.1, 0.2, 0.6, −0.2) · d = 8 · base 10,000 · ωᵢ = 10000^(−2i/8)
ω = (1, 0.1, 0.01, 0.001) rad/token · λ = 2π/ω = (6.283, 62.83, 628.3, 6,283.2) tokens
angles m·ω at m = 3: (3, 0.3, 0.03, 0.003) rad · at n = 7: (7, 0.7, 0.07, 0.007) rad
pair 0 of q at m = 3: (1, 0) → (cos 3, sin 3) = (−0.98999, 0.14112)
R(3)q = (−0.98999, 0.14112, 0.62543, −0.32991, 0.19091, 0.30586, −0.40030, 0.09880)
R(7)k = (−0.65699, 0.75390, −0.22150, 0.72865, −0.11374, 0.19252, 0.60139, −0.19580)
⟨R(3)q, R(7)k⟩ = 0.154972 · ⟨q, R(4)k⟩ = 0.154972 · ⟨R(13)q, R(17)k⟩ = 0.154972

A checkable micro-example: d = 8 gives four pairs; the 0-indexed convention ωᵢ = 10000^(−2i/8) fixes every speed. Each following step adds one operation — ending at the relative-position identity verified three ways to machine precision. 검산 가능한 초소형 예제: d = 8이면 pair가 4개이고, 0-index 관례 ωᵢ = 10000^(−2i/8)이 모든 속도를 결정한다. step마다 연산이 하나씩 더해지며, 마지막에는 상대-position 항등식을 세 가지 방식으로 machine precision까지 확인한다.

Takeaway핵심 한 줄 The relative-position identity survives contact with actual numbers: ⟨R(3)q, R(7)k⟩ = ⟨q, R(4)k⟩ = ⟨R(13)q, R(17)k⟩ = 0.154972 — three routes, one value, machine precision. 상대-position 항등식은 실제 숫자와의 접촉에서도 살아남는다: ⟨R(3)q, R(7)k⟩ = ⟨q, R(4)k⟩ = ⟨R(13)q, R(17)k⟩ = 0.154972 — 세 가지 경로, 하나의 값, machine precision.

The mechanism is settled — but the design space around it is not. What is the field still arguing about? 메커니즘은 정리됐다 — 그러나 그 주변의 설계 공간은 아니다. field는 아직 무엇을 두고 다투고 있나?

§10 Where this goes — the open edges 다음은 어디로 — 열린 가장자리들

The open questions are no longer about whether RoPE works but about which of its dials are actually needed. The p-RoPE result of section d — removing the lowest quarter of frequencies and retraining slightly beats protecting them with a bigger base — exists only at Gemma-2B scale, retrained from scratch; whether frontier-scale models want the same diet is unmeasured. Architectures push the same question from the other side: Qwen3.5's hybrid stack rotates only its full-attention layers (one in four), mRoPE splits the dial budget across temporal/height/width axes for multimodal inputs, and linear-attention hybrids keep softmax attention — and with it, the dial board — in only a small fraction of layers (see the MiniMax-01 and Gated DeltaNet reviews, and the hybrid-attention page). 열린 질문은 이제 "RoPE가 작동하는가"가 아니라 "어느 다이얼이 실제로 필요한가"다. section d의 p-RoPE 결과 — 가장 낮은 frequency 4분의 1을 제거하고 재학습한 쪽이 더 큰 base로 보호한 쪽을 근소하게 이긴다 — 는 처음부터 재학습한 Gemma-2B 규모에서만 존재하고, frontier 규모 모델이 같은 식단을 원하는지는 측정된 바 없다. 아키텍처는 같은 질문을 반대편에서 민다: Qwen3.5의 hybrid stack은 full-attention layer(4개 중 1개)만 회전시키고, mRoPE는 멀티모달 입력을 위해 다이얼 예산을 temporal/height/width 축으로 나누며, linear-attention hybrid는 softmax attention을 — 그리고 그와 함께 다이얼 보드를 — 소수의 layer에만 남긴다 (MiniMax-01·Gated DeltaNet 리뷰와 hybrid-attention 페이지 참고).

The serving edge is the collision between section f's fact and cache compression. Position lives in the cached K bytes, so every KV-cache compression design must take a stance on the rotation: KVQuant quantizes keys before it to keep the channel-wise outlier structure (review), KIVI picks its quantization axes on the post-RoPE tensors (review), and DuoAttention asks which heads need full positional resolution at all before deciding whose cache to shrink (review). Where the rotation should sit relative to compression, eviction and sharing is a live design question, still being argued paper by paper. serving 쪽 가장자리는 section f의 사실과 cache 압축의 충돌이다. position이 cache된 K byte 안에 살기 때문에, 모든 KV-cache 압축 설계는 회전에 대한 입장을 정해야 한다: KVQuant는 channel별 outlier 구조를 지키려 회전 전에 quantize하고 (리뷰), KIVI는 post-RoPE tensor 위에서 quantization 축을 고르며 (리뷰), DuoAttention은 누구의 cache를 줄일지 정하기 전에 어느 head가 full positional resolution을 필요로 하는지부터 묻는다 (리뷰). 회전이 압축·eviction·공유에 대해 어디에 놓여야 하는가는 살아 있는 설계 질문이고, 아직 논문 단위로 다투는 중이다.

Going deeper 더 깊이 가기

Sources verified July 2026: RoFormer Eq. 14–16/34 and §3.4.3; PI Eq. 4 and Thm 2.1; YaRN Eq. 8–20 and Def. 2; Barbero et al. 2410.06205 (Gemma 7B norm/head analysis; Table 2 = Gemma 2B retrained from scratch); GPT-NeoX-20B; DeepSeek-V2 §2.1; KVQuant; HF transformers modeling_qwen3.py (inv_freq, rotate_half, QK-norm-before-RoPE, attention_scaling, one cos/sin per forward broadcast to all heads and layers) and convert_llama_weights_to_hf.py (q/k permute); vLLM rotary_embedding/common.py (rotate_neox and rotate_gptj); config.json of Qwen3-8B (θ 10⁶, head_dim 128, full rotary, max_position 40,960), Llama-3-8B (θ 500,000, max_position 8,192), Qwen3.5-27B (partial_rotary_factor 0.25, θ 10⁷, hybrid + mRoPE). "Every layer, every head" holds for standard dense decoders; Qwen3.5's hybrid stack rotates only its full-attention layers and MLA rotates only a 64-dim sub-key. Derived arithmetic — λ_max = 2π·base^((d−2)/d) ≈ 54,410 (base 10⁴) / ≈ 2.56M (base 5·10⁵), the NTK per-band ratio, the cosine-series decomposition, and the d = 8 example — is computed and labeled in place. Wavelength convention: 0-indexed ωᵢ = base^(−2i/d); RoFormer's 1-indexed θᵢ is the same ladder. 2026년 7월 검증한 출처: RoFormer Eq. 14–16/34, §3.4.3; PI Eq. 4, Thm 2.1; YaRN Eq. 8–20, Def. 2; Barbero et al. 2410.06205 (Gemma 7B norm/head 분석; Table 2는 처음부터 재학습한 Gemma 2B); GPT-NeoX-20B; DeepSeek-V2 §2.1; KVQuant; HF transformers modeling_qwen3.py (inv_freq, rotate_half, QK-norm이 RoPE보다 먼저, attention_scaling, forward당 한 번의 cos/sin을 전 head·전 layer에 broadcast)와 convert_llama_weights_to_hf.py (q/k permute); vLLM rotary_embedding/common.py (rotate_neox·rotate_gptj); Qwen3-8B (θ 10⁶, head_dim 128, full rotary, max_position 40,960), Llama-3-8B (θ 500,000, max_position 8,192), Qwen3.5-27B (partial_rotary_factor 0.25, θ 10⁷, hybrid + mRoPE)의 config.json. "모든 layer, 모든 head"는 표준 dense decoder에서 성립한다 — Qwen3.5의 hybrid stack은 full-attention layer만 회전하고 MLA는 64-dim sub-key만 회전한다. 유도 계산 — λ_max = 2π·base^((d−2)/d) ≈ 54,410 (base 10⁴) / ≈ 2.56M (base 5·10⁵), NTK band별 비율, cosine 급수 분해, d = 8 예제 — 는 본문 해당 위치에 계산·표기했다. wavelength 관례: 0-index ωᵢ = base^(−2i/d); RoFormer의 1-index θᵢ와 같은 사다리다.