> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sifi.life/llms.txt
> Use this file to discover all available pages before exploring further.

# ML/AI 성능 최적화와 GPU 사이징

## 5. ML/AI 성능 최적화

### 5.1 Model Serving 지연시간 최적화

| 최적화 영역             | 전략                     | 효과                    |
| ------------------ | ---------------------- | --------------------- |
| **콜드 스타트**         | Minimum Instances >= 1 | 첫 요청 지연 제거            |
| **모델 크기**          | ONNX 변환, 양자화           | 로드 시간 50\~80% 감소      |
| **GPU 선택**         | 모델 크기에 맞는 GPU          | 과도한 GPU는 비용 낭비        |
| **배치 요청**          | Batch Inference 활용     | 개별 요청 대비 10\~100x 처리량 |
| **Feature Lookup** | Online Table 활용        | Feature 조회 \< 10ms    |

```python theme={null}
# Model Serving 엔드포인트 설정 (최적화 버전)
import mlflow

# 모델 등록 시 최적화 힌트
mlflow.pyfunc.log_model(
    artifact_path="model",
    python_model=my_model,
    pip_requirements=["scikit-learn==1.3.0"],  # 최소 의존성
    metadata={"serving_optimization": "latency"}
)
```

### 5.2 배치 추론 병렬화

```python theme={null}
import mlflow
from pyspark.sql.functions import struct

# Spark UDF로 배치 추론 병렬화
model_uri = "models:/fraud_detection/production"
predict_udf = mlflow.pyfunc.spark_udf(spark, model_uri)

# 대용량 데이터셋에 병렬 추론 적용
predictions = (
    spark.table("catalog.schema.transactions")
    .withColumn("prediction", predict_udf(struct("feature1", "feature2", "feature3")))
)

# 최적화 팁: 파티션 수를 코어 수의 2~3배로 설정
predictions.repartition(spark.sparkContext.defaultParallelism * 2)
```

### 5.3 Vector Search 검색 속도 최적화

| 최적화 항목       | 권장 설정              | 이유                           |
| ------------ | ------------------ | ---------------------------- |
| **임베딩 차원**   | 768\~1536 (모델에 따라) | 불필요하게 큰 차원은 속도 저하            |
| **인덱스 유형**   | Delta Sync Index   | 자동 동기화, 운영 부담 최소             |
| **엔드포인트 크기** | 데이터 크기에 비례         | 1M 문서 미만: Small, 이상: Medium+ |
| **필터링**      | 메타데이터 필터 활용        | 검색 범위 축소로 속도/정확도 향상          |

```python theme={null}
# Vector Search 쿼리 최적화
results = index.similarity_search(
    query_text="고객 이탈 예측 방법",
    columns=["content", "source", "page"],  # 필요한 컬럼만 반환
    filters={"category": "ml", "year": 2025},  # 메타데이터 필터로 범위 축소
    num_results=5  # 필요한 만큼만 요청
)
```

***

## 6. GPU 클러스터 사이징

### 6.1 GPU 인스턴스 비교

| GPU 인스턴스         | GPU      | GPU 메모리 | 적합한 용도           | 시간당 비용 (USD, 대략) |
| ---------------- | -------- | ------- | ---------------- | ---------------- |
| **g5.xlarge**    | A10G × 1 | 24GB    | 소규모 파인튜닝, 추론     | \$1.01           |
| **g5.2xlarge**   | A10G × 1 | 24GB    | 파인튜닝 + 큰 CPU 메모리 | \$1.21           |
| **g5.12xlarge**  | A10G × 4 | 96GB    | 중규모 분산 학습        | \$5.67           |
| **g5.48xlarge**  | A10G × 8 | 192GB   | 대규모 분산 학습        | \$16.29          |
| **p4d.24xlarge** | A100 × 8 | 320GB   | LLM 파인튜닝, 대규모 모델 | \$32.77          |
| **p5.48xlarge**  | H100 × 8 | 640GB   | LLM 사전 학습, 초대규모  | \$98.32          |

### 6.2 모델 크기별 GPU 선택 가이드

