SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor

로컬 LLM 초당 토큰 처리량 측정 및 비용 효율 분석

GPU 대여 비용이 API 토큰 과금보다 저렴한지 확인하려면 직접 측정한 처리량이 필요합니다. 동시성 스윕을 통해 정확한 tokens per second를 산출하고, GPU 가동률에 따른 비용 효율을 계산하는 기준을 확인하십시오.

토큰당 처리 속도가 GPU 비용 효율을 결정하는 이유

토큰당 처리 속도(tokens per second)는 서버가 출력 텍스트를 생성하는 속도이며, GPU를 대여하는 것이 API 토큰당 비용을 지불하는 것보다 저렴한지 결정하는 기준이 됩니다. GPU 서버는 작업 중인지 유휴 상태인지와 관계없이 시간 단위로 요금이 청구됩니다. 반면 호스팅된 API는 토큰 단위로 과금됩니다. 따라서 GPU가 비용 효율을 가지려면 비용을 지불하는 시간 대부분 동안 충분히 높은 출력 속도를 유지해야 합니다.

즉, 어딘가에서 읽은 수치가 아니라 직접 측정한 데이터가 필요합니다. 이 페이지에서는 기록할 가치가 있는 4가지 수치를 정의하고, 해당 수치를 산출하는 명령어와 이를 바탕으로 의사결정을 내리는 계산식을 설명합니다.

공개된 초당 토큰 처리량 수치가 실제 사용자의 수치가 아닌 이유

DigitalOcean은 2026년 7월, vLLM 환경에서 FP8(8비트 부동 소수점)로 동작하는 단일 NVIDIA H200의 llama3.3-70b-instruct 처리량 수치를 발표했습니다. 이 수치는 유용하지만, 사용자의 실제 환경과는 다릅니다.

차트Published DigitalOcean H200 figures, llama3.3-70b-instruct FP8, July 2026
이 차트의 데이터
[
  {
    "config": "H200, one stream",
    "tok_s": "47"
  },
  {
    "config": "H100, saturated",
    "tok_s": "236"
  },
  {
    "config": "H200, saturated",
    "tok_s": "2,036"
  },
  {
    "config": "H200, saturated, in+out",
    "tok_s": "4,071.6"
  }
]

위 표의 모든 행은 해당 페이지에서 인용되었으며, 그중 두 개는 제시된 범위의 하한값이므로 최소치로 해석해야 합니다. 이 차트의 어떤 수치도 우리가 직접 측정한 것이 아닙니다.

마지막 두 행부터 살펴보겠습니다. 헤드라인 수치는 4,071.6 tok/s이며, 출력 전용 속도는 2,036 tok/s입니다. 헤드라인은 입력 토큰과 출력 토큰을 합산한 수치입니다. 해당 테스트는 1,024개의 입력 토큰과 1,024개의 출력 토큰을 사용했으므로, 헤드라인의 거의 절반이 출력에 해당합니다. 출력은 속도가 느린 절반에 해당하므로 이 구분은 중요합니다. 프리필(프롬프트 읽기)은 모든 입력 토큰을 한 번에 처리합니다. 디코드(답변 작성)는 한 번에 하나의 토큰을 생성합니다. 총 처리량 헤드라인은 저렴한 비용의 수치와 비싼 비용의 수치를 평균 낸 것입니다.

이제 첫 번째 행을 보겠습니다. 동일한 H200이 한 번에 하나의 요청을 처리할 때는 47 tok/s를 생성하므로, 포화 상태의 수치는 동일한 하드웨어에서 40배 이상 높습니다. 이러한 격차가 발생하는 이유는 단일 디코드 단계에서는 GPU가 대부분의 시간을 메모리 대기 상태로 보내기 때문이며, 동시 요청이 이러한 유휴 시간을 채워주기 때문입니다. 두 번째 행인 236 tok/s는 동일한 모델을 사용하는 단일 H100의 수치로, KV 캐시(서비스 중인 대화가 카드에 유지하는 요청별 메모리인 키 및 값 캐시)에 의해 제한됩니다. 80 GB 카드는 70B 모델에 대해 더 적은 동시 요청을 수용하므로 포화 지점이 더 낮습니다.

