M1 Mac上PyTorch用MPS加速训练遇RuntimeError:Placeholder存储未分配MPS设备
解决M1 Mac上PyTorch MPS加速LSTM训练的"Placeholder storage has not been allocated on MPS device!"错误
核心原因
错误源于LSTM的初始隐藏状态(h0、c0)与输入张量不在同一设备,或是提前在Dataset中将数据移至MPS导致的多进程加载冲突。
具体解决方案
1. 修正LSTM隐藏状态的设备分配
在模型的forward方法中,必须确保h0和c0与输入张量x处于同一设备(MPS)。不要硬编码设备,而是通过x.device动态获取:
def forward(self, x): batch_size = x.size(0) # 动态获取输入张量的设备,创建对应设备上的隐藏状态 h0 = torch.zeros(self.num_layers, batch_size, self.hidden_size, device=x.device) c0 = torch.zeros(self.num_layers, batch_size, self.hidden_size, device=x.device) out, _ = self.lstm(x, (h0, c0)) # 后续模型输出处理逻辑... return out
2. 修改Dataset,避免提前将数据移至MPS
Dataset中仅创建CPU张量,不要在初始化时指定device或调用.to(device)。因为PyTorch的DataLoader多进程模式下,MPS张量无法跨进程传递,会导致设备不匹配问题:
class MyDataset(Dataset): def __init__(self, df, window_size): self.df = df self.window_size = window_size self.data = [] self.labels = [] for i in range(len(df) - window_size): # 仅创建CPU张量,不指定设备 x = torch.tensor(df.iloc[i:i+window_size].values, dtype=torch.float) y = torch.tensor(df.iloc[i+window_size].values, dtype=torch.float) self.data.append(x) self.labels.append(y) def __len__(self): return len(self.data) def __getitem__(self, idx): return self.data[idx], self.labels[idx]
3. 在训练步骤中批量移动数据至MPS
在train_step函数里,将DataLoader输出的批量张量统一移至MPS设备:
def train_step(model, criterion, optimizer, x, y, device): # 将批量数据移至指定设备 x = x.to(device) y = y.to(device) optimizer.zero_grad() y_pred = model(x) loss = criterion(y_pred, y) loss.backward() optimizer.step() return loss.item()
额外检查点
- 确认模型已正确移至MPS:可以通过
next(model.parameters()).device查看参数设备,确保输出为mps:0。 - 若使用PyTorch 1.13版本,确保你的macOS版本为12.3+(MPS支持的最低系统版本)。
内容的提问来源于stack exchange,提问作者Collin Bell
相关产品推荐
相关产品推荐

