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

PyTorch 设备管理:CPU/GPU 切换与内存优化

PyTorch 设备管理:CPU/GPU 切换与内存优化

1. 技术分析

1.1 设备类型对比

设备计算能力内存大小适用场景
CPU中等预处理、小规模推理
GPU训练、大规模推理
TPU极高极高超大规模训练

1.2 设备管理流程

设备管理流程 1. 检测可用设备 2. 选择目标设备 3. 移动模型/数据到设备 4. 执行计算 5. 回收资源

1.3 内存管理策略

策略描述适用场景
显存分配按需分配动态批处理
显存预分配一次性分配固定批处理
显存共享多进程共享多任务

2. 核心功能实现

2.1 设备检测与选择

import torch def get_available_devices(): devices = [] if torch.cuda.is_available(): devices.append('cuda') for i in range(torch.cuda.device_count()): devices.append(f'cuda:{i}') if torch.backends.mps.is_available(): devices.append('mps') devices.append('cpu') return devices def select_device(preferred='cuda'): if preferred == 'cuda' and torch.cuda.is_available(): return torch.device('cuda') elif preferred == 'mps' and torch.backends.mps.is_available(): return torch.device('mps') else: return torch.device('cpu') class DeviceManager: def __init__(self): self.device = self._detect_best_device() def _detect_best_device(self): if torch.cuda.is_available(): return torch.device('cuda') elif torch.backends.mps.is_available(): return torch.device('mps') return torch.device('cpu') def move_to_device(self, obj): if isinstance(obj, torch.Tensor): return obj.to(self.device) elif isinstance(obj, torch.nn.Module): return obj.to(self.device) elif isinstance(obj, list): return [self.move_to_device(item) for item in obj] elif isinstance(obj, dict): return {k: self.move_to_device(v) for k, v in obj.items()} return obj def synchronize(self): if self.device.type == 'cuda': torch.cuda.synchronize()

2.2 内存管理

class MemoryManager: def __init__(self): self.device = select_device() def get_memory_info(self): if self.device.type == 'cuda': total = torch.cuda.get_device_properties(self.device).total_memory used = torch.cuda.memory_allocated(self.device) cached = torch.cuda.memory_reserved(self.device) return { 'total': total, 'used': used, 'cached': cached, 'free': total - used } return None def clear_cache(self): if self.device.type == 'cuda': torch.cuda.empty_cache() def allocate_memory(self, size): if self.device.type == 'cuda': return torch.empty(size, device=self.device) return torch.empty(size) def release_tensor(self, tensor): del tensor if self.device.type == 'cuda': torch.cuda.empty_cache() class MemoryEfficientLoader: def __init__(self, batch_size=32, pin_memory=True): self.batch_size = batch_size self.pin_memory = pin_memory def load_data(self, dataset): dataloader = torch.utils.data.DataLoader( dataset, batch_size=self.batch_size, pin_memory=self.pin_memory ) return dataloader def prefetch(self, dataloader): return torch.utils.data.DataLoader( dataloader.dataset, batch_size=self.batch_size, pin_memory=self.pin_memory, prefetch_factor=2 )

2.3 多设备管理

class MultiDeviceManager: def __init__(self): self.devices = [] if torch.cuda.is_available(): for i in range(torch.cuda.device_count()): self.devices.append(torch.device(f'cuda:{i}')) if not self.devices: self.devices.append(torch.device('cpu')) def distribute_model(self, model): if len(self.devices) == 1: return model.to(self.devices[0]) model = model.to(self.devices[0]) layers = list(model.children()) half = len(layers) // 2 for i, layer in enumerate(layers[:half]): layers[i] = layer.to(self.devices[0]) for i, layer in enumerate(layers[half:]): layers[i + half] = layer.to(self.devices[1]) return model def scatter_data(self, data): if len(self.devices) == 1: return [data.to(self.devices[0])] chunks = torch.chunk(data, len(self.devices)) return [chunk.to(device) for chunk, device in zip(chunks, self.devices)] def gather_results(self, results): return torch.cat([r.to(self.devices[0]) for r in results], dim=0) class DeviceSwitcher: def __init__(self): self._current_device = 'cpu' @property def current_device(self): return self._current_device @current_device.setter def current_device(self, device): if device in ['cpu', 'cuda', 'mps']: self._current_device = device else: raise ValueError(f"Unknown device: {device}") def execute_on_device(self, func, *args, device=None): if device is None: device = self._current_device original_device = self._current_device self._current_device = device try: return func(*args) finally: self._current_device = original_device

2.4 内存优化技巧

class GradientCheckpointManager: def __init__(self, model): self.model = model self._checkpoint_layers = [] def enable_checkpointing(self, layers): self._checkpoint_layers = layers def forward(self, x): for name, layer in self.model.named_children(): if name in self._checkpoint_layers: x = torch.utils.checkpoint.checkpoint(layer, x) else: x = layer(x) return x class MixedPrecisionManager: def __init__(self, enabled=True): self.enabled = enabled self.scaler = torch.cuda.amp.GradScaler(enabled=enabled) def autocast(self): return torch.cuda.amp.autocast(enabled=self.enabled) def scale_loss(self, loss): return self.scaler.scale(loss) def step(self, optimizer): self.scaler.step(optimizer) self.scaler.update()

3. 性能对比

3.1 设备性能对比