모델을 변경하거나 입력 대 출력 비율을 바꾸면 위의 모든 수치는 변합니다. 공개된 수치는 예산이 아닌 기대치를 설정하는 기준일 뿐이며, 이는 VPS 성능을 정직하게 벤치마킹할 때 디스크와 네트워크에 적용되는 규칙과 동일합니다.

중요한 4가지 지표

  • 첫 토큰 생성 시간(TTFT, Time to first token): 요청을 보낸 시점부터 첫 번째 출력 토큰이 도착할 때까지의 지연 시간입니다. 프리필(prefill) 시간과 대기열(queue) 시간을 합친 값이며, 사용자가 직접 체감하는 지표입니다.
  • 스트림당 초당 출력 토큰 수(Output tokens per second, per stream): 답변 생성이 시작된 후 글자가 작성되는 속도입니다. 대략 20 tok/s를 넘어가면 대부분의 사람이 읽는 속도보다 빠르므로, 그 이상의 속도는 큰 의미가 없습니다.
  • 포화 상태의 총 출력 처리량(Saturated total output throughput): 서버가 완전히 부하 상태일 때 모든 동시 스트림을 합친 처리량입니다. 이는 서버의 용량을 나타내는 수치이며, GPU 비용 효율을 결정짓는 지표입니다.
  • 동시성 환경에서의 p50 및 p99 TTFT: p50은 전체 요청의 중간값이며, p99는 100건의 요청 중 99건이 이 시간 이내에 처리됨을 의미합니다. 대기열 지연은 항상 p99에서 가장 먼저 나타납니다.

앞의 두 지표는 서버가 한가할 때 개선되고, 세 번째 지표는 서버가 바쁠 때 개선됩니다. 이 지표들은 서로 상충하기 때문에 단 하나의 숫자만으로 서버의 성능을 정의할 수 없습니다.

측정 전 입력 및 출력 길이를 고정하십시오

처리량은 트래픽의 형태에 따라 달라집니다. 4,000 토큰의 프롬프트에 50 토큰의 답변이 나오는 작업은 프리필(prefill) 부하가 큽니다. 반면 200 토큰의 프롬프트에 2,000 토큰의 답변이 나오는 작업은 디코드(decode) 부하가 큽니다. 동일한 서버라도 이 두 경우의 초당 토큰 처리량(tokens per second)은 크게 다르므로, 하나의 비율을 선택하여 기록하는 모든 수치 옆에 명시하고 서로 다른 비율 간에는 비교하지 마십시오. 여러 벤더가 해당 비율로 성능을 공개하므로 1,024 토큰 입력에 1,024 토큰 출력을 기본값으로 사용하는 것이 합리적입니다. 실제 트래픽을 알고 있다면 해당 트래픽을 사용하십시오.

출력 길이도 강제로 고정하십시오. 60 토큰 후 정지 토큰(stop token)에 도달하는 모델은 전체 실행과 비교할 수 없는 짧은 결과를 냅니다. 이 경우 TTFT가 전체 시간에서 차지하는 비중이 커져 벤치마크상 출력 처리량이 낮게 측정됩니다. 각 요청이 더 빨리 완료되더라도 말입니다. vLLM 벤치마크 클라이언트의 --ignore-eos 플래그를 사용하면 모든 요청이 정확히 요청된 수만큼 생성되므로 두 번의 실행 결과를 비교할 수 있습니다. 어떤 플래그보다도 모델 선택이 수치에 더 큰 영향을 미칩니다. 단일 VPS GPU에 Qwen 3 모델 탑재하기에서 해당 선택의 메모리 측면을 다룹니다.

단일 스트림 측정

가장 단순한 사례부터 시작합니다. 이는 정상 작동 여부를 확인하는 기준이자 성능의 상한선입니다. Ollama는 자체적으로 처리 시간을 출력합니다.

ollama run llama3.1:8b --verbose "Write 200 words about disk scheduling."

확인해야 할 항목은 eval rate으로, 초당 출력 토큰 수입니다. prompt eval rate는 프리필(prefill) 속도이며, load duration는 모델을 VRAM에 로드하는 데 소요된 시간입니다. 콜드 스타트 이후 첫 번째 호출에서는 load duration 값이 크기 때문에 total duration 수치는 왜곡될 수 있습니다. 명령을 두 번 실행하고 두 번째 결과를 확인하십시오. Ollama는 기본적으로 5분이 지나면 유휴 모델을 언로드하므로, 실행 사이에 긴 휴지기가 있으면 다시 콜드 스타트 상태가 됩니다.

