目录

常见问题解答

我的模型报告 “cuda runtime error(2):内存不足”

如错误消息所示,您的 GPU 的 GPU 中。由于我们经常在 PyTorch 中处理大量数据, 小错误会很快导致您的程序用完所有 图形处理器;幸运的是,这些情况下的修复通常很简单。 以下是一些需要检查的常见事项:

不要在训练循环中累积历史记录。默认情况下,涉及需要梯度的变量的计算 将保留历史记录。这意味着您应该避免使用此类 计算中的变量,这些变量将存在于您的训练循环之外, 例如,在跟踪统计数据时。相反,您应该分离变量 或访问其基础数据。

有时,当可微变量可以时,它可能并不明显 发生。考虑以下训练循环(从源代码删节):

total_loss = 0
for i in range(10000):
    optimizer.zero_grad()
    output = model(input)
    loss = criterion(output)
    loss.backward()
    optimizer.step()
    total_loss += loss

这里, 是在整个训练循环中累积历史,因为 是一个具有 autograd 历史的可微变量。您可以通过以下方式解决此问题 写入 total_loss += float(loss) 来代替。total_lossloss

此问题的其他实例: 1.

不要保留不需要的张量和变量。如果你将 Tensor 或 Variable 分配给 local,Python 不会 deallocate,直到 local 超出范围。您可以免费 此引用使用 .同样,如果您将 将 Tensor 或 Variable 转换为对象的成员变量,它将 在对象超出范围之前不解除分配。您将 如果您不保留临时 (Temporaries),则获得最佳内存利用率 你不需要。del x

局部变量的范围可能比您预期的要大。例如:

for i in range(5):
    intermediate = f(input[i])
    result += g(intermediate)
output = h(result)
return output

在这里,即使在执行时仍然活着, ,因为它的范围会超出 Loop 的终点。释放它 早些时候,你应该在完成它时。intermediatehdel intermediate

避免在太大的序列上运行 RNN。通过 RNN 进行反向传播所需的内存量可以扩展 与 RNN 输入的长度呈线性关系;因此,您将耗尽内存 如果您尝试向 RNN 提供太长的序列。

这种现象的技术术语是 backpropagation over time, 并且有很多关于如何实现 Truncated 的参考 BPTT,包括在词语言模型示例中;截断由此论坛帖子中所述的函数处理。repackage

不要使用太大的线性图层。线性层使用nn.Linear(m, n)O(nm)O(nm)记忆:也就是说, 权重的内存要求 随特征数进行二次缩放。这很容易 以这种方式刷新您的记忆(请记住,您至少需要两倍于 weights,因为您还需要存储梯度。

考虑检查点。您可以使用 checkpoint 权衡计算的内存。

我的 GPU 内存没有正确释放

PyTorch 使用缓存内存分配器来加快内存分配速度。作为 result,则 中显示的值通常不反映 true 内存使用情况。有关 GPU 的更多详细信息,请参阅内存管理 内存管理。nvidia-smi

如果您的 GPU 内存在 Python 退出后仍未释放,则很可能是 一些 Python 子进程仍然存在。您可以通过 找到它们并使用 手动杀死它们。ps -elf | grep pythonkill -9 [pid]

我的内存不足异常处理程序无法分配内存

您可能有一些代码尝试从内存不足错误中恢复。

try:
    run_model(batch_size)
except RuntimeError: # Out of memory
    for _ in range(batch_size):
        run_model(1)

但是发现,当您确实耗尽内存时,您的恢复代码无法分配 也。这是因为 python 异常对象包含对 stack 帧。这会阻止原始张量 对象。解决方案是将 OOM 恢复代码移出 的子句。except

oom = False
try:
    run_model(batch_size)
except RuntimeError: # Out of memory
    oom = True

if oom:
    for _ in range(batch_size):
        run_model(1)

我的数据加载程序 worker 返回相同的随机数

您可能正在使用其他库在数据集中生成随机数 和 worker 子进程通过 启动 。请参阅 的文档 以了解如何 使用其选项在 workers 中正确设置 random seeds。forkworker_init_fn

我的循环网络无法使用数据并行

with 中使用模式有一个微妙之处。Input 到每个 on 每个装置将只是整个 input 的一部分。因为 unpack 操作默认只填充到 seen longest input,即该特定设备上最长的 size。 将结果收集在一起时,将发生不匹配。因此,您可以 相反,请利用参数 of 来确保调用返回相同长度的序列。例如,您可以 写:pack sequence -> recurrent network -> unpack sequenceforward()total_lengthforward()

from torch.nn.utils.rnn import pack_padded_sequence, pad_packed_sequence

class MyModule(nn.Module):
    # ... __init__, other methods, etc.

    # padded_input is of shape [B x T x *] (batch_first mode) and contains
    # the sequences sorted by lengths
    #   B is the batch size
    #   T is max sequence length
    def forward(self, padded_input, input_lengths):
        total_length = padded_input.size(1)  # get the max sequence length
        packed_input = pack_padded_sequence(padded_input, input_lengths,
                                            batch_first=True)
        packed_output, _ = self.my_lstm(packed_input)
        output, _ = pad_packed_sequence(packed_output, batch_first=True,
                                        total_length=total_length)
        return output


m = MyModule().cuda()
dp_m = nn.DataParallel(m)

此外,当 Batch 维度较暗(即)且具有数据并行性时,需要格外小心。在本例中,第一个 pack_padded_sequence 的参数将是 shape 的,并且应该沿 dim 分散,但第二个参数将是 shape 的,并且应该沿着 dim 分散。需要额外的代码来操作张量形状。1batch_first=Falsepadding_input[T x B x *]1input_lengths[B]0

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源