当前位置: 首页 > news >正文

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

CPU性能基准测试

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

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

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的设备管理机制。核心概念是所有参与计算的张量和模型必须位于同一设备上:

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的同步传输:

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同步操作:

# 优化版本:减少数据传输频率
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调用机制解析

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组件都能以统一方式调用。

@浙大疏锦行

http://www.dtcms.com/a/320141.html

相关文章:

  • [特殊字符] 未来图钉式 AI 时代的智能生态布局:副脑矩阵与人机共振的系统构想
  • USB2.0 和 USB3.0 枚举对比
  • 数据标注之数据集的类型与如何标注
  • Ubuntu24.04的“errors from xkbcomp are not fatal to the X server”终极修复方案
  • 【驱动】RK3576-Debian系统使用ping报错:socket operation not permitted
  • 3_steels_detect_CSDN_20250807_165405
  • spring cache(二)核心接口
  • Claude Code MCP 网络搜索配置命令
  • Qwen3-235B-A22B-Instruct-2507模型介绍
  • 【更新被拒绝,因为推送的一个分支的最新提交落后于其对应的远程分支。】
  • 【网络编程】一请求一线程
  • 【洛谷题单】--分支结构(一)
  • 《网络空间测绘技术白皮书》
  • Docker容器强制删除及文件系统修复完整指南
  • 8. 字符串转换整数 (atoi)
  • 大模型LL04 微调prompt-Tuning方法入门(背景与发展)
  • 【自动驾驶】《Sparse4Dv3》代码学习笔记
  • Redis的五个基本类型(2)
  • 单页面应用(SPA)和多页面应用(MPA)
  • RP2040下的I2S Slave Out,PIO状态机(三)
  • pybind11 的应用
  • (Python)Python爬虫入门教程:从零开始学习网页抓取(爬虫教学)(Python教学)
  • 腾讯iOA技术指南:实现数据防泄漏与高级威胁防护
  • Spark Memory 内存设计的核心组件、对比Flink内存配置
  • langchain入门笔记02:几个实际应用
  • 生信分析进阶16 - 可准确有效地检测血浆 ccf-mtDNA 突变的分析方法
  • DrissionPage实战案例:小红书旅游数据爬取
  • 串口转ADC/PWM 串口转I2C 串口转GPIO工具
  • c++20--std::format
  • 工业相机使用 YOLOv8深度学习模型 及 OpenCV 实现目标检测简单介绍