본문 바로가기
[GPUaaS]

[GPU 사용률 보정 포함] 월별 GPU 리포트 Lambda (Advanced)

by METAVERSE STORY 2026. 1. 7.
반응형

 

 

아래는 **GPU-Hour + 평균 GPU 사용률 보정까지 포함한 “월별 GPU 리포트 Lambda 고급 버전”**입니다.
👉 실제 차지백(Chargeback) 분쟁이 거의 없는 방식
👉 대기업·연구기관에서 가장 많이 쓰는 정산 로직입니다.


 

1️⃣ 정산 로직 요약 (핵심)

✅ 최종 비용 계산식

 
최종 비용 = GPU-Hour × GPU 단가 × 사용률 보정 계수

✅ 사용률 보정 계수 표 (권장)

평균 GPU 사용률보정 계수
70% 이상 1.0
40 ~ 69% 0.8
20 ~ 39% 0.6
20% 미만 0.4

2️⃣ Prometheus 쿼리 (2개 사용)

① 월별 GPU 사용 시간 (GPU-Hour)

 
sum by (namespace, modelName) ( count_over_time( DCGM_FI_DEV_GPU_UTIL > 0 [30d]) )

② 월 평균 GPU 사용률

 
avg by (namespace, modelName) ( DCGM_FI_DEV_GPU_UTIL )

3️⃣ Lambda 환경 변수 (추가 포함)

변수명설명
PROMETHEUS_URL Prometheus URL
S3_BUCKET 리포트 저장 버킷
S3_PREFIX reports/gpu
GPU_PRICE_A100 A100 단가
GPU_PRICE_T4 T4 단가
GPU_PRICE_A10G A10G 단가

4️⃣ Lambda Python 코드 (고급 버전)

 
import os import csv import requests import boto3 from datetime import datetime, timedelta PROM_URL = os.environ['PROMETHEUS_URL'] S3_BUCKET = os.environ['S3_BUCKET'] S3_PREFIX = os.environ.get('S3_PREFIX', 'reports/gpu') GPU_PRICE = { "A100": float(os.environ.get("GPU_PRICE_A100", 4000)), "T4": float(os.environ.get("GPU_PRICE_T4", 900)), "A10G": float(os.environ.get("GPU_PRICE_A10G", 1500)), } s3 = boto3.client('s3') def query_prometheus(query): r = requests.get( f"{PROM_URL}/api/v1/query", params={"query": query}, timeout=15 ) r.raise_for_status() return r.json()['data']['result'] def utilization_factor(util): if util >= 70: return 1.0 elif util >= 40: return 0.8 elif util >= 20: return 0.6 else: return 0.4 def lambda_handler(event, context): # 전월 계산 today = datetime.utcnow() first_day = today.replace(day=1) last_month = first_day - timedelta(days=1) report_month = last_month.strftime("%Y-%m") # PromQL gpu_hour_q = """ sum by (namespace, modelName) ( count_over_time( DCGM_FI_DEV_GPU_UTIL > 0 [30d]) ) """ avg_util_q = """ avg by (namespace, modelName) ( DCGM_FI_DEV_GPU_UTIL ) """ gpu_hours = query_prometheus(gpu_hour_q) avg_utils = query_prometheus(avg_util_q) # 평균 사용률 매핑 util_map = {} for u in avg_utils: key = ( u['metric'].get('namespace', 'unknown'), u['metric'].get('modelName', 'unknown') ) util_map[key] = float(u['value'][1]) rows = [] for g in gpu_hours: namespace = g['metric'].get('namespace', 'unknown') model = g['metric'].get('modelName', 'unknown') hours = float(g['value'][1]) avg_util = util_map.get((namespace, model), 0.0) factor = utilization_factor(avg_util) price = GPU_PRICE.get(model, 0) raw_cost = hours * price final_cost = raw_cost * factor rows.append([ report_month, namespace, model, round(hours, 2), round(avg_util, 2), factor, price, round(final_cost, 2) ]) filename = f"gpu-usage-advanced-{report_month}.csv" path = f"/tmp/{filename}" with open(path, "w", newline="") as f: writer = csv.writer(f) writer.writerow([ "Month", "Namespace", "GPU_Model", "GPU_Hours", "Avg_GPU_Util(%)", "Util_Factor", "Price_per_Hour", "Final_Cost" ]) writer.writerows(rows) s3_key = f"{S3_PREFIX}/{filename}" s3.upload_file(path, S3_BUCKET, s3_key) return { "status": "success", "report": f"s3://{S3_BUCKET}/{s3_key}", "rows": len(rows) }

5️⃣ 생성되는 CSV 리포트 예시

MonthNamespaceGPUGPU-HoursAvg UtilFactorCost
2025-12 team-ai A100 320 78% 1.0 1,280,000
2025-12 team-data T4 210 35% 0.6 113,400

👉 “GPU는 썼지만 효율이 낮으면 비용도 줄어드는 구조”


6️⃣ 실무 운영 팁 (중요)

✔ 왜 이 방식이 좋은가?

  • GPU 점유만 하고 놀리는 문제 방지
  • 팀 간 비용 분쟁 최소화
  • 사용자 스스로 GPU 효율 개선 유도

✔ 감사/재무 대응에 강함

  • “사용 시간 + 사용률” 근거 명확
  • 수작업 계산 불필요
  • 월별 이력 추적 가능

 

 

반응형

댓글