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나 다른 모델 조합에서는 다른 결과가 나올 수 있어 추가 재현이 필요하다.
커뮤니티 반응
포스트는 재현 가능한 스크립트와 구체적 수치표를 포함해 많은 사용자가 추가 재현을 권유했고 NVIDIA/CUDA 및 다른 GPU 환경에서 결과가 어떻게 변하는지에 대한 요청이 다수 있었다. 일부는 Vulkan과 AMD 환경의 특성이 결과에 크게 작용할 수 있다고 지적했고 다른 일부는 모델 크기 비율과 드래프트 품질이 핵심 변수라는 점을 지지했다. 전반적으로 실험 설계와 수치 제공을 긍정적으로 평가하면서도 결과 일반화에는 주의가 필요하다는 반응이 우세했다.
주요 논점
작성자는 특정 하드웨어·설정에서는 speculative decoding이 오히려 에너지 페널티를 낳는다는 근거 있는 주장을 제시했고, 이는 수치(1stream +10%, 8stream +121%)와 재현 스크립트로 뒷받침된다.
일부 참가자는 결과가 RX 6650 XT와 Vulkan 환경에 특화되었을 수 있으며 CUDA/NVIDIA 환경에서는 다른 결과가 나올 여지가 있다고 지적했다.
배치(동시 스트림 증가)가 고정 전력 분산으로 토큰당 에너지 절감에 훨씬 큰 영향을 준다는 점은 실험에서 명확히 관찰되어 실무적 우선순위로 제시되었다.
합의점 vs 논쟁점
합의점
- 실험 참가자 대부분은 실험자가 제공한 전력 측정 방식과 다회 평균 절차가 재현 가능하고 신뢰할 만하다고 보았으며, LibreHardwareMonitor 폴링과 조건별 윈도우 매칭은 GPU 패키지 전력을 J로 통합해 토큰당 에너지를 산출하는 합리적 방법이라는 점에 동의했다. 많은 사람들이 실험자가 공개한 PowerShell 스크립트와 서버 플래그를 사용해 자신의 환경에서 검증하는 것이 필요하다고 권장했다. 이 합의는 실험 결과를 단일 데이터 포인트로 해석할 때 생길 수 있는 과대일반화를 억제하는 근거가 되었다.
- 대다수는 드래프트와 타깃 모델의 크기 비율이 추측적 디코딩의 유효성을 좌우하는 핵심 요소라는 점에 동의했다. 게시물의 저자는 이번 실험에서 타깃 모델이 드래프트보다 약 6배 크다고 밝혔고, 이는 문헌에서 종종 인용되는 70B/1B 같은 극단적 비율과 차이가 있어 결과 차이를 설명할 수 있다. 따라서 모델 비율과 드래프트 비용을 함께 고려해야 한다는 점이 공통된 관찰로 남았다.
- 커뮤니티는 배치가 GPU 고정 전력 오버헤드를 아문화하는 가장 효과적인 수단이라는 점에 대해 일치된 견해를 보였다. 해당 실험에서 1스트림에서 8스트림으로 갈 때 토큰당 에너지가 크게 감소한 실측값이 제시되어 이 주장을 뒷받침했다. 따라서 배치 최적화는 비용·에너지 절감에서 우선적으로 고려해야 할 실무적 조치로 인식되었다.
논쟁점
- 추측적 디코딩의 일반적 유용성은 논쟁거리가 되었고 일부는 데이터센터의 고성능 NVIDIA GPU 환경에서는 전력·지연 이득이 나타날 수 있다고 주장했다. 실험자는 본 사례가 AMD/Vulkan 및 특정 모델 조합에 한정된다는 점을 명확히 밝혔으나 일부 커뮤니티 멤버는 실험의 결론을 더 넓게 적용하는 경향을 보였다. 결과 해석의 범위와 하드웨어·백엔드 의존성에 대한 의견이 갈렸다.
- 드래프트 튜닝의 실무적 난이도와 기본 설정의 민감성도 분열된 의견을 불러일으켰다. 글 작성자는 기본 설정에서 수용률이 낮아 성능이 안 나왔고 튜닝으로 수용률을 92–94%로 올렸으나 여전히 전체 에너지 이득은 없었다고 보고했다. 일부는 더 공격적인 드래프트 파라미터나 다른 드래프트 모델 아키텍처를 시도하면 다른 결과가 나올 수 있다고 반박했다.
실용적 조언
- 실험자는 먼저 GPU 패키지 전력만을 측정할 때에도 실제 소비 에너지(J)를 얻기 위해 전력 샘플을 고정 간격으로 폴링해 구간을 적분해야 한다고 권고했다. 전력 샘플링 주파수는 약 150ms 내외로 설정해 각 추론 구간과 정확히 매칭해야 하며 로그와 조건 윈도우를 동기화하면 J/token 계산이 가능하다. 이러한 절차는 추측적 디코딩의 에너지 영향 평가에서 필수적이다.
- 추측적 디코딩을 실무에 적용하려면 드래프트 수용률, 드래프트/타깃 모델 크기 비율, 시스템 부하(동시성) 세 축을 먼저 평가해야 한다고 실험 결과가 시사한다. 수용률 튜닝이 가능하더라도 타깃 대비 드래프트의 상대적 실행 비용이 크면 에너지 이득이 사라질 수 있으므로 작은 모델 비율을 확보하거나 배치 최적화를 우선 적용하는 편이 효과적이다. 하드웨어·백엔드에 따라 행동이 달라지므로 NVIDIA/CUDA 환경에서의 재검증을 권장한다.
섹션별 상세
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)를 계산할 수 있다. 실험 재현 시 전력 샘플링과 타임라인 동기화에 사용된다.
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 계산을 위해 반드시 함께 실행해야 하는 스크립트이다.
$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) 등을 계산해 요약 테이블을 만든다. 전력 샘플 타임스탬프와 조건 윈도우를 매칭해 실제 소비 에너지를 구하는 핵심 후처리 로직을 포함한다. 실험 결과의 통계적 평균과 토큰당 에너지 수치를 산출하는 마지막 단계이다.
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 빌드와 옵션 사용이 요구된다.
용어 해설
- Speculative Decoding
- — 추측적 디코딩은 빠른 저용량 'draft' 모델로 미래 토큰을 미리 생성하고 이후 고성능 'target' 모델에서 검증하거나 대체해 전체 추론 비용을 줄이는 기법이다. 구체적으로는 draft가 제안한 토큰을 target이 검증하는 과정에서 성공 비율(acceptance rate)이 높을수록 이득이 발생하며 드래프트의 속도·정확도·모델 크기 비율이 핵심 변수이다. 데이터센터·엣지 환경에서 추론 지연과 에너지 소비를 절감하기 위해 사용된다.
- Draft Model
- — 드래프트 모델은 추측적 디코딩에서 먼저 토큰을 생성하는 저비용·저지연 모델로서 제안 토큰을 만든 뒤 타깃 모델이 이를 검증하거나 이어서 생성하는 방식으로 동작한다. 드래프트의 추론 속도와 모델 크기가 작을수록 검증 오버헤드 대비 유리하지만 드래프트의 낮은 품질이 오히려 재검증 비용을 유발할 수 있다. 본 게시물에서는 Qwen2.5-0.5B가 드래프트로 사용되었다.
- Acceptance Rate
- — 수용률은 드래프트가 제안한 토큰을 타깃 모델이 그대로 받아들이는 비율로, 추측적 디코딩의 유효성을 직접 결정하는 지표이다. 높은 수용률은 드래프트가 제안한 토큰을 재계산 없이 사용할 수 있음을 뜻해 전체 연산과 에너지 절감을 가능하게 한다. 게시물에서는 기본 설정에서 약 15%였던 수용률이 튜닝 후 92–94%로 상승했지만 전력 이득은 발생하지 않았다.
- Batching
- — 배치 처리는 여러 요청을 묶어 한 번에 처리함으로써 GPU의 고정 전력과 메모리 접근 비용을 여러 토큰에 분산시키는 최적화 기법이다. 본 실험에서는 단일 스트림에서 다중 동시 스트림(8스트림)으로 바꾼 결과 토큰당 에너지가 약 3배 줄어드는 이득이 관찰되었다. 실무에서는 긴 대화나 높은 동시성 환경에서 비용·지연 최적화 수단으로 활용된다.
언급된 도구
경량화된 로컬 추론을 위한 라이브러리와 서버 런타임을 제공해 Vulkan 빌드에서 모델을 로드하고 추론을 수행하는 데 사용되었다.
GPU 패키지 전력 센서를 폴링해 전력 로그를 CSV로 기록하는 데 사용된 도구로서 전력 적분을 통해 J/token 산출에 쓰였다.
llama-server에 HTTP 요청을 보내 동시 요청 및 응답 타이밍을 수집하는 데 사용된 범용 클라이언트이다.
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.