| 모델 규모   | 파라미터 수  | 최소 GPU 메모리 | 권장 인스턴스                 | 비고                        |
| ------- | ------- | ---------- | ----------------------- | ------------------------- |
| **소형**  | \< 1B   | 8\~16GB    | g5.xlarge (A10G × 1)    | scikit-learn, XGBoost도 포함 |
| **중형**  | 1\~7B   | 24\~48GB   | g5.xlarge \~ g5.2xlarge | Llama 3 8B, Mistral 7B    |
| **대형**  | 7\~13B  | 48\~96GB   | g5.12xlarge (A10G × 4)  | Llama 3 13B               |
| **초대형** | 13\~70B | 160\~320GB | p4d.24xlarge (A100 × 8) | Llama 3 70B, DBRX         |
| **거대**  | 70B+    | 640GB+     | p5.48xlarge (H100 × 8)  | 사전 학습용                    |

> **참고**
> **GPU 메모리 계산 공식**: 모델 파라미터를 float16(2바이트)으로 로드할 때 필요한 GPU 메모리 = `파라미터 수 × 2바이트`. 예: 7B 모델 = 7 × 10^9 × 2 = 14GB. 학습 시에는 옵티마이저 상태와 그래디언트로 인해 **3\~4배** 추가 메모리가 필요합니다.

### 6.3 GPU 활용률 모니터링

```python theme={null}
# GPU 사용률 확인 (노트북에서)
import subprocess
result = subprocess.run(['nvidia-smi', '--query-gpu=utilization.gpu,memory.used,memory.total',
                        '--format=csv,noheader,nounits'], capture_output=True, text=True)
print(result.stdout)

# GPU 사용률 지속 모니터링 (학습 중)
# nvidia-smi dmon -s u -d 5  # 5초 간격으로 사용률 출력
```

| GPU 활용률     | 진단                 | 조치                          |
| ----------- | ------------------ | --------------------------- |
| **\< 30%**  | GPU 낭비 (데이터 로딩 병목) | 데이터 로더 최적화, num\_workers 증가 |
| **30\~70%** | 적정 (약간의 여유)        | 배치 사이즈 증가 시도                |
| **70\~95%** | 최적 활용              | 현재 설정 유지                    |
| **> 95%**   | OOM 위험             | 배치 사이즈 축소 또는 큰 GPU          |

***

## 7. 분산 학습 성능 튜닝

### 7.1 TorchDistributor 활용

```python theme={null}
from pyspark.ml.torch.distributor import TorchDistributor

def train_fn():
    import torch
    import torch.distributed as dist
    from torch.nn.parallel import DistributedDataParallel as DDP
    
    # 분산 환경 초기화 (TorchDistributor가 자동 설정)
    local_rank = int(os.environ.get("LOCAL_RANK", 0))
    device = torch.device(f"cuda:{local_rank}")
    
    model = MyModel().to(device)
    model = DDP(model, device_ids=[local_rank])
    
    optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4)
    
    for epoch in range(10):
        for batch in train_loader:
            loss = model(batch)
            loss.backward()
            optimizer.step()
            optimizer.zero_grad()
    
    return model

# Databricks에서 분산 학습 실행
distributor = TorchDistributor(
    num_processes=4,     # 총 GPU 수
    local_mode=False,    # 멀티 노드
    use_gpu=True
)
model = distributor.run(train_fn)
```

### 7.2 분산 학습 성능 최적화

| 최적화 항목                    | 전략                               | 효과                |
| ------------------------- | -------------------------------- | ----------------- |
| **데이터 로딩**                | num\_workers=4, pin\_memory=True | GPU 대기 시간 감소      |
| **배치 사이즈**                | GPU 메모리의 70\~80% 활용              | GPU 활용률 극대화       |
| **통신 백엔드**                | NCCL (GPU 간), Gloo (CPU)         | 그래디언트 동기화 속도      |
| **Mixed Precision**       | torch.cuda.amp                   | 메모리 50% 절감, 속도 2x |
| **Gradient Accumulation** | GPU 메모리 부족 시                     | 실효 배치 사이즈 증가      |

