mcpField
G
gpu-optimizer

gpu-optimizer

github.com/mathews-tom开发337131 次安装2 天前更新
代码仓库

关于 gpu-optimizer

GPU Optimizer 是一项面向消费级 NVIDIA GPU 的优化技能,适用于使用 PyTorch、XGBoost 和 RAPIDS 的开发者。它提供代码前后对照、显存管理与性能诊断建议,范围针对单 GPU 和 8–24GB 显存设备。

主要功能

  1. 01优化 XGBoost GPU 训练
  2. 02提供 PyTorch 混合精度与编译建议
  3. 03管理显存并监控用量
  4. 04将 NumPy 和 Pandas 工作迁移至 GPU
  5. 05提供性能分析与故障排查

适用场景

  1. 01降低模型训练的显存占用
  2. 02加速 XGBoost 训练与推理
  3. 03将大型数组或表格处理迁至 GPU
  4. 04定位 GPU 训练瓶颈

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mathews-tom/armory --skill gpu-optimizer

安装后在 Claude Code 中输入/gpu-optimizer确认已加载。

附带文件evals/cases.yaml

详细介绍

GPU 优化器

面向配备 8–24GB VRAM 的消费级 GPU 的专家级 GPU 优化。仅采用有证据支持的模式。

硬件配置

应用优化前,请填写硬件信息:

属性你的值
GPU 型号(例如:RTX 4080 Mobile、RTX 3090、RTX 4090)
VRAM(例如:12GB、16GB、24GB)
CUDA 版本(nvidia-smi → 右上角)
TDP / 功率限制(笔记本电脑与台式机会影响持续吞吐量)
驱动程序版本(nvidia-smi → 左上角)

关键限制:VRAM 容量决定适用的策略。下方模式会在相关处标注最低 VRAM 要求。

优化类别

1. XGBoost GPU 加速

DMatrix 与 QuantileDMatrix:

# GPU-optimized: QuantileDMatrix is 1.8x faster
dtrain = xgb.QuantileDMatrix(X_train.astype(np.float32))
dval = xgb.QuantileDMatrix(X_val.astype(np.float32))

# Standard: DMatrix (use for inference only)
dtest = xgb.DMatrix(X_test.astype(np.float32))

关键参数:

params = {
    'tree_method': 'hist',        # GPU-accelerated histogram
    'device': 'cuda:0',           # Explicit GPU device
    'max_bin': 256,               # Higher bins = better splits (VRAM permitting)
    'grow_policy': 'depthwise',   # vs 'lossguide' for imbalanced data
    'predictor': 'gpu_predictor', # GPU inference
}

# Training with explicit device
model = xgb.train(params, dtrain, num_boost_round=100)

GPU 验证(快速失败):

def verify_gpu():
    """Verify XGBoost GPU availability. Raises if unavailable."""
    import subprocess
    try:
        result = subprocess.run(["nvidia-smi"], capture_output=True, text=True)
        if result.returncode != 0:
            raise RuntimeError("nvidia-smi failed - no GPU available")
    except FileNotFoundError:
        raise RuntimeError("nvidia-smi not found - no GPU available")

    build_info = xgb.build_info()
    if not build_info.get("USE_CUDA"):
        raise RuntimeError("XGBoost not compiled with CUDA support")

内存管理:

# Single-pass training (reuse QuantileDMatrix across slots)
dtrain = xgb.QuantileDMatrix(X_train.astype(np.float32))
for slot_idx in range(num_slots):
    dtrain.set_label(y_train[:, slot_idx])  # Reuse matrix
    model = xgb.train(params, dtrain, num_boost_round=100)
2. PyTorch 混合精度

BF16(优先)与 FP16:

from torch.amp import autocast, GradScaler

# Auto-detect best precision
if torch.cuda.is_bf16_supported():
    amp_dtype = torch.bfloat16  # Ampere+ GPUs support BF16
