GPT랑 공부하니까 너무좋다.. 다들 GPT랑 공부하세요.. (물론 약간의 개념공부는 끝내고..)
1) LLM 단계
| 단계 | 용어 | 쉽게 말하면 | 예시 |
|---|---|---|---|
| 1 | Tokenization | 문장을 token으로 쪼갬 | "Explain HTTP" → 여러 token |
| 2 | Prompt | 사용자가 LLM에게 넣는 입력 | "Explain HTTP in one sentence." |
| 3 | Prefill | 요청 전송부터 첫 출력 token 수신까지 걸린 시간 | 질문을 "읽고 이해할 준비" |
| 4 | Decode | 모델이 답변 token을 하나씩 생성 | HTTP → is → a → ... |
| 5 | Response | 생성된 token들이 모여 최종 답변이 됨 | "HTTP is a protocol..." |
2) 측정값
| 항목 | 의미 | 쉽게 이해하기 |
|---|---|---|
prompt_eval_count | 입력 token 수 | 질문이 몇 token이야? |
prompt_eval_duration | 서버가 입력 prompt를 처리하는 데 걸린 시간 | 질문 처리하는 데 얼마나 걸렸어? |
eval_count | 출력 token 수 | 답변을 몇 token 만들었어? |
eval_duration | 출력 생성 시간 | 답변 만드는 데 얼마나 걸렸어? |
load_duration | 모델 로딩 시간 | 모델을 메모리에 올리는 데 얼마나 걸렸어? |
total_duration | 전체 처리 시간 | 처음부터 끝까지 얼마나 걸렸어? |
stream | 출력 전달 방식 | 답변을 조금씩 받을까, 한꺼번에 받을까? |
tok/s | 초당 token 생성량 | 1초에 답변을 몇 token 만들 수 있어? |
GPU: RTX 3050
VRAM: 3926 MiB / 8192 MiB
GPU Util: 5%
Process: /llama-server
1) thinking여부
| 실험 | Model | Tokens | Decode Time | Throughput |
|---|---|---|---|---|
| Thinking | Qwen3 4B | 259 | 4.17s | 62.1 tok/s |
| Thinking | Qwen3 4B | 947 | 14.88s | 63.6 tok/s |
| Instruct | Qwen3 4B Instruct | 2 | 0.017s | 짧아서 참고용 |
| Instruct | Qwen3 4B Instruct | 200 | 3.19s | 62.7 tok/s |
2) Prefill + TTFT (길이별)
| Prompt | 실제 입력 토큰 | Prefill | 출력 | Decode | 전체 |
|---|---|---|---|---|---|
| 짧음 | 15 | 28.2 ms | 20 | 314.9 ms | 392.3 ms |
| 중간 | 76 | 338.8 ms | 20 | 297.1 ms | 650.9 ms |
| 장문 | 194 | 92.2 ms | 20 | 295.8 ms | 405.4 ms |
-> 중간길이의 테스트가 장문보다 오래걸림. 좀더 확인요망 (캐시때문인가?)
3) HTTP 설명 요청을 10회 보내서 LLM의 첫 응답까지 걸리는 시간과 전체 응답 시간, 생성 속도를 측정.
| 회차 | TTFT | 전체 응답 시간 | 출력 Token | 생성 속도 |
|---|---|---|---|---|
| 1 | 30.24 ms | 578.37 ms | 37 | 67.62 tok/s |
| 2 | 32.54 ms | 587.84 ms | 34 | 61.33 tok/s |
| 3 | 31.46 ms | 532.05 ms | 34 | 68.01 tok/s |
| 4 | 29.71 ms | 609.03 ms | 37 | 64.00 tok/s |
| 5 | 27.92 ms | 622.20 ms | 37 | 62.35 tok/s |
| 6 | 38.02 ms | 555.61 ms | 34 | 65.75 tok/s |
| 7 | 24.88 ms | 579.96 ms | 34 | 61.33 tok/s |
| 8 | 25.06 ms | 592.20 ms | 37 | 65.36 tok/s |
| 9 | 28.55 ms | 596.12 ms | 37 | 65.30 tok/s |
| 10 | 25.60 ms | 528.41 ms | 34 | 67.76 tok/s |
전체요약
| 지표 | 평균 | P50 | P95 | 의미 |
|---|---|---|---|---|
| TTFT | 29.40 ms | 29.13 ms | 35.55 ms | 첫 번째 출력까지 걸린 시간 |
| 전체 응답 시간 | 578.18 ms | 583.90 ms | 616.27 ms | 요청부터 답변 완료까지 걸린 시간 |
이전 토큰의 K/V를 저장해서 Decode 때 재계산하지 않도록 하는 메모리.
요청이 많고 Context가 길어지면 KV Cache가 GPU VRAM을 많이 차지한다.
->fragmentation(메모리 파편화) 이슈 발생
PagedAttention - KV Cache를 작은 Block 단위로 관리해서 GPU 메모리를 더 효율적으로 사용하는 아이디어.이를 통해 LLM을 많은 요청에 효율적으로 Serving한다.(메모리 fragmentation을 줄이고 block 재사용을 쉽게 하는 것이 핵심)
[개인적인 비유]
- 캐시 저장방식은 뭐랄까.. 가상메모리같기도하고.. 포인터같기도한것같다..
- 먼저 끝난 프로세스가 나가고 그 자리에 새로운 프로세스가 들어오는 것
-> NodeJS에서의 Event loop방식이랑 비슷하다고 생각했는데 이건 아니라고한다. (동시에 여러프로세스가 돌아갈 수 있기 때문/그리고 PagedAttention과 Event Loop는 서로 다른 문제를 해결한다.)
| 요청 | 생성 토큰 | 완료 시간 |
|---|---|---|
| D | 200 | 8.21s |
| C | 100 | 9.75s |
| A | 200 | 12.81s |
| B | 30 | 13.28s |
관찰
- 동일한 시점에 4개 요청을 시작했지만 요청별 완료 시간이 크게 달랐음
- 생성 토큰 수가 적은 B(30 tokens)가 가장 늦게 완료되는 현상도 관찰됨
- 단일 요청에서 측정한 decode throughput과 비교하면 동시 요청 상황에서 요청별 latency가 크게 증가함
| 요청 | 토큰 | TTFT | 완료 |
|---|---|---|---|
| B | 30 | 0.35s | 0.80s |
| A | 300 | 0.82s | 5.46s |
| C | 300 | 5.50s | 10.08s |
| D | 300 | 10.12s | 14.70s |
| E | 300 | 13.94s | 19.34s |
관찰
- B가 0.80초에 완료된 후 E를 새로 요청했지만, E의 TTFT는 13.94초로 측정됨
- C, D, E의 TTFT가 앞선 요청의 처리 완료 시점과 유사한 간격으로 증가하는 현상이 관찰됨
- 요청이 동시에 GPU decode batch에 참여하고 있다고 보기 어려우며, 요청이 순차적으로 처리되거나 대기하는 구간이 존재할 가능성이 있음
→ 이번 실험을 통해 단순한 HTTP 동시 요청과 LLM Serving에서의 Continuous Batching은 서로 다른 개념임을 확인함.
→ 실제 Continuous Batching의 동작과 Request Scheduler를 확인하기 위해 vLLM 기반으로 추가 실험할 예정