```python theme={null}
# Mixed Precision Training (메모리 절감 + 속도 향상)
from torch.cuda.amp import autocast, GradScaler

scaler = GradScaler()

for batch in train_loader:
    optimizer.zero_grad()
    
    with autocast():  # FP16으로 연산
        output = model(batch)
        loss = criterion(output, labels)
    
    scaler.scale(loss).backward()  # 그래디언트 스케일링
    scaler.step(optimizer)
    scaler.update()

# Gradient Accumulation (큰 배치 효과를 작은 GPU로)
accumulation_steps = 4
for i, batch in enumerate(train_loader):
    loss = model(batch) / accumulation_steps
    loss.backward()
    
    if (i + 1) % accumulation_steps == 0:
        optimizer.step()
        optimizer.zero_grad()
```

> **주의**
> **분산 학습 주의사항**: 노드 간 네트워크 대역폭이 중요합니다. Databricks에서 멀티 노드 학습 시 **EFA(Elastic Fabric Adapter)** 또는 고대역폭 네트워크가 지원되는 인스턴스(p4d, p5)를 사용하세요. 네트워크 병목이 있으면 GPU가 유휴 상태로 대기합니다.

***

## 8. Spark ML vs 단일 노드 성능 비교

### 8.1 선택 가이드

| 기준             | 단일 노드 (scikit-learn, XGBoost) | Spark ML                |
| -------------- | ----------------------------- | ----------------------- |
| **데이터 크기**     | \< 100GB (메모리 내)              | 100GB+ (분산 처리)          |
| **모델 복잡도**     | 높음 (딥러닝, 복잡한 앙상블)             | 낮\~중 (선형, 트리, 기본 앙상블)   |
| **Feature 수**  | 1000+                         | 100\~1000               |
| **학습 속도**      | 빠름 (단일 노드 최적화)                | 데이터 분산 오버헤드             |
| **하이퍼파라미터 튜닝** | Optuna, Hyperopt              | Spark ML CrossValidator |
| **MLflow 통합**  | 네이티브                          | 네이티브                    |

```python theme={null}
# 단일 노드: Pandas + scikit-learn (데이터 < 100GB)
import pandas as pd
from sklearn.ensemble import GradientBoostingClassifier
import mlflow

# Spark 테이블을 Pandas로 변환 (데이터가 메모리에 들어갈 때)
df = spark.table("catalog.schema.features").toPandas()

with mlflow.start_run():
    model = GradientBoostingClassifier(n_estimators=100)
    model.fit(df[features], df[target])
    mlflow.sklearn.log_model(model, "model")

# 분산: Spark ML (데이터 > 100GB)
from pyspark.ml.classification import GBTClassifier
from pyspark.ml.feature import VectorAssembler

assembler = VectorAssembler(inputCols=features, outputCol="features")
gbt = GBTClassifier(featuresCol="features", labelCol="target", maxIter=100)

pipeline = Pipeline(stages=[assembler, gbt])
model = pipeline.fit(spark.table("catalog.schema.features"))
```

### 8.2 하이브리드 패턴

```python theme={null}
# 대용량 데이터에서 Feature Engineering은 Spark로,
# 학습은 단일 노드로 하는 하이브리드 패턴

# Step 1: Spark로 대규모 Feature Engineering (분산)
features_df = (
    spark.table("catalog.schema.raw_data")  # 1TB
    .withColumn("feature_1", ...)
    .withColumn("feature_2", ...)
    .groupBy("entity_id")
    .agg(...)
)
features_df.write.saveAsTable("catalog.schema.features")  # 50GB

# Step 2: 학습용 샘플링 (50GB → 5GB)
sample_df = features_df.sample(fraction=0.1).toPandas()

# Step 3: 단일 노드에서 학습 (최적화된 라이브러리 활용)
import xgboost as xgb
model = xgb.XGBClassifier(tree_method="gpu_hist", gpu_id=0)
model.fit(sample_df[feature_cols], sample_df[target_col])

# Step 4: 전체 데이터에 Spark UDF로 추론 (분산)
predict_udf = mlflow.pyfunc.spark_udf(spark, "models:/my_model/production")
predictions = features_df.withColumn("prediction", predict_udf(struct(*feature_cols)))
```
