国产gaysexchina男同gay,japanrcep老熟妇乱子伦视频,吃奶呻吟打开双腿做受动态图,成人色网站,国产av一区二区三区最新精品

PyTorch 經(jīng)常問(wèn)的問(wèn)題(FAQ)詳解

2025-06-24 18:29 更新

一、模型報(bào)告“CUDA 運(yùn)行時(shí)錯(cuò)誤(2):內(nèi)存不足”

當(dāng)您的模型報(bào)告“CUDA 運(yùn)行時(shí)錯(cuò)誤(2):內(nèi)存不足”時(shí),這表明您的 GPU 內(nèi)存已用完。以下是一些常見(jiàn)的檢查事項(xiàng):

1.1 不要在訓(xùn)練循環(huán)中累積歷史記錄

默認(rèn)情況下,涉及需要漸變的變量的計(jì)算將保留歷史記錄。您應(yīng)避免在計(jì)算中使用此類變量,這些變量將不受訓(xùn)練循環(huán)的影響,例如在跟蹤統(tǒng)計(jì)信息時(shí)。相反,您應(yīng)該分離變量或訪問(wèn)其基礎(chǔ)數(shù)據(jù)。

示例代碼

total_loss = 0
for i in range(10000):
    optimizer.zero_grad()
    output = model(input)
    loss = criterion(output)
    loss.backward()
    optimizer.step()
    # total_loss += loss  # 這會(huì)累積歷史記錄
    total_loss += float(loss)  # 解決方法

1.2 不要使用不需要的張量和變量

如果將 Tensor 或 Variable 分配給本地,Python 將不會(huì)取消分配,直到本地超出范圍。您可以通過(guò) del 釋放此引用。同樣,如果將 Tensor 或 Variable 分配給對(duì)象的成員變量,則在對(duì)象超出范圍之前它不會(huì)釋放。如果不需要的臨時(shí)存儲(chǔ),將獲得最佳的內(nèi)存使用率。

示例代碼

for i in range(5):
    intermediate = f(input[i])
    result += g(intermediate)
    del intermediate  # 釋放引用
output = h(result)
return output

1.3 不要對(duì)太大的序列運(yùn)行 RNN

通過(guò) RNN 反向傳播所需的內(nèi)存量與 RNN 輸入的長(zhǎng)度成線性比例;因此,如果您嘗試向 RNN 輸入過(guò)長(zhǎng)的序列,則會(huì)耗盡內(nèi)存。這種現(xiàn)象的技術(shù)術(shù)語(yǔ)是到時(shí)間的反向傳播(BPTT),可以通過(guò)截?cái)?BPTT 來(lái)解決。

## 使用截?cái)?BPTT
def repackage_hidden(h):
    """Wraps hidden states in new Tensors, to detach them from their history."""
    if isinstance(h, torch.Tensor):
        return h.detach()
    else:
        return tuple(repackage_hidden(v) for v in h)

1.4 請(qǐng)勿使用太大的線性圖層

線性層 nn.Linear(m, n) 使用的內(nèi)存量與要素?cái)?shù)量成正比關(guān)系。例如,nn.Linear(10000, 10000) 將使用 10000 * 10000 = 100,000,000 個(gè)浮點(diǎn)數(shù),這大約是 400MB 的內(nèi)存(假設(shè)每個(gè)浮點(diǎn)數(shù)是 4 字節(jié))。如果您同時(shí)需要存儲(chǔ)梯度,則內(nèi)存使用量將翻倍。以這種方式穿透內(nèi)存非常容易。

二、我的 GPU 內(nèi)存未正確釋放

PyTorch 使用緩存內(nèi)存分配器來(lái)加速內(nèi)存分配。因此,nvidia-smi 中顯示的值通常不能反映真實(shí)的內(nèi)存使用情況。有關(guān) GPU 內(nèi)存管理的更多詳細(xì)信息,請(qǐng)參見(jiàn)內(nèi)存管理。

如果即使在退出 Python 后仍沒(méi)有釋放 GPU 內(nèi)存,則很可能某些 Python 子進(jìn)程仍然存在。您可以通過(guò) ps -elf | grep python 找到它們,然后使用 kill -9 [pid] 手動(dòng)將其殺死。

