본문으로 건너뛰기

RX 6650 XT 환경에서 speculative decoding의 에너지 측정 결과 공유

RX 6650 XT에서 speculative decoding은 부하가 높을수록 토큰당 에너지가 증가해 8스트림에서 +121%의 에너지 페널티를 보였고 배치로 토큰당 에너지를 약 3배 절감할 수 있었다.

이 요약은 AI가 원문을 분석해 생성했습니다. 정확한 내용은 원문 기준으로 확인하세요.

TL;DR

작성자는 RX 6650 XT와 llama.cpp Vulkan 환경에서 speculative decoding의 전력 효율을 측정해 단일 스트림에서 토큰당 에너지가 1.42J에서 1.56J로 약 10% 증가했고 8스트림에서는 0.47J에서 1.03J로 121% 증가하는 등 추측 검증 오버헤드가 GPU 부하가 높을수록 크게 악화된다는 결과를 보고했다. 전력은 LibreHardwareMonitor로 약 6Hz 샘플링해 각 생성 구간을 적분해 계산했으며 실험은 동일 프롬프트와 반복 측정, 드래프트 튜닝(--spec-draft-n-max 6 --spec-draft-p-min 0.75)을 통해 수용률을 92–94%로 개선한 상태에서도 타깃 단순 디코딩을 이기지 못했다. 반면 배치(동시성 증대)는 토큰당 에너지를 약 3배 낮추는 큰 이득을 보여 배치 최적화가 우선적인 비용·에너지 절감 수단임이 확인되었고 모델 크기 비율과 하드웨어·백엔드 의존성이 추측적 디코딩 효과를 결정한다고 결론지었다. 이 결과는 AMD/Vulkan 및 단일 GPU 환경에 대한 사례이며 NVIDIA/CUDA나 다른 모델 조합에서는 다른 결과가 나올 수 있어 추가 재현이 필요하다.

실용적 조언

  • 실험자는 먼저 GPU 패키지 전력만을 측정할 때에도 실제 소비 에너지(J)를 얻기 위해 전력 샘플을 고정 간격으로 폴링해 구간을 적분해야 한다고 권고했다. 전력 샘플링 주파수는 약 150ms 내외로 설정해 각 추론 구간과 정확히 매칭해야 하며 로그와 조건 윈도우를 동기화하면 J/token 계산이 가능하다. 이러한 절차는 추측적 디코딩의 에너지 영향 평가에서 필수적이다.
  • 추측적 디코딩을 실무에 적용하려면 드래프트 수용률, 드래프트/타깃 모델 크기 비율, 시스템 부하(동시성) 세 축을 먼저 평가해야 한다고 실험 결과가 시사한다. 수용률 튜닝이 가능하더라도 타깃 대비 드래프트의 상대적 실행 비용이 크면 에너지 이득이 사라질 수 있으므로 작은 모델 비율을 확보하거나 배치 최적화를 우선 적용하는 편이 효과적이다. 하드웨어·백엔드에 따라 행동이 달라지므로 NVIDIA/CUDA 환경에서의 재검증을 권장한다.

섹션별 상세

01
실험의 주된 관찰은 추측적 디코딩(speculative decoding)이 이 실험 환경에서는 속도나 에너지에서 '공짜' 이득을 주지 않았다는 것이다. 동일한 하드웨어와 소프트웨어(라즈베리 아님)에서 단일 스트림은 토큰당 에너지가 1.42J에서 1.56J로 약 10% 증가했고, 8스트림에서는 0.47J에서 1.03J로 121% 증가한 값이 측정됐다. 이 수치는 드래프트가 제안한 토큰을 검증하는 추가 연산과 높은 GPU 부하가 결합되면 검증 오버헤드가 전체 에너지 소비를 능가함을 보여준다.
02
측정 방식은 GPU 패키지 전력 센서를 약 6Hz로 폴링해 각 생성 구간의 전력을 적분해 실제 소비 줄(J)을 계산하는 방식이었다. 하드웨어는 RX 6650 XT, 소프트웨어는 llama.cpp(b9902) Vulkan 빌드와 llama-server를 사용했고 전력은 LibreHardwareMonitor로 수집해 조건별 윈도우와 매칭했다. 동일한 8개 프롬프트를 사용해 온전한 재현성을 확보하고 각 조건을 20~32회 평균해 결과의 일시적 편향을 줄였다.
powershell
param([string]$OutFile = "D:\\ai-energy-test\\power.csv")

