b11412: llama : k-pool 모델에서 예상치 못한 그래프 재할당 문제 수정 (#29958)
요약
본 기사는 llama.cpp의 k-pool 모델에서 발생하던 예상치 못한 그래프 재할당 문제를 수정하는 내용을 다룹니다. 기존에는 컨텍스트 예약 방식과 실제 디코딩 과정 간에 불일치가 생겨 메모리 할당 오류가 발생했습니다. 이를 해결하기 위해 특정 API를 제거하고, 모든 ubatch의 경계를 정의하며 하나의 공유된 그래프 모양을 사용하도록 개선되었습니다.
핵심 포인트
- k-pool 모델의 그래프 재할당 문제를 수정하여 안정성을 높였습니다.
- 특정 `cache_safe` API와 조건부 `new_pool_rep` 사용이 제거되었습니다.
- 공유 셀을 가진 레이아웃이 풀링 과정을 정확히 결정하도록 개선되었습니다.
- llama : k-pool 모델에서 예상치 못한 그래프 재할당 문제 수정
k-pool 모델들은 상태에 의존하는 그래프 모양을 구축하는데, 전체 컨텍스트 예약(full-context reserve)으로는 알 수 없는 부분이 있습니다:
- qwen4exp는
inp->cache_safe에 분기하며, 이는llama_memory_seq_cp가 셀을 공유할 때 거짓이 됩니다 (예: batched-bench -pps):
QSA 레이어들은 scatter+gather를 fill+concat으로 교체하고new_pool_rep리프를 제거하여 디코드 그래프의 노드 수가 예약된 것보다 12개 적어졌습니다. - glm5-next는
gather = n_tokens <= 16 && n_kv > n_sel에 분기하며, 이로 인해 TG 디코드는 gather 모양(7564 노드)을 구축한 반면, 마지막 예약된 PP는 dense 모양(7762 노드)을 가졌습니다.
이러한 불일치 중 하나는 디코드 시간 재예약(decode-time re-reserve)을 강제하여 최악의 경우 크기를 제거하고 현재 상태를 고정합니다. 따라서 다음 상태 성장(n_pool, n_kv, n_new)은 변경되지 않은 그래프 크기에서 더 많은 공간이 필요하며, GGML_SCHED_DEBUG_REALLOC=1 하에서는 중단됩니다. 예를 들어 다음과 같이 재현할 수 있습니다:
GGML_SCHED_DEBUG_REALLOC=1 ./bin/llama-batched-bench
-hf ggml-org/GLM-5.3-Flash-GGUF:Q2_K -npp 2500 -ntg 32 -npl 1,2
-c 32768 -pps -kvu
항상 풀링된 키(pooled keys)를 scatter+gather하고, 컨텍스트 상수에서만 gather를 선택해야 합니다: n_ubatch는 모든 ubatch의 경계를 정의하며, top_k + kpool - 1은 n_sel을 제한합니다. 따라서 컨텍스트의 모든 그래프는 하나의 모양을 공유하게 되며, 이는 예약된 영역이 커버하고, dense 경로가 2.5k 및 16k 컨텍스트에서 gather 경로보다 더 빠르게 측정되었습니다.
Assisted-by: pi:llama.cpp/MiMo-V2.6-Flash-MOPD
- llama : 사용되지 않는 k-pool cache_safe 그래프 API 제거
k-pool 그래프는 더 이상 cache_safe에 분기하지 않으므로, 아무도 get_kpool_cache_safe()나 조건부 new_pool_rep을 읽지 않습니다. 두 모델 모두 항상 scatter 대상을 전달하며, 이제 set_input_kpool은 단순히 선호하는 것 대신 필요로 합니다.
또한 크기 전용 헬퍼인 kpool_build_sizes()에서 cache_safe 복사본도 제거합니다. 레이아웃과 상태 플래그 자체는 유지되며, 여전히 공유 셀을 가진 레이아웃이 어떤 풀링을 다시 해야 하는지 결정합니다.
Assisted-by: pi:llama.cpp/MiMo-V2.6-Flash-MOPD
- tests : shared-seq 그래프 예약 회귀 테스트 추가
프롬프트를 seq 0으로 디코딩하고, llama_memory_seq_cp를 통해 seq 1과 셀을 공유한 다음, 두 시퀀스를 모두 계속 디코딩합니다. k-pool 모델의 경우 공유는 cache_safe를 수행하며, 이는 풀이 계속 성장하는 동안 그래프 토폴로지를 변경합니다. 따라서 최악의 경우(worst-case)가 아닌 현재 상태(current state)로 재예약하는 스케줄러는 GGML_SCHED_DEBUG_REALLOC=1 하에서 중단됩니다. 이 테스트 등록은 해당 플래그를 설정하며, 테스트는 2220411 이전에 두 k-pool 모델 모두에서 중단됩니다.
kimi-linear와 minimax-01은 건너뜁니다. 이들은 n_seqs = 1로 최종 pp 그래프를 예약하기 때문입니다 (llama-context.cpp의 [TAG_RESERVE_DIAG_DECAY] 참조). 따라서 모든 다중 시퀀스(multi-seq) 그래프는 레이아웃이 다르며 설계상 재예약됩니다.
Assisted-by: pi:llama.cpp/MiMo-V2.6-Flash-MOPD
-
cont : TODO 추가
-
cont : 주석 수정
-
cuda: 빈 ubatch에 대한 moe 가중치 감소(weighted reduction) 일치시키기
ggml_cuda_match_moe_weighted_reduction은 행(rows)이 0인 텐서를 거부했습니다. 출력이 없는 ubatch는 inp_out_ids를 통해 마지막 레이어를 0행으로 축소하므로, graph_optimize가 그곳의 할당 종속성(alloc dep)을 제거했고 스케줄러 그래프는 예약된 것보다 노드가 하나 적어졌습니다. 이후 스케줄러는 해당 ubatch 크기로 재예약했으며, 같은 노드 개수이지만 더 큰 텐서를 가진 다음 ubatch는 GGML_SCHED_DEBUG_REALLOC=1 하에서 중단되었습니다.
컴퓨트 루프(compute loop)는 이미 어떤 융합(fusion)을 시도하기 전에 빈 노드를 건너뛰므로, 가드(guard)는 할당 종속성이 행 개수에만 의존하도록 만들었습니다.
- tests: 내부 심볼이 연결되는 곳에서만 롤백 테스트 빌드
공유 시퀀스(shared-seq) 케이스는 llm_arch_from_string을 호출하는데, libllama가 LLAMA_API를 통해 내보내지 않기 때문에 공유 라이브러리로 Windows에서 test-recurrent-state-rollback 연결이 실패합니다. 이제 이 빌드는 test-llama-archs 옆의 NOT WIN32 OR NOT BUILD_SHARED_LIBS 블록에 위치하며, 이미 등록된 테스트 아래에 있습니다.
- tests: 공유 시퀀스 예약 테스트에서 이름별 아키텍처 건너뛰기(skip archs by name in the shared-seq reserve test)
kimi-linear와 minimax-01을 건너뛴 이유는 이들이 llm_arch_from_string을 거치는데, libllama가 LLAMA_API를 통해 내보내지 않기 때문에 공유 라이브러리로 Windows에서 테스트 연결이 불가능했기 때문입니다. 이제는 general.architecture 문자열을 직접 비교하며, 테스트는 모든 플랫폼에서 다시 빌드됩니다.
공동 작성자: Pascal [email protected]
AI 자동 생성 콘텐츠
본 콘텐츠는 llama.cpp Releases의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기