OpenArchLabOpen Architecture — From Models to Systems

3C · Ring SWA & Hierarchical Indexer

3C · Cửa sổ trượt vòng (Ring SWA) và Bộ chọn chỉ mục phân cấp (Hierarchical Indexer)

Ring SWA giữ 128 vị trí gần nhất trong cache vòng và không góp byte nào vào cache lâu dài; Indexer chọn 2048 block × 8 vị trí bằng score relu(q·k) × weights_proj, block mới nhất pin +inf.

LESSON ID dsv41-sparse-indexer GROUP Kiến trúc & Giải phẫu
Mục lục bài học

1Định nghĩa

Ring SWA và Hierarchical Indexer là bộ chọn vị trí của khối 3C: Ring SWA giữ cửa sổ 128 vị trí gần nhất trong cache vòng (window_kv_cache) và không persist phần này xuống ổ đĩa, nhờ SWA Bounded Replay tái dựng tối đa n_win = 128 token gần nhất khi phục vụ lại; Indexer là đầu attention phụ với score = relu(q·k) × weights_proj tính trên index_n_heads = 32 head, mỗi head index_head_dim = 128, dùng để chọn index_topk = 512 vị trí đáng đọc nhất. Bài toán cần giải là đọc ngữ cảnh rất dài mà không tính toàn bộ attention đắt đỏ; bài local vs global trình bày cách cắt nhiễu theo cửa sổ, còn indexer giữ thêm một phần đọc chọn lọc trên phần xa hơn cửa sổ.

Về cơ chế, đầu vào của indexer là index_k 128 chiều của các entry nén như mô tả trong bài CSA2; pool ứng viên do lớp 20 chọn qua select_candidate_blocks: 2048 block × 8 vị trí cho tổng 16.384 vị trí; block mới nhất được pin +inf nên luôn nằm trong pool, còn các lớp Reindex sâu hơn (24, 28, 32, 36) chỉ đọc trong pool này vì candidate_source_layer_id = 20. index_source_layer_ids = [2, 8, 14, 20, 24, 28, 32, 36] cho biết indexer dùng K của tám lớp này, các lớp rải đều để kernel đọc các khoảng xếp sẵn. Đầu ra là 512 vị trí top-k dùng cho attention của các lớp sau; muốn thấy pool được chốt và đối chiếu các lớp bị mask, theo bước 3C của Bài Lab tổng hợp DeepSeek-V4.1-Flash.

Ví dụ đời thường: Ring SWA giống bảng ghi hình vòng của camera an ninh: khi bảng đầy, khung cũ bị ghi đè và chỉ khung gần nhất còn nguyên; khi phục vụ lại phiên, máy chỉ dựng lại tối đa 128 khung gần nhất thay vì lưu tạm bản ghi đầy dưới ổ đĩa. Indexer giống người lập danh mục thay vì xem lần lượt băng hình dài nhiều giờ: chấm điểm từng đoạn 8 khung và giữ danh sách 2048 đoạn đáng chú ý, trong đó đoạn mới nhất được dán tem ưu tiên. Giới hạn của phép so: việc chọn đoạn chỉ dựa theo score học được và 2048 block là con số thiết kế cố định; đổi pool phải huấn luyện lại mô hình, không chỉnh được lúc runtime.

2Luồng

Cách đọc hình (Cột 2, khối 3C dưới đáy): kết hợp vòng đệm Ring Buffer 128 slot gần nhất (window_kv) với phễu lọc 2048×8 khối ứng viên ở L20 và phép chấm điểm ReLU(Q·K)·w chọn Top-512 vị trí nén cấp sang Cột 3; xem bước [3C] trong Bài Lab tổng hợp ở Tab 02.

Sơ đồ luồng dữ liệu 4 cột · 10 thành phần (1A → 6B)

Kiến trúc DeepSeek-V4.1-Flash & Ánh xạ 1:1 với Bài Lab tổng hợp

Bắt đầu từ 1A ở góc dưới Cột 1 đi lên 1B → 2A, sang Cột 2 (3A → 3B → 3C), qua Cột 3 (4A ↔ 6A) và kết thúc ở Cột 4 (5A → 6B). Di chuột hoặc bấm vào từng khối để xem pop-over và đối chiếu với Lab.

Sơ đồ luồng dữ liệu 4 cột của kiến trúc DeepSeek-V4.1-Flash gồm 10 thành phần từ 1A đến 6B
3C2 · CED 20+20 & CSA2 Compression
Ring Buffer (SWA: 128 slots k_0..k_127) + L20: 2048×8 Candidate Blocks → ReLU(Q·K)·w → Top-512 Idxs

3C · Ring SWA (128) & Sparse Indexer

Đáy Cột 2: kết hợp vòng đệm Ring Buffer 128 slot gần nhất với bộ lọc phân cấp 2048×8 khối ứng viên để chọn Top-512 vị trí nén.