## 手動(dòng)清理 GPU 緩存
torch.cuda.empty_cache()

三、我的數(shù)據(jù)加載器工作人員返回相同的隨機(jī)數(shù)

您可能會(huì)使用其他庫(kù)在數(shù)據(jù)集中生成隨機(jī)數(shù)。例如,當(dāng)通過(guò) fork 啟動(dòng)工作程序子流程時(shí),NumPy 的 RNG 被復(fù)制??梢酝ㄟ^(guò) worker_init_fn 選項(xiàng)在工人中正確設(shè)置隨機(jī)種子。

import numpy as np
import torch


def worker_init_fn(worker_id):
    np.random.seed(np.random.get_state()[1][0] + worker_id)


dataloader = torch.utils.data.DataLoader(
    dataset,
    num_workers=4,
    worker_init_fn=worker_init_fn
)

四、我的經(jīng)常性網(wǎng)絡(luò)無(wú)法使用數(shù)據(jù)并行性

ModuleDataParalleldata_parallel() 中使用 pack sequence -> recurrent network -> unpack sequence 模式是很微妙的。每個(gè)設(shè)備上每個(gè) forward() 的輸入僅是整個(gè)輸入的一部分。由于默認(rèn)情況下,拆包操作 torch.nn.utils.rnn.pad_packed_sequence() 僅填充其看到的最長(zhǎng)輸入,即該特定設(shè)備上的最長(zhǎng)輸入,因此,將結(jié)果匯總在一起時(shí)會(huì)發(fā)生大小不匹配的情況。因此,您可以改而利用 pad_packed_sequence()total_length 自變量來(lái)確保 forward() 調(diào)用相同長(zhǎng)度的返回序列。

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


class MyModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.my_lstm = nn.LSTM(input_size=10, hidden_size=20, batch_first=True)


    def forward(self, padded_input, input_lengths):
        total_length = padded_input.size(1)  # 獲取最大序列長(zhǎng)度
        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)

此外,當(dāng)批處理尺寸為 1(即 batch_first=False)且數(shù)據(jù)并行時(shí),需要格外小心。在這種情況下,pack_padded_sequence 的第一個(gè)參數(shù)的形狀將為 [T x B x *],并且應(yīng)沿昏暗 1 分散,而第二個(gè)參數(shù) input_lengths 的形狀將為 [B],并且應(yīng)沿昏暗 0 分散。

## 批處理尺寸為 1 的情況
padded_input = torch.randn(10, 1, 10)  # [T x B x *]
input_lengths = torch.tensor([10])      # [B]


packed_input = pack_padded_sequence(padded_input, input_lengths, batch_first=False)
packed_output, _ = m.my_lstm(packed_input)
output, _ = pad_packed_sequence(packed_output, batch_first=False, total_length=padded_input.size(0))

五、常見(jiàn)問(wèn)題解答(Q&A)

Q1:如何避免在 PyTorch 中出現(xiàn) CUDA 內(nèi)存不足的問(wèn)題?

A1:可以通過(guò)以下幾種方式避免 CUDA 內(nèi)存不足的問(wèn)題:

  • 不要在訓(xùn)練循環(huán)中累積歷史記錄,避免不必要的內(nèi)存占用。
  • 及時(shí)釋放不需要的張量和變量,使用 del 語(yǔ)句。
  • 對(duì)于 RNN,使用截?cái)嗟姆聪騻鞑ィ╰runcated BPTT)來(lái)減少內(nèi)存占用。
  • 避免使用過(guò)大的線性層,減少內(nèi)存需求。
  • 使用 torch.cuda.empty_cache() 手動(dòng)清理 GPU 緩存。

Q2:如何解決數(shù)據(jù)加載器工作進(jìn)程返回相同隨機(jī)數(shù)的問(wèn)題?

A2:可以通過(guò)設(shè)置 worker_init_fn 來(lái)解決數(shù)據(jù)加載器工作進(jìn)程返回相同隨機(jī)數(shù)的問(wèn)題。在 worker_init_fn 中為每個(gè)工作進(jìn)程設(shè)置不同的隨機(jī)種子。

def worker_init_fn(worker_id):
    np.random.seed(np.random.get_state()[1][0] + worker_id)