동일한 필드 정보를 API를 통해 얻을 수 있으며, 이는 스크립트로 작성하기에 더 용이합니다.

curl -s http://127.0.0.1:11434/api/generate -d '{
  "model": "llama3.1:8b",
  "prompt": "Write 200 words about disk scheduling.",
  "stream": false
}' | jq '{eval_count, eval_duration,
         tok_s: (.eval_count / (.eval_duration / 1000000000))}'

eval_duration은 나노초 단위이므로 1,000,000,000으로 나누면 초 단위가 됩니다. 이 나눗셈은 Ollama 공식 API 문서에서 초당 토큰 수를 계산하기 위해 권장하는 방식입니다. 서버가 아직 준비되지 않았다면 Ollama를 이용한 VPS 기반 LLM 셀프 호스팅 문서에서 설치 및 systemd 유닛 설정 방법을 참조하십시오.

TTFT를 측정하려면 스트리밍 요청이 필요하며, curl을 사용하여 시간을 측정할 수 있습니다.

curl -s -o /dev/null -N \
  -w 'ttfb=%{time_starttransfer}s  total=%{time_total}s\n' \
  http://127.0.0.1:8000/v1/chat/completions \
  -H 'Content-Type: application/json' \
  -d '{"model":"Qwen/Qwen3-8B",
       "messages":[{"role":"user","content":"Write 200 words about disk scheduling."}],
       "stream":true,"max_tokens":256}'

time_starttransfer는 응답 본문의 첫 번째 바이트가 도착하는 시점입니다. 스트리밍 채팅 완료 요청에서 해당 바이트는 첫 번째 서버 전송 이벤트(SSE)에 해당하며, 이는 첫 번째 콘텐츠 토큰이거나 그 직전에 전송된 역할 전용 델타입니다. 따라서 이 값을 이벤트 하나 정도의 오차를 포함한 TTFT로 간주하십시오. 동일한 서버에서 두 번의 실행 결과를 비교하기에는 충분히 정확합니다.

단일 스트림 수치는 서버의 성능을 실제보다 높게 평가하게 만듭니다. TTFT는 앞서 대기 중인 요청이 없으므로 최상의 상태를 나타냅니다. 스트림당 처리 속도 역시 그래픽 카드 전체가 하나의 요청을 처리하므로 최상의 상태입니다. 이 수치들만으로는 서버의 실제 수용 능력을 알 수 없습니다.

동시성 스윕(concurrency sweep)은 어떻게 실행합니까?

스윕은 고정된 워크로드를 동시성을 높여가며 실행하고 각 단계에서 발생하는 결과를 기록합니다. vLLM은 이를 위한 클라이언트를 제공하며, 이 클라이언트는 OpenAI API를 사용하므로 Ollama를 비롯한 모든 OpenAI 호환 서비스에서 작동합니다.

vllm bench serve \
  --backend openai-chat \
  --base-url http://127.0.0.1:8000 \
  --endpoint /v1/chat/completions \
  --model Qwen/Qwen3-8B \
  --dataset-name random \
  --random-input-len 1024 \
  --random-output-len 1024 \
  --ignore-eos \
  --num-prompts 160 \
  --max-concurrency 16 \
  --percentile-metrics ttft,tpot,itl,e2el \
  --metric-percentiles 50,99

--max-concurrency은 진행 중인 요청 수를 제한하며, 스윕 과정에서 변경하는 변수입니다. --num-prompts은 전송된 총 요청 수이므로, 안정적인 평균값을 얻으려면 동시성의 약 10배 정도로 설정하십시오. 요약 결과에는 Output token throughput (tok/s):와 Total token throughput (tok/s):이 출력되며, Time to First Token 헤딩 아래에 Mean TTFT (ms):, Median TTFT (ms):, P99 TTFT (ms):이 표시됩니다.

출력 결과에 스트림당 속도는 포함되어 있지 않지만, 간단한 나눗셈으로 구할 수 있습니다. Mean TPOT (ms):은 첫 번째 토큰 이후의 토큰당 평균 처리 시간입니다. 예를 들어 토큰당 25 ms라면 스트림당 초당 40 토큰을 처리하는 셈입니다. 전체 출력 처리량을 동시성으로 나누어도 같은 결과가 나옵니다.