[System.Reflection.Assembly]::LoadFrom("D:\\ai-energy-test\\lhm\\LibreHardwareMonitorLib.dll") | Out-Null

$pc = New-Object [LibreHardwareMonitor.Hardware.Computer]

$pc.IsGpuEnabled = $true

$pc.Open()

$gpu = $pc.Hardware | Where-Object { $_.HardwareType -eq 'GpuAmd' } | Select-Object -First 1

$sw = New-Object System.IO.StreamWriter($OutFile, $false)

$sw.AutoFlush = $true

$sw.WriteLine("ts,power,clock")

while ($true) {

  $gpu.Update()

  $p = ($gpu.Sensors | Where-Object { $_.SensorType -eq 'Power' -and $_.Name -eq 'GPU Package' } | Select-Object -First 1).Value

  $c = ($gpu.Sensors | Where-Object { $_.SensorType -eq 'Clock' -and $_.Name -eq 'GPU Core' } | Select-Object -First 1).Value

  $ts = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()

  $sw.WriteLine("$ts,$p,$c")

  Start-Sleep -Milliseconds 150

}

이 스크립트는 LibreHardwareMonitor 라이브러리를 로드해 GPU 패키지 전력을 약 150ms 간격으로 폴링해 타임스탬프와 함께 CSV로 기록하는 전력 로거 예시이다. 전력값과 GPU 코어 클럭을 기록하므로 추론 구간의 평균 전력과 총 에너지(J)를 계산할 수 있다. 실험 재현 시 전력 샘플링과 타임라인 동기화에 사용된다.

powershell
param(
  [int]$Port = 8090,
  [int]$Conc = 1,
  [int]$Waves = 4,
  [int]$NPredict = 256,
  [string]$Label = "cond",
  [string]$OutDir = "D:\\ai-energy-test\\results"
)
$ErrorActionPreference = 'Stop'
New-Item -ItemType Directory -Force $OutDir | Out-Null

$prompts = @(
  "Write a detailed explanation of how photosynthesis works, aimed at a curious teenager.",
  "Write a Python function that parses a CSV file and returns a dictionary of column statistics (mean, min, max). Include docstrings.",
  "Explain the causes of the First World War in a structured essay with clear paragraphs.",
  "Write a JavaScript function that debounces another function, with comments explaining each step.",
  "Describe a typical day in the life of a lighthouse keeper in the 1890s, in vivid detail.",
  "Write a SQL schema for a small library management system with books, members, and loans. Explain each table.",
  "Explain how vaccines train the immune system, using simple analogies.",
  "Write a Python class implementing a simple LRU cache with get and put methods, with comments."
)

$tmp = Join-Path $OutDir "tmp_$Label"
New-Item -ItemType Directory -Force $tmp | Out-Null

$startMs = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()
$allOut = @()
for ($w = 0; $w -lt $Waves; $w++) {
  $procs = @()
  for ($i = 0; $i -lt $Conc; $i++) {
    $p = $prompts[(($w * $Conc) + $i) % $prompts.Count]
    $body = @{ prompt = $p; n_predict = $NPredict; temperature = 0; cache_prompt = $false } | ConvertTo-Json
    $bodyFile = Join-Path $tmp "body_${w}_$i.json"
    $outFile = Join-Path $tmp "out_${w}_$i.json"
    [System.IO.File]::WriteAllText($bodyFile, $body, (New-Object System.Text.UTF8Encoding($false)))
    $procs += Start-Process -FilePath curl.exe -ArgumentList @('-s','-X','POST',"http://127.0.0.1:$Port/completion",'-H','Content-Type: application/json','-d',"@$bodyFile",'-o',$outFile) -NoNewWindow -PassThru
    $allOut += $outFile
  }
  $procs | Wait-Process
}
$endMs = [DateTimeOffset]::UtcNow.ToUnixTimeMilliseconds()