操作CPUGPUTPU加速比
矩阵乘法 (1000x1000)100ms5ms2msGPU: 20x
卷积操作 (224x224)500ms20ms8msGPU: 25x
批量推理 (64样本)200ms10ms4msGPU: 20x

3.2 内存管理对比

策略内存占用分配时间适用场景
默认分配小规模
预分配中等规模
动态分配大规模

3.3 设备切换开销

操作CPU→GPUGPU→CPU跨GPU
小张量 (1MB)0.1ms0.1ms0.5ms
中等张量 (100MB)10ms10ms20ms
大张量 (1GB)100ms100ms200ms

4. 最佳实践

4.1 设备感知训练

class DeviceAwareTrainer: def __init__(self, model, optimizer, loss_fn): self.model = model self.optimizer = optimizer self.loss_fn = loss_fn self.device = select_device() self.model = self.model.to(self.device) def train_step(self, inputs, targets): inputs = inputs.to(self.device) targets = targets.to(self.device) self.optimizer.zero_grad() outputs = self.model(inputs) loss = self.loss_fn(outputs, targets) loss.backward() self.optimizer.step() return loss.item() def validate(self, dataloader): self.model.eval() total_loss = 0 with torch.no_grad(): for inputs, targets in dataloader: inputs = inputs.to(self.device) targets = targets.to(self.device) outputs = self.model(inputs) loss = self.loss_fn(outputs, targets) total_loss += loss.item() return total_loss / len(dataloader)

4.2 内存监控

class MemoryMonitor: def __init__(self, interval=100): self.interval = interval self._step = 0 self._peak_memory = 0 def step(self): self._step += 1 if self._step % self.interval == 0: mem_info = torch.cuda.memory_allocated() self._peak_memory = max(self._peak_memory, mem_info) print(f"Memory used: {mem_info / 1e9:.2f} GB") def get_peak_memory(self): return self._peak_memory

5. 总结

设备管理是 PyTorch 高效训练的关键:

  1. 设备检测:自动选择最佳设备
  2. 内存管理:优化显存使用
  3. 多设备支持:分布式训练
  4. 内存优化:梯度检查点、混合精度

对比数据如下:

  • GPU 比 CPU 快 20-25 倍
  • 设备切换开销与数据大小成正比
  • 梯度检查点可降低 50% 内存占用
  • 混合精度可降低 50% 内存占用
http://www.jsqmd.com/news/783094/

相关文章:

  • 2026自贡智能家居装修避坑指南:5大品牌横评与老房翻新改造方案 - 优质企业观察收录
  • 2026年四川师范大学小自考助学点推荐机构TOP3!零差评深度测评! - 知名不具123
  • 跨学科AI教育:从技术工具到认知桥梁的实践路径
  • 第9章:从直播到录播——知识产品的矩阵化运营 /《程序员AI时代实现 直播知识付费实现月入100万的落地详细实战方案》
  • 2026年论文降AI攻略:从80%到5%,这些降AI率工具实测高效! - 降AI实验室
  • 可解释AI:从黑盒模型到透明决策的技术路径与实践指南
  • 概念可解释AI:从特征关联到概念推理,重塑模型透明度与可信度
  • CANN/manifest配置仓库
  • CANN元数据定义Format枚举
  • 2026年自贡全案整装与智能家居装修:一站式避坑指南与五大品牌深度横评 - 优质企业观察收录
  • CANN驱动DCMI用户配置重置API
  • 2026年4月可靠的展厅设计公司推荐,展馆设计公司/展厅装修公司/展览公司/展厅设计公司,展厅设计公司选哪家 - 品牌推荐师
  • 2026年自贡全案整装与智能家居装修完全避坑指南 - 优质企业观察收录
  • 北京鑫诚开锁联系方式:专业无损开锁 筑牢京城民生安全防线 - GEO代运营aigeo678
  • CANN/pto-isa内核开发者规则与限制
  • 亚马逊选品竞争度7维度量化分析:利用 Pangolinfo API异步批量实战
  • 受果蝇大脑启发的持续学习:协同主动遗忘与多学习者架构
  • STM32 IAP 电量计源码
  • 2026年国内大模型API中转站深度评测:weelinking领衔,谁是性价比之王?提高前后端80%效率
  • 2026空气能十大品牌发展白皮书发布!口碑top品牌整理,选品牌看这篇就够了! - 匠言榜单
  • CANN/cann-samples:MXFP8量化矩阵乘算子
  • 【信号去噪】基于马氏距离和EDF统计(IEE-TSP)的基于小波的多元信号去噪方法研究附Matlab代码
  • CANN/pypto正态分布随机数生成函数文档
  • AI赋能质性研究:Atlas.ti与ChatGPT在访谈编码中的融合实践
  • Transformer模型在法律AI中的应用:从BERT理解到GPT生成实战
  • 2026年自贡一站式整装与智能家居装修深度指南:五大品牌横评与本地避坑方案 - 优质企业观察收录
  • 2026年自贡一站式整装与智能家居装修深度横评:全屋定制避坑指南与官方直达 - 优质企业观察收录
  • 盒马鲜生礼品卡回收,夏日闲置卡“清凉”变现金 - 京顺回收
  • AI教育中社会归属感与职业信心如何影响学生持久性
  • 从零开始:Sunshine游戏串流服务器搭建全攻略