그런 다음 반복문을 사용하여 각 실행 결과를 저장하십시오.

for C in 1 4 16 32 64 128; do
  vllm bench serve \
    --backend openai-chat \
    --base-url http://127.0.0.1:8000 \
    --endpoint /v1/chat/completions \
    --model Qwen/Qwen3-8B \
    --dataset-name random \
    --random-input-len 1024 \
    --random-output-len 1024 \
    --ignore-eos \
    --num-prompts $(( C * 10 )) \
    --max-concurrency "$C" \
    --percentile-metrics ttft,tpot,itl,e2el \
    --metric-percentiles 50,99 \
    --save-result --result-filename "sweep-c$C.json"
done
저장된 JSON 파일 읽기

각 실행마다 파일이 하나씩 생성되므로, 모든 파일에서 필요한 필드만 한꺼번에 추출하십시오.

for f in sweep-c*.json; do
  jq -r --arg f "$f" \
    '[$f, .output_throughput, .total_token_throughput,
      .median_ttft_ms, .p99_ttft_ms] | @tsv' "$f"
done

output_throughput는 초당 출력 토큰 수입니다. total_token_throughput은 입력 토큰 수를 합산한 값이므로, 1:1 비율일 경우 거의 두 배가 됩니다. p99_ttft_ms이 존재하는 이유는 --metric-percentiles에 99가 포함되어 있기 때문입니다. 요청하지 않은 백분위수를 조회하면 jq는 null을 출력합니다.

동시성 스윕(concurrency sweep)은 실제로 무엇을 보여주는가?

차트Illustrative sweep shape: 8B model, one 24 GB GPU, 1024 in / 1024 out
이 차트의 데이터
[
  {
    "label": "1 stream",
    "per_stream_tok_s": 92,
    "total_tok_s": 92,
    "ttft_p50_ms": 48,
    "ttft_p99_ms": 61
  },
  {
    "label": "4 streams",
    "per_stream_tok_s": 88,
    "total_tok_s": 352,
    "ttft_p50_ms": 71,
    "ttft_p99_ms": 96
  },
  {
    "label": "16 streams",
    "per_stream_tok_s": 71,
    "total_tok_s": 1136,
    "ttft_p50_ms": 152,
    "ttft_p99_ms": 244
  },
  {
    "label": "32 streams",
    "per_stream_tok_s": 54,
    "total_tok_s": 1728,
    "ttft_p50_ms": 287,
    "ttft_p99_ms": 498
  },
  {
    "label": "64 streams",
    "per_stream_tok_s": 34,
    "total_tok_s": 2176,
    "ttft_p50_ms": 611,
    "ttft_p99_ms": 1240
  },
  {
    "label": "128 streams",
    "per_stream_tok_s": 18,
    "total_tok_s": 2304,
    "ttft_p50_ms": 1490,
    "ttft_p99_ms": 3820
  }
]

6개의 행은 소규모 대여 GPU 박스에서 스윕이 생성하는 형태를 그럴듯한 자릿수로 예시한 것입니다. 이는 귀하의 서버를 측정한 값이 아니며, 벤더가 제공하는 수치도 아닙니다. 위의 루프를 실행하여 귀하의 환경에 맞는 값으로 대체하십시오.

형태를 읽으십시오. 일반화할 수 있는 것은 바로 그 형태이기 때문입니다. 1개의 스트림에서 전체 박스는 초당 92개의 토큰을 생성하며, p99 TTFT는 61 ms입니다. 128 streams에서는 총 처리량이 초당 2304개의 토큰으로 25배 증가하지만, 개별 스트림의 속도는 초당 18개의 토큰으로 떨어지고 p99 TTFT는 3820 ms에 도달합니다. 배치 처리가 유휴 메모리 대기 시간을 유용한 작업으로 전환하기 때문에 전체 처리량은 상승합니다. 동일한 연산 자원을 공유하게 되므로 스트림당 속도는 하락합니다.

