国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

解決pytorch中Dataloader讀取數(shù)據(jù)太慢的問(wèn)題

這篇具有很好參考價(jià)值的文章主要介紹了解決pytorch中Dataloader讀取數(shù)據(jù)太慢的問(wèn)題。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

提示:文章寫(xiě)完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔


前言

最近在使用pytorch框架進(jìn)行模型訓(xùn)練時(shí)遇到一個(gè)性能問(wèn)題,即數(shù)據(jù)讀取的速度遠(yuǎn)遠(yuǎn)大于GPU訓(xùn)練的速度,導(dǎo)致整個(gè)訓(xùn)練流程中有大部分時(shí)間都在等待數(shù)據(jù)發(fā)送到GPU,在資源管理器中呈現(xiàn)出CUDA使用率周期性波動(dòng),且大部分時(shí)間都是在等待數(shù)據(jù)加載。


一、造成的原因

其實(shí)從前言中就可以知道,造成這樣的原因可以理解為:GPU的算力與數(shù)據(jù)加載速度之間的不匹配。

二、查找不匹配的原因

本人使用的GPU為RTX3060,數(shù)據(jù)集為cifar10,使用的模型為VGG,顯然這張顯卡對(duì)于這個(gè)任務(wù)來(lái)說(shuō)是綽綽有余的,無(wú)論是顯存還是算力。
但是幾經(jīng)測(cè)試發(fā)現(xiàn),數(shù)據(jù)從內(nèi)存送到GPU的速度實(shí)在是太慢了,去百度了很久都沒(méi)有很好的解決。那回到這個(gè)問(wèn)題的本身,既然是數(shù)據(jù)加載導(dǎo)致的性能差,那問(wèn)題就出在pytorch的datasetdataloader中。

在dataset中,會(huì)將數(shù)據(jù)從磁盤(pán)讀入內(nèi)存中,如果啟用了dataloader中的pin_memory,就會(huì)讓數(shù)據(jù)常駐內(nèi)存,同時(shí)設(shè)置num_workers還能實(shí)現(xiàn)多進(jìn)程讀取數(shù)據(jù),但即使設(shè)置了這些,數(shù)據(jù)加載速度依然沒(méi)有質(zhì)的提升。

博主發(fā)現(xiàn),dataset中的transform是導(dǎo)致性能慢的一個(gè)原因,dataset中有個(gè)函數(shù)為_(kāi)_getitem__,每獲取一個(gè)數(shù)據(jù)就會(huì)讓這個(gè)數(shù)據(jù)過(guò)一次transform。相信大家都寫(xiě)過(guò)如下的代碼:

transform = transforms.Compose([
	transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.4914, 0.4822, 0.4465], [0.5, 0.5, 0.5])
])

但是這里的ToTensor和Normalize完全沒(méi)必要沒(méi)讀一次數(shù)據(jù)都處理一次,可以在數(shù)據(jù)加載到內(nèi)存的時(shí)候就直接全部處理完,這樣每個(gè)數(shù)據(jù)只需要經(jīng)歷一次ToTensor和Normalize,這會(huì)大大提高數(shù)據(jù)讀取速度,大家可以自行測(cè)試一次ToTensor和Normalize所需要的時(shí)間,還是非常大的。

在訓(xùn)練的過(guò)程中,相信大家也寫(xiě)過(guò)如下代碼:

for x, y in dataloader:
	x, y = x.cuda(), y.cuda()

經(jīng)過(guò)博主測(cè)試,將數(shù)據(jù)發(fā)送到GPU也是非常耗時(shí)的,那為什么不一次性全部加載到GPU里面呢?當(dāng)然前提是你的GPU顯存夠大。

三、解決方法

以上分析可以總結(jié)為兩點(diǎn):

  1. 數(shù)據(jù)的預(yù)處理有一部分可以提前對(duì)全部數(shù)據(jù)做一遍;
  2. 如果顯存足夠,可以將數(shù)據(jù)全部加載到GPU中。

基于此,我們可以重載類(lèi),這里以pytorch自帶的cifar10為例:

