Day 34:GPU训练与类的call方法

CPU性能基准测试

首先回顾昨天在CPU上的训练结果。使用鸢尾花数据集训练多层感知机,20000个epochs的训练时间为19.09秒。这为我们的对比分析提供了重要的基准线。

通过代码了解一下测试环境的CPU配置:

python 复制代码
import wmi
c = wmi.WMI()
processors = c.Win32_Processor()

for processor in processors:
    print(f"CPU 型号: {processor.Name}")
    print(f"核心数: {processor.NumberOfCores}")  
    print(f"线程数: {processor.NumberOfLogicalProcessors}")

# 输出:12th Gen Intel(R) Core(TM) i7-1255U
# 核心数: 10,线程数: 12

这是我的Intel第12代处理器,采用混合架构设计,结合了性能核心和能效核心,在处理小规模任务时具有良好的单核性能。

GPU训练环境配置

将训练迁移到GPU需要理解PyTorch的设备管理机制。核心概念是所有参与计算的张量和模型必须位于同一设备上:

python 复制代码
import torch

# 检测GPU环境
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")

# 数据迁移到GPU
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train).to(device)

# 模型迁移到GPU  
model = MLP().to(device)

这里需要注意.to(device)方法的行为差异:对于张量会返回新的副本,对于模型则直接修改原对象的参数位置。

意外的性能对比结果

运行相同的训练代码后,得到了比较意外的结果:

  • CPU训练时间:19.09秒
  • GPU训练时间:21.23秒

GPU居然比CPU更慢,但是跟据我们的经验GPU擅长并行运算,进行深度学习等科学计算相比CPU更有优势,训练速度应该更快。

GPU性能劣势的根本原因

GPU在小规模任务上表现不佳主要源于三个开销:

数据传输开销 是最主要的瓶颈。每次GPU计算都需要CPU内存到GPU显存的数据传输,更关键的是代码中的loss.item()操作会在每个epoch都进行GPU到CPU的同步传输:

python 复制代码
for epoch in range(num_epochs):
    outputs = model(X_train)
    loss = criterion(outputs, y_train)
    
    optimizer.zero_grad()
    loss.backward()  
    optimizer.step()
    
    losses.append(loss.item())  # 这里触发GPU->CPU传输!

对于20000个epochs,这种频繁的数据同步累积了大量开销。

核心启动开销是第二个因素。GPU的每个操作都需要启动计算核心,当实际计算量很小时,启动开销在总时间中占比显著。

计算资源浪费是第三个问题。鸢尾花数据集只有150个样本,无法充分利用GPU的大量并行计算单元。

性能优化实验验证

为了验证数据传输开销的影响,进行了对照实验,减少不必要的GPU-CPU同步操作:

python 复制代码
# 优化版本:减少数据传输频率
for epoch in range(num_epochs):
    outputs = model(X_train)
    loss = criterion(outputs, y_train)
    
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    
    # 只在打印时才进行数据传输
    if (epoch + 1) % 100 == 0:
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

优化后的GPU训练时间降至14.86秒,接近CPU性能。这清晰地证明了数据传输开销的重大影响。

进一步的实验显示,记录频率与性能的关系并非简单的线性关系,这涉及GPU异步执行的复杂机制。

GPU优势的发挥条件

GPU的真正优势在于处理大规模并行计算任务。当满足以下条件时,GPU的性能优势才会显现:

处理包含数万张图片的大型数据集时,数据传输开销被大量计算掩盖。训练具有数百万参数的深度网络时,复杂的矩阵运算能充分利用GPU的并行架构。使用较大的批量处理时,能够填满GPU的计算单元。

简单来说,只有当计算量足够大时,GPU的并行优势才能超越各种固定开销。

PyTorch调用机制解析

python 复制代码
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(4, 10)  # 创建对象
        
    def forward(self, x):
        out = self.fc1(x)  # 像函数一样调用对象
        return out

这里self.fc1是一个对象,但可以像函数一样调用。这是因为nn.Module实现了__call__方法,当我们调用self.fc1(x)时,实际执行的是self.fc1.__call__(x),进而调用forward方法完成计算。

这种设计保证了接口的一致性,让所有PyTorch组件都能以统一方式调用。

@浙大疏锦行

相关推荐
闲人编程12 分钟前
Elasticsearch搜索引擎集成指南
python·elasticsearch·搜索引擎·jenkins·索引·副本·分片
痴儿哈哈21 分钟前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
A尘埃21 分钟前
保险公司车险理赔欺诈检测(随机森林)
算法·随机森林·机器学习
花酒锄作田34 分钟前
SQLAlchemy中使用UPSERT
python·sqlalchemy
SoleMotive.35 分钟前
一个准程序员的健身日志:用算法调试我的增肌计划
python·程序员·健身·职业转型
亓才孓43 分钟前
[Properties]写配置文件前,必须初始化Properties(引用变量没执行有效对象,调用方法会报空指针错误)
开发语言·python
Bruk.Liu1 小时前
(LangChain 实战14):基于 ChatMessageHistory 自定义实现对话记忆功能
人工智能·python·langchain·agent
大江东去浪淘尽千古风流人物1 小时前
【VLN】VLN(Vision-and-Language Navigation视觉语言导航)算法本质,范式难点及解决方向(1)
人工智能·python·算法
Swift社区1 小时前
Gunicorn 与 Uvicorn 部署 Python 后端详解
开发语言·python·gunicorn
Coinsheep1 小时前
SSTI-flask靶场搭建及通关
python·flask·ssti