마지막 두 배 증가 구간이 핵심입니다. 64개에서 128개 스트림으로 늘리면 전체 처리량은 6% 미만으로 증가하는 반면, p99 TTFT는 거의 3배가 됩니다. 이는 KV 캐시가 가득 찼거나 서버가 vLLM의 max_num_seqs와 같은 스케줄링 제한에 도달하여 요청이 처리되지 않고 대기 중임을 의미합니다. 유용한 운영 지점은 그보다 앞선 구간입니다. 32개 스트림에서 해당 박스는 여전히 초당 1728개의 토큰(피크의 75%)을 반환하며, 스트림당 초당 54개의 토큰, p99 TTFT 498 ms의 성능을 보입니다. 이 지점을 귀하의 용량으로 보고하십시오. 곡선의 정점은 실제 사용자에게 서비스를 제공할 수 있는 수치가 아닙니다.

Ollama와 vLLM은 동일한 지표를 측정하지 않습니다

기본 Ollama 서버를 대상으로 해당 스윕(sweep)을 실행하면 전체 수치는 거의 변하지 않습니다. OLLAMA_NUM_PARALLEL의 기본값은 1이므로 하나의 요청이 실행되는 동안 나머지는 대기하며, 이 대기열로 인해 p99 TTFT는 상승하지만 전체 출력은 일정하게 유지됩니다. 측정을 시작하기 전에 이 값을 높이십시오.

sudo systemctl edit ollama.service
[Service]
Environment="OLLAMA_NUM_PARALLEL=8"

sudo systemctl restart ollama 옵션으로 재시작한 뒤, 모델이 여전히 메모리에 적재되는지 확인하십시오. 각 병렬 슬롯은 컨텍스트 윈도우의 일부를 점유하므로, Ollama 문서에 따르면 2K 컨텍스트에서 4개의 병렬 요청을 처리할 경우 8K가 할당됩니다. 슬롯 수를 너무 많이 높이면 모델이 VRAM 범위를 벗어납니다. ollama ps을 확인하십시오. PROCESSOR 열의 값이 48%/52% CPU/GPU와 같이 표시된다면 모델의 일부가 CPU로 넘어갔다는 의미이며, 이 경우 동시성을 높여도 처리량은 증가하지 않고 오히려 감소합니다. 병렬 슬롯을 초과한 요청은 기본값 512인 OLLAMA_MAX_QUEUE까지 대기열에 쌓이며, 그 이후에는 서버가 503 오류를 반환합니다.

vLLM은 연속 배치(continuous batching) 방식을 사용하므로 슬롯이 비는 즉시 새로운 요청을 실행 중인 배치에 포함합니다. 따라서 vLLM의 성능 곡선은 무언가 한계에 도달할 때까지 계속 상승합니다. 보통은 KV 캐시가 한계점이지만, max_num_seqs와 같이 설정된 제한이나 CPU 스케줄링 오버헤드 때문에 더 일찍 평탄화될 수도 있습니다. Ollama는 단일 모델, 단일 머신, 낮은 설정 비용에 최적화되어 있습니다. 따라서 두 엔진은 동일한 스윕에 대해 서로 다른 결과를 도출하며, 이것이 바로 서빙 엔진으로서의 Ollama와 vLLM 비교의 핵심 주제입니다. 모든 수치를 기록할 때는 어떤 엔진과 어떤 버전을 사용했는지 반드시 명시하십시오.

잘못된 지표를 측정하는 5가지 경우

  • 클라이언트가 너무 멀리 있습니다. 인터넷을 통해 노트북에서 벤치마킹을 수행하면 모든 TTFT에 왕복 지연 시간이 추가되므로, 결국 사용자의 가정용 네트워크 연결 상태를 측정하게 됩니다. 클라이언트를 서버와 동일한 리전에서 실행하십시오.
  • 모델이 준비되지 않았습니다(Cold). 첫 번째 요청은 가중치 로딩 비용을 발생시키며, vLLM의 경우 그래프 캡처 비용이 추가될 수 있습니다. 워밍업 배치를 먼저 보내고 해당 결과는 폐기하십시오.
  • 프리픽스 캐싱(Prefix caching)이 대신 응답했습니다. vLLM은 기본적으로 자동 프리픽스 캐싱을 활성화하므로, 동일한 프롬프트를 반복해서 보내면 프리필(prefill)이 아닌 캐시 성능을 측정하게 되어 TTFT가 실제 값보다 훨씬 낮게 나타납니다. --dataset-name random는 모든 프롬프트가 다르기 때문에 이러한 문제를 방지합니다. 확실하게 하려면 --no-enable-prefix-caching 옵션으로 서버를 시작하십시오.
  • 출력 길이가 너무 짧습니다. 32 토큰 정도의 짧은 답변에서는 TTFT가 각 요청의 대부분을 차지하므로, 초당 토큰 수(tokens per second) 지표는 사실상 프리필 성능만을 나타내게 됩니다. 현실적인 출력 길이를 설정하여 --ignore-eos을 사용하십시오.
  • 동시성(concurrency) 1인 경우만 보고했습니다. 이 수치는 결과표에서 가장 좋은 TTFT를 보여주지만, 실제 요청이 절대 겹치지 않는 경우에만 유효한 비용 입력값입니다. 요청이 겹친다면 비용은 실제 트래픽 환경의 동시성 수준에서 유지되는 처리량(throughput)에 따라 달라지므로, 해당 환경에서도 측정해야 합니다.