class CUDACIFAR10(CIFAR10):
    def __init__(
            self, 
            root: str, 
            train: bool = True,
            to_cuda: bool = True,
            half: bool = False,
            pre_transform: Optional[Callable] = None,
            transform: Optional[Callable] = None, 
            target_transform: Optional[Callable] = None, 
            download: bool = False) -> None:

        super().__init__(root, train, transform, target_transform, download)
        if pre_transform is not None:
            self.data = self.data.astype("float32")
            for index in range(len(self)):
                """
                ToTensor的操作會(huì)檢查數(shù)據(jù)類(lèi)型是否為uint8, 如果是, 則除以255進(jìn)行歸一化, 這里data提前轉(zhuǎn)為float,
                所以手動(dòng)除以255.
                """
                self.data[index] = pre_transform(self.data[index]/255.0).numpy().transpose((1, 2, 0))
                self.targets[index] = torch.Tensor([self.targets[index]]).squeeze_().long()
                if to_cuda:
                    self.targets[index] = self.targets[index].cuda()
            self.data = torch.Tensor(self.data).permute((0, 3, 1, 2))
            if half:
                self.data = self.data.half()
            if to_cuda:
                self.data = self.data.cuda()

    def __getitem__(self, index: int) -> Tuple[Any, Any]:
        """
        Args:
            index (int): Index

        Returns:
            tuple: (image, target) where target is index of the target class.
        """
        img, target = self.data[index], self.targets[index]

        if self.transform is not None:
            img = self.transform(img)
        if self.target_transform is not None:
            target = self.target_transform(target)
        return img, target

to_cuda為T(mén)rue就會(huì)讓數(shù)據(jù)全部加載到GPU中,后續(xù)就不需要寫(xiě)x, y = x.cuda(), y.cuda()了。
pre_transform就是讓所有數(shù)據(jù)提前進(jìn)行的處理,例如使用ToTensor和Normalize,后續(xù)調(diào)用時(shí)不會(huì)再進(jìn)行這些處理。
transform為后續(xù)調(diào)用時(shí)會(huì)進(jìn)行的處理,一般就是一些隨機(jī)處理過(guò)程。

在博主的測(cè)試過(guò)程中發(fā)現(xiàn),解決了以上問(wèn)題后,一個(gè)epoch只要2秒就能完成,而平時(shí)需要15秒,并且任務(wù)管理器中的CUDA幾乎全程拉滿。唯一的代價(jià)就是顯存占用更高了,這何嘗不是一種空間換時(shí)間。

四、使用方法

這里直接粘貼我為這個(gè)類(lèi)寫(xiě)的注釋

- 使用pytorch自帶的CIFAR10時(shí), 每讀取一個(gè)數(shù)據(jù)都會(huì)調(diào)用一次transforms, 其中ToTensor()和Normalize()會(huì)消耗巨大的時(shí)間
  如果你的數(shù)據(jù)集非常的大, 那么一個(gè)epoch將會(huì)花費(fèi)非常多的時(shí)間用于讀取數(shù)據(jù), 如果還要將數(shù)據(jù)送入GPU, 那么時(shí)間將會(huì)繼續(xù)增加。

- 一般的寫(xiě)法如下:

    for epoch in range(epochs):
        for x, y in dataloader:
            x, y = x.cuda(), y.cuda()

  如果你的數(shù)據(jù)集很大并且GPU算力很強(qiáng), 那么讀取數(shù)據(jù)并發(fā)送的GPU將會(huì)成為性能瓶頸。

- CUDACIFAR10是專(zhuān)門(mén)針對(duì)pytorch的CIFAR10進(jìn)行優(yōu)化的, 使用的前提是你的顯存足夠的大, 至少8GB, 且讀取數(shù)據(jù)已經(jīng)是性能瓶頸。
  CUDACIFAR10的參數(shù)與CIFAR10非常相似, 新增的參數(shù)為:
    to_cuda: bool, 是否將數(shù)據(jù)集常駐GPU, default=True
    half: bool, 進(jìn)一步降低數(shù)據(jù)所占據(jù)的顯存, 在混合精度訓(xùn)練時(shí)使用, 否則可能存在意外(例如梯度值overflow)
    pre_transform: 傳入一個(gè)transforms, 如果不為None, 則會(huì)在初始化數(shù)據(jù)時(shí)直接對(duì)所有數(shù)據(jù)進(jìn)行對(duì)應(yīng)的轉(zhuǎn)換, 在后續(xù)調(diào)用時(shí)將
                    不會(huì)使用pre_transform. 可以將ToTensor()和Normalize()作為pre_transform, 這會(huì)大幅度減少讀取時(shí)間.

