Transformers documentation
Paged attention
Paged attention
이 페이지는 continuous batching에서 사용되는 paged attention forward 함수를 문서화합니다.
Varlen 경로
flash_attn_varlen_func 커널은 가변 길이 배치(batch)를 처리합니다. prefill 단계에서 요청 수가 많은 배치의 경우 이 경로를 사용하는 것이 권장됩니다.
캐시 동작
이 커널은 paged cache와 직접 상호작용하는 메커니즘이 없으므로, ~PagedAttentionCache.update 메서드를 사용하여 캐시를 수동으로 읽고 씁니다. 시퀀스 길이가 커지면 이것이 병목 현상이 될 수 있습니다.
인덱싱 메커니즘
커널은 각 시퀀스에 대한 attention을 계산하기 위해 최대 시퀀스 길이(max_length_q, max_length_k)와 누적 시퀀스 길이(cu_seq_lens_q, cu_seq_lens_k)를 사용합니다.
예시
쿼리 길이가 [10, 3, 1]이고 키 길이가 [0, 1, 7]인 3개의 시퀀스로 이루어진 배치에 대해 생각해 보겠습니다:
cu_seq_lens_q = [0, 10, 13, 14]
cu_seq_lens_k = [0, 0, 1, 8]
max_length_q = 10
max_length_k = 7입력 형상:
Q: [1, 10+3+1, num_heads, head_dim] = [1, 14, num_heads, head_dim]
K or V: [1, 0+1+7, num_kv_heads, head_dim] = [1, 8, num_kv_heads, head_dim]커널은 누적 시퀀스 길이를 사용하여 각 쿼리 및 키/밸류 토큰을 시퀀스에 할당합니다:
Q request index: [r0, r0, r0, r0, r0, r0, r0, r0, r0, r0, r1, r1, r1, r2]
cu_seq_lens_q: 0____________________________________10__________13__14
K request index: [r1, r2, r2, r2, r2, r2, r2, r2] (r0 has 0 K tokens)
cu_seq_lens_k: 0,0_1_______________________8디코딩 경로
flash_attn_with_kvcache 커널은 각 시퀀스가 정확히 하나의 query 토큰을 가지는 decode 전용 배치만 처리합니다. varlen 경로보다 효율적이지만, prefilling 요청이 포함된 배치는 처리할 수 없습니다.
캐시 동작
이 커널은 block_table을 사용하여 paged cache에 접근하고, 이를 인덱싱한 뒤 인플레이스로 업데이트합니다. 블록 테이블의 shape은 (batch_size, max_blocks_per_seq)이며, 각 행에는 해당 요청의 KV cache 텐서 내 캐시 블록의 물리적 위치가 포함됩니다.
인덱싱 메커니즘
커널은 cache_seqlens를 사용하여 각 시퀀스의 캐시 길이를 가져옵니다. 각 쿼리 토큰이 서로 다른 시퀀스에 속한다고 가정합니다(시퀀스당 1개 토큰).
예시
쿼리 길이가 [1, 1, 1], 키 길이가 [30, 32, 70]인 3개의 시퀀스로 구성된 배치라고 가정해 보겠습니다. 캐시 블록 크기는 32이고, 시퀀스당 최대 블록 수는 4입니다.
캐시 시퀀스 길이는 단순히 키 길이입니다:
cache_seqlens = [30, 32, 70]블록 테이블의 모양은 (3, 4)입니다. 예시 주소를 사용하여:
block_table = [[2, -1, -1, -1],
[0, 1, -1, -1],
[3, 5, 6, -1]]-1 값은 할당되지 않은 블록을 나타냅니다.
- Sequence 0(캐시된 토큰 30개):
KV_cache[2]에 캐시됨. 새 토큰이 들어갈 수 있음(30 + 1 = 31 < 32). - Sequence 1(캐시된 토큰 32개):
KV_cache[0]와KV_cache[1]에 캐시됩니다. 32 + 1 > 32이므로 두 번째 블록이 필요합니다. - Sequence 2 (캐시된 토큰 70개):
KV_cache[3],KV_cache[5],KV_cache[6]에 캐시됨. 블록이 반드시 연속적이지 않을 수 있으며, 이것이 paged cache의 핵심 장점입니다. 새로운 토큰은 세 번째 블록에 들어갑니다.