dataloader = DataLoader(
    dataset,
    num_workers=4,
    worker_init_fn=worker_init_fn
)

Q3:如何在使用數(shù)據(jù)并行性時(shí)解決 RNN 的大小不匹配問(wèn)題?

A3:可以通過(guò)使用 pad_packed_sequencetotal_length 參數(shù)來(lái)確保所有設(shè)備上的輸出序列長(zhǎng)度一致。在定義 RNN 模塊時(shí),確保在 forward 方法中傳遞 total_length 參數(shù)。

output, _ = pad_packed_sequence(packed_output, batch_first=True, total_length=total_length)

Q4:如何檢查和清理未釋放的 GPU 內(nèi)存?

A4:可以通過(guò)以下步驟檢查和清理未釋放的 GPU 內(nèi)存:

  1. 使用 nvidia-smi 查看 GPU 內(nèi)存使用情況。
  2. 如果發(fā)現(xiàn)內(nèi)存未正確釋放,可以使用 torch.cuda.empty_cache() 手動(dòng)清理緩存。
  3. 如果問(wèn)題仍然存在,可以檢查是否有子進(jìn)程未正確退出,并使用 kill -9 [pid] 手動(dòng)殺死這些進(jìn)程。

Q5:如何優(yōu)化 RNN 的內(nèi)存使用?

A5:可以通過(guò)以下幾種方式優(yōu)化 RNN 的內(nèi)存使用:

  • 使用截?cái)嗟姆聪騻鞑ィ╰runcated BPTT)減少內(nèi)存占用。
  • 減少序列長(zhǎng)度,避免過(guò)長(zhǎng)的序列導(dǎo)致內(nèi)存不足。
  • 使用更小的批量大小,減少單次計(jì)算的內(nèi)存需求。
  • 優(yōu)化模型結(jié)構(gòu),減少不必要的計(jì)算和存儲(chǔ)。

六、優(yōu)化技巧與最佳實(shí)踐

6.1 內(nèi)存管理最佳實(shí)踐

  • 避免不必要的張量復(fù)制:盡量減少?gòu)埩康膹?fù)制操作,因?yàn)檫@會(huì)增加內(nèi)存占用。
  • 使用 inplace 操作:某些操作(如 add_())會(huì)在原地修改張量,減少內(nèi)存使用。
  • 及時(shí)釋放張量:使用 del 語(yǔ)句及時(shí)釋放不再需要的張量。
  • 使用 torch.cuda.empty_cache():在需要時(shí)手動(dòng)清理 GPU 緩存,釋放未使用的內(nèi)存。

6.2 數(shù)據(jù)加載器優(yōu)化

  • 設(shè)置 worker_init_fn:確保數(shù)據(jù)加載器工作進(jìn)程正確初始化隨機(jī)種子,避免返回相同的隨機(jī)數(shù)。
  • 使用 num_workers:合理設(shè)置 num_workers 參數(shù),提高數(shù)據(jù)加載效率。
  • 優(yōu)化數(shù)據(jù)預(yù)處理:盡量減少數(shù)據(jù)預(yù)處理的復(fù)雜度,提高數(shù)據(jù)加載速度。

6.3 模型優(yōu)化

  • 使用混合精度訓(xùn)練:通過(guò)使用混合精度訓(xùn)練(AMP)減少內(nèi)存占用并加速計(jì)算。
  • 優(yōu)化模型結(jié)構(gòu):減少模型的復(fù)雜度,避免使用過(guò)大的線性層和 RNN 層。
  • 使用模型量化:對(duì)模型進(jìn)行量化,減少內(nèi)存占用和計(jì)算量。

七、總結(jié)與展望

通過(guò)本文的介紹,我們總結(jié)了 PyTorch 中常見(jiàn)的內(nèi)存管理和數(shù)據(jù)加載問(wèn)題,并提供了解決方案和優(yōu)化技巧。希望這些內(nèi)容能夠幫助您更好地理解和使用 PyTorch,提高模型的訓(xùn)練效率和性能。

關(guān)注編程獅(W3Cschool)平臺(tái),獲取更多 PyTorch 相關(guān)的優(yōu)質(zhì)教程和資源。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)