~시연이의 우주~
AI 워크로드는 전력을 '다르게' 먹는다 - CPU·GPU 전력 비선형성 측정 시스템 Track A 구현기 본문
Preview) 들어가며 -- 왜 이게 문제일까?
ChatGPT 하나 쓰는 데 구글 검색 10번치 전력이 든다.
이런 말 들어본 적 있는가?
AI 서비스가 폭발적으로 성장하면서 데이터센터 전력 소비가 전 세계 에너지 이슈로 떠올랐다.
그런데 기존의 에너지 관리 모델들은 하나같이 같은 가정을 깔고 있다.
CPU 사용률이 두 배가 되면 전력도 두 배가 된다.
정말 그럴까?🤔
우리 팀은 이 가정이 틀렸다는 것을 실험으로 증명하고, 비선형적 전력 소비 패턴을 정밀하게 측정하는 시스템을 구현했다.
이 글에서는 Track A가 무엇을 하는 시스템인지, 어떻게 만들었는지, 그리고 어떤 결과를 얻었는지를 공유한다.
전체 소스코드:
https://github.com/Team37-OptimusPrime/TrackA
GitHub - Team37-OptimusPrime/TrackA: 전통적인워크로드와 AI워크로드 전력소비 패턴 비교
전통적인워크로드와 AI워크로드 전력소비 패턴 비교. Contribute to Team37-OptimusPrime/TrackA development by creating an account on GitHub.
github.com
이 글은 캡스톤디자인과창업프로젝트B (그로쓰) 37팀 Optimus Prime 팀의 Track A에 해당하며, 프로젝트 전체는 컴퓨터 자원 이용률과 에너지 소비량 간의 관계를 다각도로 분석하는 것을 목표로 한다.
1. Track A란?
Track A의 정식 명칭은 "컴퓨터 자원 이용률과 에너지 소비량 사이의 비선형성 분석"이다.
한 줄로 요약하면: 전통적인 워크로드 (정렬, 압축 등)와 AI 워크로드 (행렬 연산, 추론 등)가 CPU,GPU를 사용하는 방식이 다르고, 그 결과 전력 소비 곡선의 모양도 완전히 다르다는 것을 측정하고, 시각화하는 자동화 실험 시스템이다.

2. 시스템 구조 한눈에 보기
Track A는 4개의 핵심 모듈로 구성된다. 전체 흐름은 다음과 같다.
[R1: 환경 자동 검증]
[R2: 실시간 메트릭 수집] <--- 실험 실행 중 지속 동작
[R3: 실험 오케스트레이션] <--- 워크로드 실행 제어
[R4: 데이터 분석 및 시각화]
언어는 대부분 Python을 사용했으며 아주 일부 (전체 코드의 0.9%)로 Shell script를 사용했다.
코드는 scripts/ 와 workloads/ 디렉토리에 위치한다. 결과 그래프는 figures_v4/, 원시 데이터는 results_v4/에 저장된다.
3. 모듈 상세 설명
R1 -- 실험 전 환경 자동 검증
실험을 싲가하기 전에 환경이 올바르게 갖춰졌는지를 자동으로 점검하는 모듈이다.
잘못된 환경에서 수십 분짜리 실험을 돌리고 나서야 결과가 오염됐다는 것을 아는 사태를 막기 위해 설계됐다.
검증 항목은 세 가지다:
- 워크로드 스크립트 파일 존재 여부 및 Python 의존성 확인
- check_workload_scripts()
- check_python_libs()
- check_binaries()
- CPU와 GPU의 통제 조건 검증 (예: frequency scaling 설정)
- check_cpu_control()
- check_gpu_control()
- perf, nvidia-smi 등 계측 도구 가용성 확인
- check_load_tools()
- check_metric_tools()