$tokens = 0; $draftN = 0; $draftAcc = 0; $reqs = 0
foreach ($f in $allOut) {
  $j = Get-Content $f -Raw | ConvertFrom-Json
  $tokens += [int]$j.timings.predicted_n
  $reqs++
  if ($null -ne $j.timings.draft_n) { $draftN += [int]$j.timings.draft_n; $draftAcc += [int]$j.timings.draft_n_accepted }
}

$rec = [pscustomobject]@{
  label = $Label; start_ms = $startMs; end_ms = $endMs
  conc = $Conc; waves = $Waves; requests = $reqs
  tokens = $tokens; draft_n = $draftN; draft_accepted = $draftAcc
}
$rec | ConvertTo-Json -Compress | Add-Content (Join-Path $OutDir "conditions.jsonl") -Encoding ascii
$rec | Format-List

이 스크립트는 여러 동시 요청을 llama-server에 보내 각 실험 조건의 시작·종료 시간과 예측 토큰 수·드래프트 통계를 기록해 전력 로그와 연동 가능한 조건 메타데이터를 생성한다. 동시성(Conc)와 파형(Waves)을 조절해 1스트림·8스트림 실험을 자동화하며 결과를 JSONL로 저장한다. 전력-작업 매칭과 J/token 계산을 위해 반드시 함께 실행해야 하는 스크립트이다.

powershell
$power = Import-Csv 'D:\\ai-energy-test\\power.csv' | ForEach-Object { [pscustomobject]@{ ts=[long]$_.ts; p=[double]$_.power } }
$conds = Get-Content 'D:\\ai-energy-test\\results\\conditions.jsonl' | ForEach-Object { $_ | ConvertFrom-Json }
$rows = foreach ($cd in $conds) {
  $w = $power | Where-Object { $_.ts -ge $cd.start_ms -and $_.ts -le $cd.end_ms }
  if ($w.Count -lt 2) { continue }
  $meanP = ($w.p | Measure-Object -Average).Average
  $durS = ($cd.end_ms - $cd.start_ms)/1000.0
  $acc = $null
  if ($cd.draft_n -gt 0) { $acc = [math]::Round(100.0*$cd.draft_accepted/$cd.draft_n,1) }
  [pscustomobject]@{
    label=$cd.label; tokens=$cd.tokens
    dur_s=[math]::Round($durS,1)
    tok_s=[math]::Round($cd.tokens/$durS,1)
    mean_W=[math]::Round($meanP,1)
    J_per_tok=[math]::Round(($meanP*$durS)/$cd.tokens,3)
    accept=$acc
  }
}
$rows | Format-Table -AutoSize

이 스크립트는 전력 CSV와 조건 JSONL을 합쳐 각 조건의 평균 전력, 초당 토큰, 토큰당 줄(J/token) 등을 계산해 요약 테이블을 만든다. 전력 샘플 타임스탬프와 조건 윈도우를 매칭해 실제 소비 에너지를 구하는 핵심 후처리 로직을 포함한다. 실험 결과의 통계적 평균과 토큰당 에너지 수치를 산출하는 마지막 단계이다.

03
드래프트 모델 튜닝의 영향이 구체적으로 관찰되었고 기본 설정에서는 수용률이 약 15%로 성능 저하가 심했으나 튜닝(--spec-draft-n-max 6 --spec-draft-p-min 0.75) 후 수용률이 92–94%로 상승했다. 수용률이 크게 개선되었음에도 불구하고 튜닝된 설정에서도 타깃 모델의 단순 디코딩보다 전체 에너지 비용이 낮아지지 않았다. 이 결과는 수용률 개선만으로는 검증 비용·모델 크기·하드웨어 부하의 상호작용을 상쇄하기 어렵다는 것을 의미한다.
bash
llama-server -m qwen2.5-3b-instruct-q4_k_m.gguf -md qwen2.5-0.5b-instruct-q4_k_m.gguf \
  --spec-type draft-simple -ngl 99 -ngld 99 --spec-draft-n-max 6 --spec-draft-n-min 0 --spec-draft-p-min 0.75 \
  -c 8192 -np 8 --port 8090