측정된 수치를 의사결정의 근거로 활용하기

스윕(sweep)을 통해 확인한 처리량(throughput)을 실제 트래픽이 도달하는 동시성(concurrency) 수준에서 산출한 뒤, 토큰당 과금 방식과 비교합니다. 이 수치는 요청이 충분히 겹쳐 배치(batch)가 가득 찰 때만 유효한 포화 상태의 수치입니다. 한 번에 하나의 요청만 보내는 워크로드는 단일 스트림 속도를 기준으로 계산해야 합니다. 손익분기점은 각 출력 토큰과 함께 들어오는 입력 토큰의 가격을 합산한 뒤 나누기 연산을 수행하면 도달할 수 있습니다.

cost_per_million_output = price_out + price_in * (input_tokens / output_tokens)
break_even_tok_s = (price_per_hour / cost_per_million_output) * 1000000 / 3600

DigitalOcean의 2026년 7월 가격을 예로 들어 계산해 봅니다. 당시 H200 전용 추론 엔드포인트는 시간당 $4.47였으며, 서버리스 Llama 3.3 70B는 입력 토큰 100만 개당 $0.65, 출력 토큰 100만 개당 $0.65였습니다. 위에서 사용한 1:1 비율을 적용하면 출력 토큰 100만 개당 입력 토큰 100만 개가 함께 발생하므로, 실질적인 가격은 출력 토큰 100만 개당 $1.30입니다. 따라서 4.47을 1.30으로 나누면 시간당 약 344만 개의 출력 토큰이 나오며, 이를 3,600초로 나누면 초당 약 955개의 출력 토큰, 즉 입력과 출력을 합쳐 초당 약 1,910개의 토큰을 처리할 수 있다는 계산이 나옵니다. 가격은 해당 업체의 정책이며, 계산은 사용자의 몫입니다. 2026년 10월 10일 확인 결과 H200 엔드포인트 가격은 여전히 시간당 $4.47였으나, DigitalOcean은 2026년 8월 18일부로 서버리스 Llama 3.3 70B 서비스를 종료하고 Llama 4 Maverick으로 전환했습니다. 이 모델의 가격은 입력 토큰 100만 개당 $0.25, 출력 토큰 100만 개당 $0.87입니다. 모델이 변경되었으므로 비교가 의미를 가지려면 다시 스윕을 수행해야 합니다.

이 결정의 핵심 단어는 지속성(sustained)입니다. 포화 상태에서 초당 955개의 출력 토큰을 하루에 2시간 동안 처리한다고 해서 이를 초당 955개의 지속적인 출력 토큰 처리량이라고 할 수는 없습니다. 나머지 22시간에 대해서도 비용을 지불해야 하기 때문입니다. GPU Droplet으로 카드를 대여한다고 해서 기준이 낮아지지는 않습니다. 2026년 10월 10일 기준 DigitalOcean의 Droplet 가격표에 따르면 H200은 온디맨드 방식으로 시간당 $4.47로 엔드포인트와 동일했습니다. 가장 저렴한 NVIDIA Droplet인 RTX 4000(시간당 $0.76)이나 L40S 또는 RTX 6000(시간당 $1.57)은 70B 모델을 FP8로 구동하기에는 용량이 너무 작습니다. 따라서 위 수치를 기준으로 볼 때, 초당 2,036개의 출력 토큰에서 포화되는 H200이 입력 및 출력 토큰 100만 개당 $0.65라는 가격과 동일한 효율을 내려면, 비용을 지불하는 매 시간마다 최대 성능의 약 47퍼센트를 평균적으로 유지해야 합니다. 이 수치 미만으로 운영된다면 토큰당 과금 방식이 더 유리합니다. 자가 호스팅의 경제성을 떨어뜨리는 주된 요인은 토큰 처리 속도가 아니라 유휴 GPU 시간입니다.