‼️Note: R1이 실패하면 이후 모듈은 실행되지 않는다. 실험의 재현성을 높이기 위한 안전장치다.
R2 -- 실시간 메트릭 수집
워크로드가 실행되는 동안 CPU와 GPU 전력,사용률을 동시에, 지속적으로 수집한다.
수집 메트릭:
- CPU 전력: perf 또는 RAPL (Running Average Power Limit) 인터페이스
- GPU 전력: nvidia-smi --query-gpu=power.draw
- CPU 사용률: /proc/stat 파싱
- GPU SM 점유율: nvidia-smi --query-gpu=utilization.gpu
- 메모리 대역폭: Memory bandwidth utilization
# scripts/collector.py (핵심 로직 발췌)
import subprocess, time, csv
SAMPLE_INTERVAL = 0.5 # 초 단위 샘플링
def get_gpu_metrics():
out = subprocess.check_output([
"nvidia-smi",
"--query-gpu=power.draw,utilization.gpu,utilization.memory",
"--format=csv,noheader,nounits"
]).decode().strip()
power, util_gpu, util_mem = out.split(", ")
return float(power), float(util_gpu), float(util_mem)
def get_cpu_utilization():
with open("/proc/stat") as f:
line = f.readline()
fields = list(map(int, line.split()[1:]))
idle = fields[3]
total = sum(fields)
return 100.0 * (1.0 - idle / total)
def collect(duration_sec, output_path):
with open(output_path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["timestamp", "cpu_util", "gpu_power", "gpu_util", "gpu_mem_util"])
start = time.time()
while time.time() - start < duration_sec:
ts = time.time() - start
cpu = get_cpu_utilization()
gpu_pwr, gpu_util, gpu_mem = get_gpu_metrics()
writer.writerow([ts, cpu, gpu_pwr, gpu_util, gpu_mem])
time.sleep(SAMPLE_INTERVAL)
R3 -- 실험 오케스트레이션
Track A의 심장부다. 각 부하율 (utilization level) 별로 워크로드를 자동 실행하고, 실험 간 간섭을 최소화한다.
실험 사이클:
Warm-up (부하 측정 제외, 하드웨어 안정화)
->부하율별 워크로드 실행 (R2 수집 동시 진행)
->Cool-down (온도 기반 idle 진입 판정)
->다음 부하율로 이동
‼️핵심 제어 기법 두가지
1. CPU 워크로드: taskset으로 코어 수 제한
CPU 부하율을 단계적으로 올리기 위해 활성 코어 수를 조절한다.
전체 16코어 머신에서 2,4,8,16 코어 순으로 실행하면 약 12.5%, 25%, 50%, 100% 부하를 만들 수 있다.

2.GPU 워크로드: batch size로 SM 점유율 제어
GPU는 batch size를 키울수록 더 많은 SM(Streaming Multiprocessor)이 활성화된다.
GEMM(General Matrix Multiplication) 연산의 행렬 크기를 단계적으로 조절하여 GPU 점유율을 제어한다.

‼️온도 기반 cool-down 판정

R4 -- 데이터 분석 및 시각화
수집된 데이터를 바탕으로 총 6종의 그래프를 자동 생성한다.
핵심 분석 코드:
# scripts/analyze.py (핵심 로직 발췌)
import pandas as pd
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
def nonlinear_model(x, a, b, c):
"""비선형 전력 모델: P = a * x^b + c"""
return a * np.power(x, b) + c
def plot_power_curve(csv_path, label, color):
df = pd.read_csv(csv_path)
x = df["gpu_util"].values
y = df["gpu_power"].values
# 비선형 피팅
popt, _ = curve_fit(nonlinear_model, x, y, p0=[1, 2, 50])
x_fit = np.linspace(0, 100, 200)
y_fit = nonlinear_model(x_fit, *popt)
plt.scatter(x, y, alpha=0.3, color=color, label=f"{label} (raw)")
plt.plot(x_fit, y_fit, color=color, linewidth=2,
label=f"{label} fit: a={popt[0]:.2f}, b={popt[1]:.2f}")
plt.figure(figsize=(10, 6))
plot_power_curve("results_v4/traditional.csv", "Traditional", "blue")
plot_power_curve("results_v4/ai_workload.csv", "AI Workload", "red")
plt.xlabel("Utilization (%)")
plt.ylabel("Power (W)")
plt.title("Nonlinear Power Model: Traditional vs AI Workload")
plt.legend()
plt.savefig("figures_v4/power_comparison.png", dpi=150, bbox_inches="tight")
생성된 그래프 예시:

- CPU 이용률 vs CPU 전력 (전통 워크로드)
- GPU 이용률 vs GPU 전력 (AI 워크로드)
- 전통 vs AI 워크로드 전력 패턴 비교
- GEMM 행렬 크기별 전력 소비
- 메모리 대역폭 vs 전력
- 비선형성 모델 피팅 곡선
4. 전체 시스템 실행 방법
‼️환경 요구사항
- OS: Linux (Ubuntu 20.04 이상 권장)
- Python 3.8+
- CUDA가 지원되는 NVIDIA GPU
- nvidia-smi, perf, taskset 설치
👩💻 설치 및 실행
# 1. 레포지토리 클론
git clone https://github.com/Team37-OptimusPrime/TrackA.git
cd TrackA
# 2. Python 의존성 설치
pip install -r requirements.txt # torch, pandas, matplotlib, scipy 등
# 3. 환경 검증 (R1)
python scripts/precheck.py
# 4. 전체 실험 실행 (R2+R3 통합 진입점)
python scripts/run_experiment.py
# 5. 분석 및 시각화 (R4)
python scripts/analyze_data.py
# 결과 확인
ls figures_v4/ # 생성된 그래프 6종
ls results_v4/ # 원시 CSV 데이터
🔗실행 흐름 전체 요약
run_experiment.py
├── precheck.py (R1: 환경 검증)
├── collect_metric.py (R2: 메트릭 수집, 백그라운드 스레드)
├── run_experiment.py (R3: 워크로드 실행 제어)
│ ├── workloads/gemm.py
│ └── workloads/gpt2_infer.py
| └── workloads/gromacs_run.py
| | └──/prepare_gromacs_input.py
| └── workloads/matmul.py
| └── workloads/resnet.py
└── results_v4/*.csv (수집 데이터 저장)
↓
analyze_data.py (R4: 분석 + 시각화)
↓
figures_v4/*.png (결과 그래프 6종)
👀 부가기능 : watchdog.sh
장시간 실험 중 GPU 하드웨어를 보호하기 위해 watchdog.sh를 별도 tmux 세션에서 상시 실행한다.
이 스크립트는 nvidia-smi를 5초 간격으로 폴링하여 GPU 온도(상한 85°C)와 전력 소비(상한 260 W)를 감시하고, 어느 한쪽이라도 임계값에 도달하면 즉시 pkill로 워크로드 프로세스를 종료한 뒤 로그에 원인을 기록하고 스스로 종료한다.
메인 실험 스크립트(run_experiment.py)가 소프트웨어 레벨의 쿨다운 로직을 담당한다면, watchdog은 그보다 낮은 레이어에서 동작하는 하드웨어 안전망 역할을 하며, 두 프로세스가 서로 독립적으로 실행되기 때문에 실험 코드에 버그가 생기거나 쿨다운 판단이 지연되는 상황에서도 GPU를 보호할 수 있다.
(watchdog.sh와 실험스크립트를 tmux에서 동시 실행)
# 1. 새 세션 시작
tmux new-session -d -s exp
# 2. 왼쪽 창: 실험 스크립트
tmux send-keys -t exp 'python run_experiment.py --workload all' Enter
# 3. 오른쪽 창 분할
tmux split-window -h -t exp
# 4. 오른쪽 창: watchdog
tmux send-keys -t exp 'bash watchdog.sh' Enter
# 5. 세션 접속 (모니터링)
tmux attach -t exp
(종료 시)
# 세션 전체 종료
tmux kill-session -t exp
# 또는 세션 안에서
Ctrl+B, then D # detach (프로세스는 유지)
Ctrl+B, then & # 현재 창 종료
5. 실험 결과 -- 비선형성의 증거


CPU-centric 워크로드인 matrix multiplication과, GPU-centric 워크로드인 gemm_gpu를 비교했을때,
CPU-centric 워크로드는 CPU Busy (%)와 소비전력이 직선형태로 비례한다. 정비례에 가까운 형태이다.
하지만 GPU-centric 워크로드는 GPU Utilization (%)와 소비전력이 볼록 (convex) 형태로 비례한다. 즉, 정비례가 아니다.
이처럼 CPU 중심과 GPU 중심 워크로드의 소비전력 형태에도 차이가 있으며, 사용량과 비례하지 않는 경우가 있다는 것을 보여준다.

이는 전력 구성 비율을 보면 더욱 극명하게 차이가 난다.
| GPU centric | gpt2, resnet, gemm_gpu |
| CPU centric | gromacs, matmul, gemm_cpu |
당연하게도, CPU 중심 워크로드는 CPU 전력 사용량이 더 많고, GPU 중심 워크로드는 GPU 사용량이 더 많다.
따라서, 같은 CPU를 할당받았을때 어떤 워크로드는 할당받은 CPU로 많은 전력을 소비할 수도 있고, 반대로 어떤 워크로드는 비교적 적은 전력을 소비할 수도 있는 것이다.
따라서, 이러한 전력소비 특성을 고려한 전력 귀속 모델링이 필요하다는 것을 잘 보여준다.
🤓 Track B, C와의 연결
본 Track A에서 제시하고 증명한 문제인식을 바탕으로
Track B에서는 여러 워크로드를 동시 실행하여 각 워크로드의 소비 전력을 partitioning하고,
Track C에서는 Multi-tenant 환경에서 실제 도입 가능한 전력 귀속 모델을 제시한다.
6. 마치며
TrackA는 단순한 전력 측정 스크립트가 아니다.
실험 환경 검증부터 측정, 워크로드 제어, 분석, 시각화까지 End-to-End 실험 자동화 파이프라인이다.
AI 인프라의 에너지 효율이 갈수록 중요해지는 시대에, "얼마나 쓰느냐"만큼이나 "어떻게 쓰느냐"를 정확히 측정하는 것이 핵심이다. TrackA는 그 정밀한 측정의 첫 번째 단계다.
'프로젝트 > 졸업프로젝트' 카테고리의 다른 글
| 2025-2 캡스톤디자인과창업프로젝트A 기술블로그 (0) | 2025.11.27 |
|---|---|
| [개발일지] github 디렉토리 서버로 가져오기 (0) | 2025.11.20 |
| [문제해결]서버 드라이버 이슈 해결 (0) | 2025.11.18 |
| 졸업프로젝트...뭐하지? : 중간발표 이전까지 준비한 것들 (0) | 2025.10.22 |