NTU60RGBD数据集训练速度慢问题和解决

数据集深度图展示

创作原因

本人最近在进行计算机视觉的研究,用到了该数据集,在运行该数据集的过程中遇到了问题,训练速度极慢,cpu和gpu使用率低,io活跃,最终解决了问题,在查找资料的过程中,发现网络上基本没有对于相关问题的讨论,借此机会多谈谈我的想法。

问题原因

本人的实验设备为4块3090显卡,个人认为可以称得上是非常高配了。

数据集大小,单纯的ntu60深度数据原始数据约为88G,ntu120更大,超过了100G,本文仅讨论ntu60,其实这里大小还行,但是对于数据预处理后大小来到了665G,我的个人PC已经装不下了,只能自掏腰包买了个移动硬盘(1T)。

数据集加载代码如下:

import os
import sys
import numpy as np
from torch.utils.data import Dataset

Cross_Subject = [1, 2, 4, 5, 8, 9, 13, 14, 15, 16, 17, 18, 19, 25, 27, 28, 31, 34, 35, 38]

def clip_normalize(clip):
    pc = np.reshape(a=clip, newshape=[-1, 3])
    centroid = np.mean(pc, axis=0)
    pc = pc - centroid
    m = np.max(np.sqrt(np.sum(pc**2, axis=1)))
    clip = (clip - centroid) / m
    return clip

class CLRNTU60Subject(Dataset):
    def __init__(self, root, meta, frames_per_clip=23, step_between_clips=2, num_points=2048, step_between_frames=2, train=True):
        super(CLRNTU60Subject, self).__init__()

        self.videos = []
        self.index_map = []
        index = 0

        with open(meta, 'r') as f:
            for line in f:
                name, nframes = line.split()
                subject = int(name[9:12])
                if train:
                    if subject in Cross_Subject:
                        label = int(name[-3:]) - 1
                        nframes = int(nframes)
                        for t in range(0, nframes-step_between_frames*(frames_per_clip-1), step_between_clips):
                            self.index_map.append((index, t))
                        index += 1
                        self.videos.append(os.path.join(root, name+'.npz'))

        self.frames_per_clip = frames_per_clip
        self.step_between_clips = step_between_clips
        self.step_between_frames = step_between_frames
        self.num_points = num_points
        self.train = train


    def __len__(self):
        return len(self.index_map)

    def __getitem__(self, idx):
        index, t = self.index_map[idx]

        video = self.videos[index]
        video = np.load(video, allow_pickle=True)['data'] * 100

        clip = [video[t+i*self.step_between_frames] for i in range(self.frames_per_clip)]
        for i, p in enumerate(clip):
            if p.shape[0] > self.num_points:
                r = np.random.choice(p.shape[0], size=self.num_points, replace=False)
            else:
                repeat, residue = self.num_points // p.shape[0], self.num_points % p.shape[0]
                r = np.random.choice(p.shape[0], size=residue, replace=False)
                r = np.concatenate([np.arange(p.shape[0]) for _ in range(repeat)] + [r], axis=0)
            clip[i] = p[r, :]
        clip = clip_normalize(np.array(clip))

        if self.train:
            # scale the points
            scales = np.random.uniform(0.9, 1.1, size=3)
            clip = clip * scales

        clip = clip.astype(np.float32) # [L, N, 3]

        return clip, index

Dataset中,__init__方法仅加载路径,直到调用__getitem__才会从磁盘中读取对应数据。

665G数据无法直接装入内存,因此需要把数据先装入先读入内存再送给gpu运行,而由于磁盘的访问速度较慢,这里我们就发现磁盘的io速度成为了瓶颈。个人测试过,对于较小数据集可以直接装入内存,就不存在该问题,即使不在init将所有数据装入,速度也不会受到太大影响,因为大部分数据在运行第一轮后还在内存中,并不会被移出内存,后续运行时可以直接在内存中找到,减少了io次数。

解决方法

网上许多人遇到了该问题,有些想法提出在Dataloader上下手,但是经个人测试效果都不明显

但是这是硬件问题,当然,不能排除有些代码问题也会导致运行速度慢,比如环境配置时配错了,这是建议运行小型数据集(能装入内存),看看运行速度是否依然有影响。

最终解决方法非常简单粗暴,把数据存放在固态硬盘中,io瓶颈就解决了,这个问题困扰了我好几天,这算不上什么好方法,但确实目前唯一能有效解决我问题的方法。

使用iotop查看磁盘吞吐速率,机械硬盘每秒读写速度约为40MB/S,而固态硬盘达到了800MB/S,读写速度足够快,cpu基本可以全速运行,机器性能得到充分利用

结尾

如果你有什么好方法,欢迎在评论区留言,大家共同讨论。

参考文献

一些已有解决方法供大家参考

Pytorch如何加速,让GPU利用率维持较高水平? - 知乎 (zhihu.com)

给训练踩踩油门 —— Pytorch 加速数据读取 - 知乎 (zhihu.com)

感谢前人提出的方法

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值