Ở đáy Cột 2, mỗi lớp giữ một bộ đệm vòng Ring Buffer 128 slot (k_0..k_127) cho các token gần nhất kết hợp với bộ chọn chỉ mục thưa cho lịch sử xa. Tại lớp 20, tầng lọc thứ nhất chọn 2048 khối ứng viên (mỗi khối 8 vị trí nén); sau đó phép chấm điểm ReLU(Q·K)·w chọn ra đúng Top-512 vị trí nén cao điểm nhất để chuyển sang phép tính MLA ở Cột 3.

Sơ đồ luồng (3 bước)
  1. 3C · Ring buffer cửa sổ SWA

    window_kv_cache giữ 128 vị trí gần nhất kiểu ring; khi phục vụ lại, SWA Bounded Replay chỉ tái dựng tối đa 128 token gần nhất.

  2. 3C · Indexer tính score

    Indexer với score = relu(q·k) × weights_proj chấm từng vị trí; index_topk giữ 512 vị trí tốt nhất.

  3. 3C · Chọn 2048 block và mask lớp sâu

    select_candidate_blocks tại lớp 20 chọn 2048 block × 8 vị trí, pin block mới nhất +inf; các lớp Reindex chỉ đọc trong pool này.

Mã Mermaid
flowchart TD
  step1["3C · Ring buffer cửa sổ SWA"]
  step2["3C · Indexer tính score"]
  step3["3C · Chọn 2048 block và mask lớp sâu"]
  step1 --> step2
  step2 --> step3

3Giải pháp

Bài toán cần giải: đọc ngữ cảnh rất dài mà chi phí attention tăng tỉ lệ theo độ dài; cần một cách đọc gần chính xác với chi phí có giới hạn trên. Ring SWA giữ chi tiết cục bộ gần; Indexer chọn phần chi tiết xa qua pool candidate. Sau bài này, bạn cần tự kể được: ring buffer giữ bao nhiêu và ghi đè phần nào, score indexer tính ra sao, và vì sao lớp 20 là nơi chốt pool candidate cho các lớp Reindex sâu hơn.

Ring buffer SWA: window_kv_cache giữ tối đa 128 vị trí gần nhất theo kiểu ring buffer: token mới ghi vào ô (token_index mod 128), tức là có thể ghi đè ở ô đó. Khi đó, thứ tự index trong cache không sắp theo độ dài chuỗi; nhớ tính sẵn vị trí. Chú ý: cache vòng có kích thước cố định, không tăng theo độ dài chuỗi, giúp giữ chi phí bộ nhớ decode cố định.

SWA Bounded Replay: khi phục vụ lại phiên làm việc cũ, SWA KV có thể bị mất vì không persist xuống ổ đĩa; cơ chế SWA Bounded Replay chỉ replay tối đa n_win = 128 token gần nhất để tái dựng window_kv_cache. Đánh đổi này hợp lý: window không persist nên cache lâu dài chỉ còn phần nén; SWA đóng góp 0 byte vào ngân sách 890 B/token tóm tắt trong bài ngân sách KV FP4. Chú ý: replay không miễn phí; SWA KV của cửa sổ phải được tính lại từ n_win token gần nhất thay vì tải cache persist.

Indexer tính score: Indexer là đầu attention phụ của mô hình với các tham số index_n_heads = 32, index_head_dim = 128, dùng trên 8 lớp index_source_layer_ids = [2, 8, 14, 20, 24, 28, 32, 36]. Với mỗi vị trí t, score = relu(q·k) × weights_proj; điểm này được xếp để giữ index_topk = 512 vị trí. Đặc điểm: relu giữ score không âm nên chỉ chọn vị trí có tích dương; weights_proj là phép chiếu nhẹ học cùng indexer.

select_candidate_blocks tại lớp 20: lớp 20 là candidate_source_layer_id, chốt pool candidate theo block: mỗi block 8 vị trí (block_size = 8), chọn 2048 block (candidate_topk_blocks = 2048), tổng 16.384 vị trí; block mới nhất được pin +inf nên luôn nằm trong pool. Các lớp 24, 28, 32, 36 chỉ đọc trong pool này, giúp indexer sâu không phải tính lại toàn bộ. Đây là cấp hai trong tầng phân cấp: gần dùng window SWA, xa dùng pool candidate chốt từ lớp 20.

Giới hạn và nơi quan sát: pool candidate 16.384 vị trí là chi phí gắn cứng trong cấu hình; đối với ngữ cảnh dài hơn, pool vẫn 16.384 vị trí (2048 × 8) và chỉ chọn trong đó, nghĩa là vị trí ngoài pool không thể được các lớp Reindex dùng. Muốn thấy pool được chốt và lớp nào bị mask, mở bước 3C của Bài Lab tổng hợp DeepSeek-V4.1-Flash, rồi tiếp bài MLA để xem attention đọc các vị trí đã chọn.