else:
    amp_dtype = torch.float16

# Training step
scaler = GradScaler('cuda') if amp_dtype == torch.float16 else None

with autocast('cuda', dtype=amp_dtype):
    output = model(input_ids, attention_mask)
    loss = criterion(output, targets)

# Backward with scaling (FP16 only)
if scaler:
    scaler.scale(loss).backward()
    scaler.step(optimizer)
    scaler.update()
else:
    loss.backward()
    optimizer.step()

BF16 优于 FP16 的原因:

  • 指数范围与 FP32 相同(不会溢出或下溢)
  • 无需 GradScaler(代码更简单)
  • Ampere 及更新架构的 GPU 配备原生 BF16 Tensor 核心
3. VRAM 管理

梯度检查点:

# Saves ~40% VRAM, adds ~20% compute time
model.gradient_checkpointing_enable()

# For transformers:
model.base_model.model.gradient_checkpointing_enable()

VRAM 监控:

import torch

torch.cuda.reset_peak_memory_stats()
# ... training ...
peak_vram_gb = torch.cuda.max_memory_allocated() / 1024**3
print(f"Peak VRAM: {peak_vram_gb:.2f} GB")

# Clear cache between experiments
torch.cuda.empty_cache()

梯度累积:

# Simulate larger batch size without OOM
grad_accum_steps = max(1, target_batch_size // actual_batch_size)

for i, batch in enumerate(dataloader):
    loss = model(batch) / grad_accum_steps
    loss.backward()

    if (i + 1) % grad_accum_steps == 0:
        optimizer.step()
        optimizer.zero_grad()

用于 VRAM 优化的实验设计(DoE):

EXPERIMENTS = [
    {"batch_size": 2,  "seq_len": 128, "grad_ckpt": True,  "amp": "bf16"},
    {"batch_size": 4,  "seq_len": 256, "grad_ckpt": True,  "amp": "bf16"},
    {"batch_size": 8,  "seq_len": 512, "grad_ckpt": False, "amp": "bf16"},
    {"batch_size": 16, "seq_len": 256, "grad_ckpt": False, "amp": "bf16"},
]
4. 激进向量化

张量查找(而非 Python 循环):

# Slow: Python loop
for i, token_id in enumerate(input_ids):
    type_id = token_to_type[token_id]
    embeddings[i] = type_embeddings[type_id]

# Fast: Vectorized
type_ids = token_to_type[input_ids]  # Broadcast lookup
embeddings = type_embeddings[type_ids]  # Single GPU kernel

注册缓冲区(持久化 GPU 数据):

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        # Build lookup tensors once
        type_ids = torch.zeros(vocab_size, dtype=torch.long)
        self.register_buffer('_type_ids', type_ids)  # Stays on GPU

    def forward(self, input_ids):
        return self._type_ids[input_ids]  # Vectorized lookup

批量操作:

# Slow: Per-sample processing
outputs = [model(x.unsqueeze(0)) for x in batch]

# Fast: Batched
outputs = model(batch)  # Single forward pass
5. 迁移到 CuPy(NumPy → GPU)

适用 CuPy 的情况:

  • 大型数组操作(>1M 个元素)
  • 在紧密循环中重复调用 NumPy
  • PyTorch/XGBoost 前的预处理流水线

迁移模式:

import cupy as cp
import numpy as np

# NumPy (CPU)
x = np.random.randn(10000, 1000)
y = np.dot(x, x.T)

# CuPy (GPU) - SAME API
x_gpu = cp.random.randn(10000, 1000)
y_gpu = cp.dot(x_gpu, x_gpu.T)

# Transfer back if needed
y_cpu = cp.asnumpy(y_gpu)

与 PyTorch 互操作:

# CuPy → PyTorch (zero-copy)
x_cupy = cp.random.randn(1000, 1000)
x_torch = torch.as_tensor(x_cupy, device='cuda')

# PyTorch → CuPy (zero-copy)
x_torch = torch.randn(1000, 1000, device='cuda')
x_cupy = cp.asarray(x_torch)

安装:

uv pip install cupy-cuda12x  # For CUDA 12.x
6. 迁移到 cuDF(Pandas → GPU)

适用 cuDF 的情况:

  • DataFrame >1GB
  • 对大型数据执行 Groupby/聚合
  • 模型训练前的 ETL 流水线

迁移模式:

import cudf
import pandas as pd

# Pandas (CPU)
df = pd.read_csv('large.csv')
grouped = df.groupby('category')['value'].mean()

# cuDF (GPU) - SAME API
df_gpu = cudf.read_csv('large.csv')
grouped_gpu = df_gpu.groupby('category')['value'].mean()

# Transfer back
grouped_cpu = grouped_gpu.to_pandas()

与 XGBoost 集成:

import cudf
import xgboost as xgb

# Load data on GPU
df = cudf.read_csv('train.csv')
X = df[feature_cols]
y = df['target']

# Create DMatrix directly from cuDF (no CPU copy)
dtrain = xgb.DMatrix(X, label=y)

安装:

# RAPIDS (includes cuDF, cuML, cuGraph)
uv pip install cudf-cu12 --extra-index-url=https://pypi.nvidia.com
7. PyTorch 编译与优化

融合优化器:

# Check availability
use_fused = (
    torch.cuda.is_available()
    and "fused" in torch.optim.AdamW.__init__.__code__.co_varnames
)

optimizer = torch.optim.AdamW(
    model.parameters(),
    lr=1e-3,
    fused=use_fused,  # Single GPU kernel (2-3x faster)
)

Torch Compile:

# PyTorch 2.0+ compile
if hasattr(torch, "compile"):
    model = torch.compile(model, mode="reduce-overhead")

cuDNN 基准测试:

# Auto-tune kernels (slower startup, faster training)
torch.backends.cudnn.benchmark = True

# Disable for determinism
torch.backends.cudnn.deterministic = True
8. 高级损失函数

加权 Slot 损失:

class WeightedSlotLoss(nn.Module):
    def __init__(self, slot_weights):
        super().__init__()
        self.slot_weights = torch.tensor(slot_weights)

    def forward(self, logits_list, targets):
        weighted_losses = []
        for i, logits in enumerate(logits_list):
            loss = F.cross_entropy(logits, targets[:, i])
            weighted_losses.append(loss * self.slot_weights[i])
        return torch.stack(weighted_losses).sum() / self.slot_weights.sum()

焦点损失(困难样本挖掘):

class FocalLoss(nn.Module):
    def __init__(self, gamma=2.0):
        super().__init__()
        self.gamma = gamma

    def forward(self, logits, targets):
        ce_loss = F.cross_entropy(logits, targets, reduction='none')
        pt = torch.exp(-ce_loss)
        focal_loss = ((1 - pt) ** self.gamma) * ce_loss
        return focal_loss.mean()
9. 缓存与预计算

位置嵌入缓存:

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self._pos_cache = {}  # {seq_len: positions}

    def forward(self, x):
        T = x.size(1)
        if T not in self._pos_cache:
            self._pos_cache[T] = torch.arange(T, device=x.device)
            # Limit cache size
            if len(self._pos_cache) > 10:
                self._pos_cache.pop(next(iter(self._pos_cache)))
        return self.pos_embed(self._pos_cache[T])

注意力掩码缓存:

def _create_causal_mask(self, T, device):
    if T not in self._mask_cache:
        mask = torch.triu(torch.ones(T, T), diagonal=1).bool()
        self._mask_cache[T] = mask.to(device)
    return self._mask_cache[T]

快速诊断

检查 GPU 利用率:

watch -n 1 nvidia-smi  # Monitor in real-time

分析 PyTorch 性能:

with torch.profiler.profile(
    activities=[torch.profiler.ProfilerActivity.GPU],
    with_stack=True,
) as prof:
    model(batch)

print(prof.key_averages().table(sort_by="cuda_time_total"))

瓶颈检测:

import torch.utils.bottleneck as bottleneck
bottleneck.main(['script.py'])

迁移检查清单

  • XGBoost:使用 QuantileDMatrix,设置 device='cuda:0'
  • PyTorch:启用 BF16/FP16、融合优化器和 torch.compile
  • VRAM:接近 VRAM 上限时启用梯度检查点
  • NumPy→CuPy:用于元素数 >1M 的预处理
  • Pandas→cuDF:用于 >1GB 的 DataFrame
  • 向量化:用张量操作替换 Python 循环
  • 缓存:预计算位置、掩码和嵌入
  • 监控:跟踪 VRAM 使用情况并分析 GPU 内核性能

反模式

避免:

  • 在训练循环中使用 .cpu()(会破坏 GPU 流水线)
  • 在 CPU 上创建张量再移至 GPU(直接在 GPU 上创建)
  • 使用 Python 循环遍历张量(改用向量化)
  • 忽略 VRAM 监控(会导致 OOM 崩溃)
  • BF16/FP16 可用时仍使用 FP32(浪费带宽)
  • 不必要地调用 torch.cuda.synchronize()(会破坏异步执行)

参考资料

文档:

错误处理

  • 运行时 CUDA 不可用:先运行 nvidia-smi 确认 GPU 是否可见;如果命令执行失败,请使用 sudo nvidia-smi 验证驱动是否已安装,或重新安装驱动后再继续。
  • XGBoost 报错 RuntimeError: XGBoost not compiled with CUDA support:在启用了 CUDA 的环境中通过 uv pip install xgboost 安装 CUDA 构建版本,或使用 -DUSE_CUDA=ON 从源代码构建。
  • 训练期间出现 OOM:先减小批次大小(减半),然后启用梯度检查点;如果两者都启用后仍然出现 OOM,则启用梯度累积,以模拟原始批次大小。
  • CuPy 导入失败(ImportError 或版本不匹配):使用 nvcc --version 验证 CUDA 工具包版本,并安装匹配的 CuPy wheel(例如,CUDA 12.x 对应 cupy-cuda12x)。
  • cuDF 安装失败或产生 CUDA 版本错误:使用 NVIDIA PyPI 索引(--extra-index-url=https://pypi.nvidia.com),并确保 cudf-cu12 后缀与 CUDA 主版本相符。
  • torch.compile 产生错误结果或崩溃:通过设置 model = model(不进行编译)来停用编译以便排查;已知某些自定义算子会导致此问题——对于这些层,请改用即时执行模式。

局限性

  • 仅适用于 NVIDIA GPU——这些模式不涵盖 AMD(ROCm)和 Intel Arc GPU。
  • 假定使用单 GPU 设置;多 GPU(DDP、FSDP)需要额外配置,此处不作介绍。
  • 这些模式针对消费级 GPU(8–24GB VRAM)进行了校准;数据中心 GPU(A100、H100)的内存层次结构不同,可能适用不同的策略。
  • 框架覆盖范围:仅限 PyTorch、XGBoost 和 RAPIDS(CuPy/cuDF)——不涵盖 JAX、TensorFlow 和 MXNet。
  • 笔记本 GPU 的 TDP 限制会影响持续吞吐量;即使 VRAM 容量相同,受功耗限制的性能也可能与台式机基准测试有显著差异。

输出格式

每条优化建议都包含一组优化前/后的代码,展示原始模式及其 GPU 优化后的对应写法。 性能提升估算以范围形式给出(例如,“快 1.8 倍”、“VRAM 减少约 40%”),依据典型消费级 GPU 基准测试得出——实际提升取决于工作负载和硬件。 如果某项更改会带来权衡(例如,梯度检查点会增加计算时间),则会在行内明确说明。

评论

支持 Markdown