Day 38 GPU训练及类的call方法

@浙大疏锦行

一、CPU 性能查看

系统级查看(Windows/Linux/Mac 通用)

(1)Windows 系统

  • 任务管理器 :按下 Ctrl+Shift+Esc → 切换到「性能」选项卡 → 查看 CPU 使用率、核心数、频率、缓存等;
  • 资源监视器:任务管理器「性能」→ 左下角「打开资源监视器」→ 可查看每个进程的 CPU 占用、线程数。

(2)Linux 系统(命令行)

复制代码
# 实时查看CPU整体使用率、核心数、负载(最常用)
top  # 按1显示每个核心,按q退出

# 查看CPU硬件信息(核心数、架构、频率)
lscpu

# 更直观的CPU监控(需安装)
apt install htop
htop

# 查看进程CPU占用(指定进程名/ID)
pidstat -p [进程ID] 1  # 每秒刷新1次

(3)Mac 系统

  • 「活动监视器」:启动台搜索「活动监视器」→ 「CPU」标签页 → 查看使用率、进程占用;

  • 终端命令:

    复制代码
    top  # 实时监控
    sysctl -n hw.ncpu  # 查看CPU核心数

二、GPU 性能查看

Python 代码中查看 GPU 性能

复制代码
import torch

# 1. 检查GPU是否可用
gpu_available = torch.cuda.is_available()
print(f"GPU是否可用:{gpu_available}")

# 2. 查看GPU数量、型号
if gpu_available:
    gpu_count = torch.cuda.device_count()
    gpu_name = torch.cuda.get_device_name(0)  # 查看第0块GPU名称
    print(f"GPU数量:{gpu_count},第0块GPU型号:{gpu_name}")
    
    # 3. 查看当前GPU显存使用(PyTorch视角)
    torch.cuda.empty_cache()  # 清空缓存
    allocated = torch.cuda.memory_allocated(0) / 1024**3  # 已分配显存(GB)
    cached = torch.cuda.memory_reserved(0) / 1024**3      # 缓存显存(GB)
    print(f"已分配显存:{allocated:.2f}GB,缓存显存:{cached:.2f}GB")
    
    # 4. 设置默认GPU
    torch.cuda.set_device(0)

三、GPU 训练方法

核心步骤:设备配置 → 模型 / 数据迁移 → 训练逻辑 → 显存优化

  • 设备配置:通过torch.cuda.is_available()判断 GPU 是否可用,将模型 / 数据移到 GPU(.to(device));

  • 数据 / 模型迁移:张量 / 模型必须和设备匹配(GPU 张量不能在 CPU 上计算,反之亦然);

  • 批量训练:避免 GPU 显存溢出,控制 batch_size;

  • 混合精度(可选):加速训练,减少显存占用。

    import torch
    import torch.nn as nn
    import torch.optim as optim
    from torch.utils.data import DataLoader, TensorDataset

    ===================== 1. 设备配置(核心) =====================

    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    print(f"训练设备:{device}")

    ===================== 2. 定义模型并迁移到GPU =====================

    class SimpleMLP(nn.Module):
    def init(self, input_dim=10, hidden_dim=64, output_dim=2):
    super().init()
    self.mlp = nn.Sequential(
    nn.Linear(input_dim, hidden_dim),
    nn.ReLU(),
    nn.Linear(hidden_dim, output_dim)
    )

    复制代码
      def forward(self, x):
          return self.mlp(x)

    初始化模型并移到GPU

    model = SimpleMLP(input_dim=10, output_dim=2).to(device)

    ===================== 3. 准备数据并迁移到GPU(批量) =====================

    模拟数据集

    batch_size = 64
    x = torch.randn(1000, 10) # CPU张量
    y = torch.randint(0, 2, (1000,)) # CPU张量
    dataset = TensorDataset(x, y)
    dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)

    ===================== 4. 定义优化器/损失函数 =====================

    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=1e-3)

    ===================== 5. GPU训练逻辑 =====================

    epochs = 5
    model.train() # 训练模式
    for epoch in range(epochs):
    epoch_loss = 0.0
    for x_batch, y_batch in dataloader:
    # 关键:将batch数据移到GPU(DataLoader默认生成CPU张量)
    x_batch = x_batch.to(device)
    y_batch = y_batch.to(device)

    复制代码
          # 前向传播
          outputs = model(x_batch)
          loss = criterion(outputs, y_batch)
          
          # 反向传播+优化
          optimizer.zero_grad()
          loss.backward()
          optimizer.step()
          
          epoch_loss += loss.item()
      
      avg_loss = epoch_loss / len(dataloader)
      print(f"Epoch [{epoch+1}/{epochs}], 平均损失:{avg_loss:.4f}")

    ===================== 6. GPU推理(验证) =====================

    model.eval()
    with torch.no_grad(): # 关闭梯度,节省显存
    test_x = torch.randn(10, 10).to(device) # 测试数据移到GPU
    pred = model(test_x)
    print(f"\nGPU推理结果(类别):{pred.argmax(dim=1).cpu().numpy()}") # 转回CPU便于打印

四、类的call方法

  1. 语法规则

    class 类名:
    def call(self, *args, **kwargs):
    # 自定义逻辑(可接收参数、返回结果)
    执行操作
    return 结果

  • 当实例被调用(实例()实例(参数))时,Python 会自动执行 __call__ 方法;
  • self 指向实例本身,可访问实例的所有属性(状态);
  • 支持任意参数(*args/**kwargs)和返回值,和普通函数完全一致。
  1. 本质:可调用对象(Callable)

Python 中「可调用对象」包括:函数、方法、类、带 __call__ 的实例。可通过 callable() 验证:

复制代码
class Counter:
    def __call__(self):
        pass

counter = Counter()
print(callable(counter))  # True(实例可调用)
print(callable(Counter))  # True(类本身可调用,调用后创建实例)
print(callable(lambda x: x+1))  # True(函数可调用)

3.基础示例:带状态的调用

最典型的场景是「保存状态的函数」(区别于普通函数的局部变量):

复制代码
class Accumulator:
    """累加器:每次调用传入一个数,累加并返回总和"""
    def __init__(self):
        self.total = 0  # 实例属性保存累加状态
    
    def __call__(self, num):
        self.total += num
        return self.total

# 使用示例
acc = Accumulator()
print(acc(10))  # 执行__call__,total=0+10 → 输出10
print(acc(20))  # total=10+20 → 输出30
print(acc(5))   # total=30+5 → 输出35
print(acc.total)# 直接访问状态 → 输出35
相关推荐
嗷嗷哦润橘_2 小时前
AI Agent学习:MetaGPT项目之RAG
人工智能·python·学习·算法·deepseek
Smart-Space2 小时前
tkinter绘制组件(47)——导航边栏
python·tkinter·tinui
认真敲代码的小火龙2 小时前
【JAVA项目】基于JAVA的养老院管理系统
java·开发语言·课程设计
AI科技星2 小时前
统一场论质量定义方程:数学验证与应用分析
开发语言·数据结构·经验分享·线性代数·算法
扶苏-su2 小时前
Java---事件处理机制
java·开发语言
ULTRA??2 小时前
KD-Tree的查询原理
python·算法
小灰灰搞电子2 小时前
Qt 实现炫酷锁屏源码分享
开发语言·qt·命令模式
电饭叔2 小时前
TypeError:unsupported operand type(s) for -: ‘method‘ and ‘int‘
开发语言·笔记·python
老歌老听老掉牙2 小时前
使用贝叶斯因子量化假设验证所需数据量
python·贝叶斯因子·假设