4Profiling

  • Parity window_kv_cache với replay

    Kiểm tra tính đúng trước: chạy chuỗi dài hơn 128 token; so window_kv_cache tái dựng qua SWA Bounded Replay (128 token gần nhất) với tính lại toàn chuỗi từ đầu; sai khác trong ngưỡng đã chọn (ví dụ 1e-9). Kiểm ring position riêng biệt: token tại index t phải nằm ở ô t mod 128, không phải t.

  • Tỉ lệ thu hẹp qua pool candidate

    Đo tỉ lệ index_topk_idxs được chọn trong pool 16.384 vị trí so với tổng số vị trí còn thấy của chuỗi; khi chuỗi càng dài (lớn hơn 16.384 vị trí), tỉ lệ chuỗi nằm ngoài pool càng tăng, cho thấy indexer thu hẹp bao nhiêu so với attention đọc toàn bộ. Ghi riêng token mới nhất và pool bị pin +inf để không đếm nhầm.

  • Chi phí đọc window trong pha decode

    Đo byte đọc window_kv_cache khi decode từng token: window 128 vị trí × 2 (K và V) × byte theo dtype khai báo; cộng từng lớp độc lập và tách phần đọc window với phần đọc compress_kv để không trùng đếm.

Mẹo đo lường: ghim số liệu trên workload thật, ghi cả p50/p95/p99 thay vì chỉ trung bình, và luôn ghi lại điều kiện chạy (batch, cache, đồng thời, phần cứng) trước và sau khi tối ưu. Số đo thiếu điều kiện chạy thì không so sánh được.

5Ví dụ

Bước 1 · Dự đoán vị trí ring buffer

Input: một chuỗi 10 token, window size = 8 (thu nhỏ cho dễ tính). Trước khi tính, hãy dự đoán: token thứ 10 nằm trong ô nào của ring buffer 8 ô, và ô nào chứa token nào? Đáp án ở Bước 2; có thể đối chiếu với kênh ring trong bước 3C của [bài lab tổng hợp](/courses/deepseek-v4-1-flash/dsv41-lab/dsv41-end-to-end-lab/).

Bước 2 · Tính vị trí ring buffer

Với window = 8 (thu nhỏ cho dễ tính), vị trí ring của token thứ k (đánh số từ 1) là (k - 1) mod 8. Tính: token 1 → ô 0; token 5 → ô 4; token 8 → ô 7; token 9 → ô 0 (ghi đè token 1); token 10 → ô 1 (ghi đè token 2). Tự kiểm tra: token 18 → (18 - 1) mod 8 = 17 mod 8 = 1, tức cùng ô với token 10; ô đó ban đầu giữ token 2, đã bị ghi đè hai lần. Sau 10 token, 8 ô chứa đúng token 3 đến 10, còn token 1–2 không còn trong cache vòng nào.

Tự kiểm tra · Pool candidate với chuỗi 40.000 token

Input: chuỗi 40.000 token, block_size = 8, candidate_topk_blocks = 2048. Trước khi tính, hãy dự đoán: cần bao nhiêu block và có bao nhiêu block nằm ngoài pool? Đáp án: cần ceil(40.000 / 8) = 5.000 block; pool giữ 2048 block, trong đó block tại cuối chuỗi được pin +inf nên luôn được chọn; còn 5.000 - 2.048 = 2.952 block ngoài pool, tương đương 2.952 × 8 = 23.616 vị trí không thể được các lớp Reindex đọc. Tự kiểm tra thêm: nếu chuỗi 12.000 token thì cần ceil(12.000 / 8) = 1.500 block nhỏ hơn 2.048, nên cả chuỗi đều nằm trong pool; kết quả này cho thấy pool chỉ chặn khi chuỗi vượt 2048 × 8 = 16.384 vị trí.

6Thuật ngữ

window_kv_cache (SWA)
Cache vòng với cửa sổ 128 vị trí gần nhất; khi đầy, ô cũ bị ghi đè và phần này không được persist xuống ổ đĩa.
SWA Bounded Replay
Cách khôi phục cửa sổ SWA bị mất khi phục vụ lại phiên: chỉ replay tối đa n_win = 128 token gần nhất, không lưu SWA KV xuống ổ đĩa.
Indexer side-attention
Đầu attention phụ: score = relu(q·k) × weights_proj dùng để chọn vị trí đáng đọc trong ngữ cảnh dài mà không cần tính attention đầy đủ.
select_candidate_blocks
Bước tại lớp 20 chọn 2048 block (mỗi block 8 vị trí) làm pool ứng viên; block mới nhất được pin +inf; các lớp Reindex sâu hơn chỉ đọc trong pool này.
index_topk
Số vị trí index được giữ top-k (512) từ pool candidate; các lớp Reindex và Reuse chỉ đọc các vị trí này.
Glossary (4)
Ring buffer
Bộ nhớ vòng kích thước cố định 128 vị trí: khi đầy, ô cũ bị ghi đè; chi phí bộ nhớ không tăng theo độ dài chuỗi.
Sliding Window Attention (SWA)
Attention chỉ đọc cửa sổ gần nhất; đánh đổi là chi phí đọc mỗi token có giới hạn trên.
Block candidate
Nhóm 8 vị trí liên tiếp được chọn hoặc bỏ cùng nhau; chọn theo block thay vì từng vị trí để giảm số lần sắp xếp.
Pin +inf
Ép điểm vô cùng cho block mới nhất, bảo đảm block luôn nằm trong pool cho các lớp sau.

7Bài liên quan

8Nguồn