- CUDACIFAR10的用法如下:

    pre_transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize([0.4914, 0.4822, 0.4465], [0.5, 0.5, 0.5])
    ])
    dataset = CUDACIFAR10(..., to_cuda=True, pre_transform=pre_transform, ...)
    dataloader = Dataloader(dataset, ..., pin_memory=False, num_workers=0, ...)
    ...
    for epoch in range(epochs):
        for x, y in dataloader:
            # 不需要寫(xiě)x, y = x.cuda(), y.cuda(), 除非to_cuda=False
            ...

- 使用CUDACIFAR10需要注意如果啟用了to_cuda, 那么Dataloader不能啟用pin_memory, pin_memory是將數(shù)據(jù)常駐內(nèi)存, 這會(huì)產(chǎn)生沖突.
  同時(shí)num_workers=0.

- 如果參數(shù)to_cuda=False, pre_transform=None, 那么該類(lèi)與CIFAR10用法完全一致.

后言

本文寫(xiě)作倉(cāng)促,可能有部分錯(cuò)誤,歡迎大家的批評(píng)與指正。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-410887.html

到了這里,關(guān)于解決pytorch中Dataloader讀取數(shù)據(jù)太慢的問(wèn)題的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 全網(wǎng)詳細(xì)解決git官網(wǎng)下載太慢的問(wèn)題

    全網(wǎng)詳細(xì)解決git官網(wǎng)下載太慢的問(wèn)題

    我們?cè)陂_(kāi)發(fā)的過(guò)程中,無(wú)可避免地要使用到 git ,來(lái)托管我們的代碼。 它是一個(gè)開(kāi)源的分布式版本控制系統(tǒng),用于敏捷高效地處理任何或小或大的項(xiàng)目。 使用 git 的前提是要下載和安裝它,因而,我們可以點(diǎn)擊它的官網(wǎng)鏈接地址:https://git-scm.com。 打開(kāi)官網(wǎng)鏈接后,如果你的

    2024年01月23日
    瀏覽(94)
  • pytorch進(jìn)階學(xué)習(xí)(二):使用DataLoader讀取自己的數(shù)據(jù)集

    pytorch進(jìn)階學(xué)習(xí)(二):使用DataLoader讀取自己的數(shù)據(jù)集

    上一節(jié)使用的是官方數(shù)據(jù)集fashionminist進(jìn)行訓(xùn)練,這節(jié)課使用自己搜集的數(shù)據(jù)集來(lái)進(jìn)行數(shù)據(jù)的獲取和訓(xùn)練。 教學(xué)視頻:https://www.bilibili.com/video/BV1by4y1b7hX/?spm_id_from=333.1007.top_right_bar_window_history.content.clickvd_source=e482aea0f5ebf492c0b0220fb64f98d3 pytorch進(jìn)階學(xué)習(xí)(一):https://blog.csdn.net/w

    2024年02月09日
    瀏覽(17)
  • Git 安裝并初始化 + 官網(wǎng)下載速度太慢的問(wèn)題

    Git 安裝并初始化 + 官網(wǎng)下載速度太慢的問(wèn)題

    目錄 1. 快速下載 2. 初始化 當(dāng)你興致勃勃地去官網(wǎng)下載 git 的時(shí)候,突然發(fā)現(xiàn),嗯??下載完成還需 9 個(gè)小時(shí)? 快速下載點(diǎn)這里! 打開(kāi)之后是這個(gè)樣子: ?我們可以自行選擇下載版本,并點(diǎn)擊,然后選擇 64 位的 exe,開(kāi)始下載: (1)右擊以管理員身份執(zhí)行 exe 文件 ?(2)填

    2024年02月11日
    瀏覽(23)
  • git clone拉取GitHub項(xiàng)目失敗/太慢的解決方法

    針對(duì) 在Ubuntu中通過(guò)git clone從GitHub上拉取項(xiàng)目時(shí),遇到失敗/速度慢等情況, 記錄本人的解決思路。 方案一、使用gitclone gitclone.com是一個(gè)提供下載緩存的代碼下載網(wǎng)站,使用方法簡(jiǎn)單,只需要 在倉(cāng)庫(kù)地址前面加上 gitclone.com ,就可以使速度提升幾倍。(個(gè)人覺(jué)得速度很慢) 例

    2024年04月27日
    瀏覽(28)
  • PlatformIO在Vscode中創(chuàng)建工程太慢的解決辦法

    PlatformIO在Vscode中創(chuàng)建工程太慢的解決辦法

    在Vscode中創(chuàng)建PlatformIO的Esp32工程,會(huì)始終停留在Please Wait…,嘗試用如下兩種解決方案 打開(kāi)PlatformIO CLI,在右側(cè)打開(kāi)的命令行中輸入pio home,會(huì)在默認(rèn)瀏覽器中打開(kāi)PlatformIO網(wǎng)頁(yè)版,按步驟創(chuàng)建ESP32項(xiàng)目即可。 手動(dòng)創(chuàng)建工程文件夾,打開(kāi)終端,命令行執(zhí)行 注意:vscode中安裝的

    2024年02月07日
    瀏覽(19)
  • centos虛擬機(jī)使用docker下載鏡像太慢的解決辦法

    centos虛擬機(jī)使用docker下載鏡像太慢的解決辦法

    虛擬環(huán)境: 1、VMware Workstation 16 Pro 2、CentOS 7(CentOS Linux release 7.9.2009 (Core),內(nèi)核版本3.10.0-1160.el7.x86_64) 問(wèn)題描述: ? ? ? ?虛擬機(jī)可以與物理主機(jī)互相Ping通,也可以Ping通百度,但是總是莫名其妙斷網(wǎng),下載docker鏡像幾乎很難(已經(jīng)配置了鏡像源,但是下載速度非常非常慢,

    2024年04月11日
    瀏覽(24)
  • git submodule update --init命令速度太慢的解決方法

    git submodule update --init命令速度太慢的解決方法

    我們?cè)?clone 某個(gè)代碼庫(kù)時(shí),代碼庫(kù)可能使用了其他代碼庫(kù)的資源,開(kāi)發(fā)者為避免重復(fù)開(kāi)發(fā),將使用到的其他庫(kù)以鏈接的方式作為公共資源保存,我們需要在 clone 之后執(zhí)行以下命令才能得到完整的依賴(lài): 但是在執(zhí)行 git submodule update --init 命令時(shí),由于沒(méi)有提示條,且看不到實(shí)

    2024年02月12日
    瀏覽(28)
  • Ubuntu/Linux/Win系統(tǒng)中g(shù)it clone速度太慢的解決辦法

    在http://tool.chinaz.com/dns中查詢(xún)下面三個(gè)域名: 進(jìn)入終端命令行模式,輸入sudo gedit /etc/hosts 在文件最后添加相應(yīng)的IP和域名。如下:記錄更換 你查詢(xún)的IP哦! 完成!

    2024年02月08日
    瀏覽(19)
  • SSH連接下Git fetch/pull/push 速度太慢的一些解決辦法

    SSH連接下Git fetch/pull/push 速度太慢的一些解決辦法

    有時(shí)候某些git的代碼庫(kù)在fetch遠(yuǎn)端的時(shí)候會(huì)非常慢,速度只有幾十k或者幾k。這個(gè)速度拉取一整個(gè)代碼庫(kù)可能要花費(fèi)一晚上或者一天時(shí)間。甚至在每天更新已有代碼庫(kù)時(shí)候也會(huì)花上十分鐘??梢試L試一下這些方法來(lái)提升拉取遠(yuǎn)端代碼的速度: 1. Git 版本過(guò)低的話可能會(huì)導(dǎo)致這個(gè)

    2024年02月10日
    瀏覽(47)
  • 【深度學(xué)習(xí)】torch.utils.data.DataLoader相關(guān)用法 | dataloader數(shù)據(jù)加載器 | pytorch

    【深度學(xué)習(xí)】torch.utils.data.DataLoader相關(guān)用法 | dataloader數(shù)據(jù)加載器 | pytorch

    dataloader數(shù)據(jù)加載器屬于是深度學(xué)習(xí)里面非常基礎(chǔ)的一個(gè)概念了,基本所有的圖像項(xiàng)目都會(huì)用上,這篇博客就把它的相關(guān)用法總結(jié)一下。 之所以要寫(xiě)這篇,是想分清楚len(data_loader)和len(data_loader.dataset) 這里加載的數(shù)據(jù)我們以Mnist手寫(xiě)數(shù)據(jù)集為例子 torchvision.datasets.MNIST是用來(lái)加載

    2024年02月16日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包