이 명령은 llama-server를 타깃 모델과 드래프트 모델을 함께 로드해 추측적 디코딩을 활성화하고 드래프트 정책을 튜닝한 서버 실행 예시이다. 핵심 플래그는 드래프트 타입, 드래프트 최대 토큰, 최소 수용 확률(spec-draft-p-min) 등으로 수용률과 성능 균형을 조절한다. 재현을 위해 동일한 llama.cpp 빌드와 옵션 사용이 요구된다.

04
배치(동시성)가 에너지 효율에 미치는 영향이 실험에서 가장 큰 변수로 나타났다. 1스트림에서 8스트림으로 전환(스펙 OFF)할 때 토큰당 에너지가 약 3배 감소해 고정 전력과 오버헤드를 여러 토큰으로 분산시키는 배치의 효과가 뚜렷했다. 또한 기존 발표 사례와 달리 이 실험에서 타깃과 드래프트의 크기 비율이 약 6배였기 때문에 드래프트 실행 비용이 상대적으로 높아 추측적 디코딩 이득이 작거나 음수로 전환될 가능성이 있었다.

용어 해설

추측적 디코딩(Speculative Decoding)
추측적 디코딩은 빠른 저용량 'draft' 모델로 미래 토큰을 미리 생성하고 이후 고성능 'target' 모델에서 검증하거나 대체해 전체 추론 비용을 줄이는 기법이다. 구체적으로는 draft가 제안한 토큰을 target이 검증하는 과정에서 성공 비율(acceptance rate)이 높을수록 이득이 발생하며 드래프트의 속도·정확도·모델 크기 비율이 핵심 변수이다. 데이터센터·엣지 환경에서 추론 지연과 에너지 소비를 절감하기 위해 사용된다.
드래프트 모델(Draft Model)
드래프트 모델은 추측적 디코딩에서 먼저 토큰을 생성하는 저비용·저지연 모델로서 제안 토큰을 만든 뒤 타깃 모델이 이를 검증하거나 이어서 생성하는 방식으로 동작한다. 드래프트의 추론 속도와 모델 크기가 작을수록 검증 오버헤드 대비 유리하지만 드래프트의 낮은 품질이 오히려 재검증 비용을 유발할 수 있다. 본 게시물에서는 Qwen2.5-0.5B가 드래프트로 사용되었다.
수용률(Acceptance Rate)
수용률은 드래프트가 제안한 토큰을 타깃 모델이 그대로 받아들이는 비율로, 추측적 디코딩의 유효성을 직접 결정하는 지표이다. 높은 수용률은 드래프트가 제안한 토큰을 재계산 없이 사용할 수 있음을 뜻해 전체 연산과 에너지 절감을 가능하게 한다. 게시물에서는 기본 설정에서 약 15%였던 수용률이 튜닝 후 92–94%로 상승했지만 전력 이득은 발생하지 않았다.
배치 처리(Batching)
배치 처리는 여러 요청을 묶어 한 번에 처리함으로써 GPU의 고정 전력과 메모리 접근 비용을 여러 토큰에 분산시키는 최적화 기법이다. 본 실험에서는 단일 스트림에서 다중 동시 스트림(8스트림)으로 바꾼 결과 토큰당 에너지가 약 3배 줄어드는 이득이 관찰되었다. 실무에서는 긴 대화나 높은 동시성 환경에서 비용·지연 최적화 수단으로 활용된다.

언급된 도구

llama.cpp추천

경량화된 로컬 추론을 위한 라이브러리와 서버 런타임을 제공해 Vulkan 빌드에서 모델을 로드하고 추론을 수행하는 데 사용되었다.

LibreHardwareMonitor추천

GPU 패키지 전력 센서를 폴링해 전력 로그를 CSV로 기록하는 데 사용된 도구로서 전력 적분을 통해 J/token 산출에 쓰였다.

curl중립

llama-server에 HTTP 요청을 보내 동시 요청 및 응답 타이밍을 수집하는 데 사용된 범용 클라이언트이다.

AI 분석 전체 내용 보기

AI 요약 · 북마크 · 개인 피드 설정 — 무료

출처 · 인용 안내

원문 발행 2026. 07. 08.수집 2026. 07. 08.출처 타입 REDDIT

인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.