결론적으로 의사결정에는 두 가지 입력값이 필요합니다. 스윕은 성능의 상한선을 제공하며, 트래픽 패턴은 그 상한선 중 실제로 활용하는 비율을 결정합니다. 두 값을 곱한 뒤 그 결과를 GPU VPS와 토큰당 API 손익분기점 비교에 대입하여 본인의 트래픽 규모에 맞는 답을 확인하십시오.

FAQ

자체 호스팅 LLM에서 적절한 초당 토큰(tokens per second) 수치는 얼마입니까?

이 지표는 두 가지 역할을 하므로 답변도 두 가지입니다. 한 명의 사용자가 출력물을 읽는 경우, 스트림당 초당 약 20 토큰 이상이면 이미 읽기 속도보다 빠르므로 그 이상의 수치는 의미가 없습니다. 비용 측면에서 중요한 수치는 실제 부하 상황에서 유지할 수 있는 총 출력 처리량이며, 적절한 수치란 손익분기점을 넘길 수 있는 수준을 의미합니다. 2026년 7월 가격 기준으로 시간당 4.47달러인 서버에서 입력과 출력을 합쳐 100만 토큰당 0.65달러인 서비스와 비교할 때, 1:1 비율로 유지해야 하는 최소 처리량은 초당 약 955 출력 토큰입니다. 대규모 모델에서 단일 스트림으로는 이 수치에 도달할 수 없으며, 이것이 배치(batching) 처리가 존재하는 이유입니다.

동시 요청을 추가해도 왜 Ollama의 처리량이 그대로입니까?

OLLAMA_NUM_PARALLEL 기본값이 1로 설정되어 있어 서버는 모델당 한 번에 하나의 요청만 처리합니다. 나머지는 OLLAMA_MAX_QUEUE(기본값 512)까지 큐에 대기하며, 그 이상은 503 오류를 반환합니다. GPU가 바쁜 것이 아니라 큐가 쌓이고 있다는 신호로, 총 출력량은 그대로 유지되면서 p99 TTFT(Time To First Token)는 상승합니다. systemd 드롭인 파일에서 변수를 설정하고 재시작한 뒤 ollama ps을 확인하십시오. 병렬 슬롯이 늘어날 때마다 할당된 컨텍스트가 곱해지며 모델의 일부가 CPU로 밀려날 수 있기 때문입니다.

첫 토큰 생성 시간(TTFT)과 초당 토큰 수 중 무엇을 측정해야 합니까?

둘 다 측정해야 합니다. 부하가 증가함에 따라 두 지표는 반대 방향으로 움직이기 때문입니다. TTFT는 사용자가 체감하는 성능이며, 포화 상태의 출력 처리량은 청구서에 반영되는 비용 효율성을 나타냅니다. 모든 동시성 단계에서 p99 TTFT를 기록한 뒤, p99 TTFT가 허용 가능한 범위 내에 있는 가장 높은 동시성 수준을 선택하십시오. 해당 지점의 처리량을 시스템의 용량으로 보고해야 하며, 성능 곡선 최상단의 최대치를 용량으로 삼아서는 안 됩니다.

초당 토큰 수가 높으면 항상 토큰당 비용이 낮아집니까?

아닙니다. 토큰당 비용은 시간당 서버 비용을 해당 시간에 실제로 처리한 토큰 수로 나눈 값입니다. 따라서 하루 중 대부분 유휴 상태인 빠른 서버는 토큰당 비용이 높습니다. 비용을 결정하는 것은 최대 속도가 아니라 가동률(utilisation)입니다. 단위도 주의 깊게 확인하십시오. 명시된 총 토큰 처리량은 입력 토큰을 포함하는 경우가 많으므로, 입력과 출력 비율이 1:1일 때 실제 출력 속도의 거의 두 배에 달합니다. 비교 대상인 API가 출력뿐만 아니라 입력 토큰에 대해서도 과금한다면, 비교하기 전에 양쪽 비용을 모두 계산하십시오.

#benchmarking#tokens-per-second#vllm#ollama#gpu-vps