当前位置: 首页 > news >正文

合肥响应式网站建设费用安徽干部学校建设网站

合肥响应式网站建设费用,安徽干部学校建设网站,网站建设合同缴印花税,极简网站设计PyTorch训练中Dataset多线程加载数据#xff0c;而不是在DataLoader 背景与需求 现在做深度学习的越来越多人都有用PyTorch#xff0c;他容易上手#xff0c;而且API相对TF友好的不要太多。今天就给大家带来最近PyTorch训练的一些小小的心得。 大家做机器学习、深度学习都…PyTorch训练中Dataset多线程加载数据而不是在DataLoader 背景与需求 现在做深度学习的越来越多人都有用PyTorch他容易上手而且API相对TF友好的不要太多。今天就给大家带来最近PyTorch训练的一些小小的心得。 大家做机器学习、深度学习都恨不得机器卡越多越好这样可以跑得越快道理好像也很直白大家都懂。实际上我们在训练的时候很大一部分制约我们的训练的速度快慢被IO限制住了然面CPU的利用率却不高就算有8卡了然而GPU的利用率却长期处理低水平不能发挥设备本应该有的水平。所以我一直在想有什么办法能加快IO的读取当然最直截的就换SSD那上速度会直接上去了。那如果是我们在服务器或者是普通的电脑就没有办法呢吗 而且经常用PyTorch的人应该会发现如果我们把DataLoader的num_workers设置比较大的时候在训练启动时会等待比较久而且在每一个epoch之间的切换也是需要等挺久的更换加载数据。 如果是一个程序员的话肯定会想到多线程、多进程这是否会能加速我们训练的IO答案是肯定的。 今天给大家带来的就是多线程读取数据的实例本次测试不含训练部分只是对Dataset, DataLoader数据加载的部分进行测试。 PyTorch DataLoader会产生一个index然后Dataset再进行读取如果一个batch_size128的话那就要产生128次的数据调试并读取。 我的想法就很简单我想要不我就直接在Dataset就生成好所需的Batches这样在DataLoader的batch_size1的话那也是对应一个batch的数据而我在Dataset的可以用线程去加载数据这样应该能提高读取的效率。 有了想法就是干了。 平时我们重要Dataset的结构如下这里用到了albumentations作为数据处理的库而不是torchvision的transforms其它没有什么区别的 def default_loader(path):return Image.open(path).convert(RGB)class AlbumentationsDatasetList(Dataset): Data processing using albumentation same as torchvision transformsdef __init__(self, imgs, transformNone, loaderdefault_loader, percentage1):# here can control the dataset size percentage img_num int(len(imgs) * percentage)self.imgs imgs[:img_num]self.transform transformself.loader loaderdef __getitem__(self, index):fn self.imgs[index]img self.loader(fn)if self.transform is not None:image_np np.array(img)augmented self.transform(imageimage_np)img augmented[image]return imgdef __len__(self):return len(self.imgs)方法的实现 说干就干把多线程加进来进行改造Dataset下面来看一下代码代码加入了一些细节所以会比较长但结构还是跟上面的是一样的。只是Dataset就已经把batches都处理好了在加载数据后是把他们都stack在一起这样就可以形成[N, C, W, H]结构的数据了。 注意如果drop_lastFalse的话那么最后的一个batch的数量一般不会与batch_size相同所以在DataLoader的里batch_size要设置成1。还有DataLoader设置成1后实际加载的数据是[1, N, C, W, H]所以在用的时候要squeeze一下。 class AlbumentationsDatasetList(Dataset):def __init__(self, images, batch_num, percentage1,transformNone, multi_loadTrue,shuffleTrue,seedNone,drop_lastFalse,num_workers4,loaderdefault_loader) - None:## Set seed#if seed is None:self.seed np.random.randint(0, 1e6, 1)[0] # Fix bug 2021-12-10else:self.seed seedrandom.seed(self.seed)# add some assertation if the image empty donot proceed. Fix 2021-12-12assert images is not None, fimages must be NOT empty, but got {images} self.images imagesself.batch_num batch_num # use batch_num instead of batch_size, same thingself.percentage percentageself.transform transformself.multi_load multi_loadself.shuffle shuffleself.drop_last drop_lastself.num_workers num_workers # Dataset num_workersself.loader loaderself.batches self._create_batches()self.batches self._get_len_batches(self.percentage)def _get_len_batches(self, percentage):Description:- you could control how many batches you want to use for training or validatingindices sort, so that could keep the batches got in order from originla batchesParameters:- percentage: float, range [0, 1]Return- numpy array of the new bagsbatch_num int(len(self.batches) * percentage)indices random.sample(list(range(len(self.batches))), batch_num)indices.sort()new_batches np.array(self.batches, dtypeobject)[indices]return new_batchesdef _create_batches(self,):if self.shuffle:random.shuffle(self.images)batches []ranges list(range(0, len(self.images), self.batch_num))for i in ranges[:-1]:batch self.images[i:i self.batch_num]batches.append(batch)# Drop last last_batch self.images[ranges[-1]:]if len(last_batch) self.batch_num:batches.append(last_batch)elif self.drop_last:passelse:batches.append(last_batch)return batchesdef __getitem__(self, index):batch self.batches[index]# Stack all images, become a 4 dimensional tensor if self.multi_load:batch_images self._multi_loader(batch)else:batch_images []for image in batch:img self._load_transform(image)batch_images.append(img)batch_images_tensor torch.stack(batch_images, dim0)return batch_images_tensordef _load_transform(self, tile):img self.loader(tile)if self.transform is not None:image_np np.array(img)augmented self.transform(imageimage_np)img augmented[image]return imgdef _multi_loader(self, tiles):images []executor ThreadPoolExecutor(max_workersself.num_workers)results executor.map(self._load_transform, tiles)executor.shutdown()for result in results:images.append(result)return imagesdef __len__(self):return len(self.batches)代码与数据测试 接下来就是拿数据进行测试了这里还设置了multi_load的参数这样我们可以方便控制是否用多线程与否这样我们就可以对比一下在相同的机器相同的数据下多线程加载数据是否比单线程快。 测试的目的 1是否多线程多单线程快2多线程能比单线路快多少3找到这机器最快或者比较全适的越参数可作为其它机器的参考。 测试平台Window10 CPUIntel Core i7-9850H 2.60GHz RAM: 32 GB 测试的数据是5000张图像全部都是3通道RBG8位的512x512像素图像图像格式是.PNG。 测试方法 超参数如下搜索空间为1024 multi_loads [True, False] prefetch_factors list(range(0, 17, 2))[1:] # [2, 4, 6, 8, 10, 12, 14, 16] dataset_workers list(range(0, 17, 2))[1:] dataloader_workers list(range(0, 17, 2))[1:]利用grid search方法每一个搜索空间都对Dataset, DataLoader设置不同的参数而且每轮数据都是读完、并处理完5000张图像drop_lastFalse 数据增强只做了resizenormalize 下面是全部的测试代码。 albumentations_valid album.Compose([album.Resize(480, 480),album.Normalize(mean[0.7347, 0.4894, 0.6820, ], std[0.1747, 0.2223, 0.1535, ]),ToTensorV2(),])from utils import get_specified_filespath rxxxxximages get_specified_files(path, suffixes[.png], recursiveTrue) # glob.globimages images[:5000]print(len(images))results []log_file open(rgrid_search_log.txt, modea, encodingutf-8)multi_loads [True, False]prefetch_factors list(range(0, 17, 2))[1:] # [2, 4, 6, 8, 10, 12, 14, 16]dataset_workers list(range(0, 17, 2))[1:]dataloader_workers list(range(0, 17, 2))[1:]for multi_load in multi_loads:for prefetch_factor in prefetch_factors:for dataset_worker in dataset_workers:for dataloader_worker in dataloader_workers:multi_load multi_loadif multi_load:prefetch_factor prefetch_factorelse:prefetch_factor prefetch_factordataloader_worker dataloader_workertrain_dataset AEDataset(images, batch_num128, percentage1, transformalbumentations_valid, multi_loadmulti_load, shuffleTrue, seed0, drop_lastFalse,num_workersdataset_worker,)train_loader DataLoader(datasettrain_dataset, batch_size1, shuffleFalse, num_workersdataloader_worker, pin_memoryTrue, prefetch_factorprefetch_factor, persistent_workersFalse)print(Start loading)start_time time.time()for i, (batches) in enumerate(train_loader):i1elapse time.time() - start_timeprint(fmulti_load: {multi_load}, prefetch_factors: {prefetch_factor}, dataset_workers: {dataset_worker}, data_loader_workers: {dataloader_worker}, elapse: {elapse:.4f})log_file.write(fmulti_load: {multi_load}, prefetch_factors: {prefetch_factor}, dataset_workers: {dataset_worker}, data_loader_workers: {dataloader_worker}, elapse: {elapse:.4f}\n)测试结果 回到我们上面的测试目标 测试的目的 1是否多线程多单线程快2多线程能比单线程快多少3找到这台机器最快或者比较全适的越参数可作为其它机器的参考。 我们带着这3个问题看一下下面的测试结果 import numpy as np import pandas as pd import matplotlib.pyplot as pltpath C:/Users/jasne/Desktop/grid_search_multi_load.csv df pd.read_csv(path) df.head()multi_loadprefetch_factorsdataset_workersdata_loader_workerselapse0True1414219.97461True1410219.98162True1412220.02053True810220.05144True1416220.0943 Max elapse 也是我们平时用的普通load的方法时间是72.28秒 df[df[elapse]df[elapse].max()]multi_loadprefetch_factorsdataset_workersdata_loader_workerselapse1024False11172.2857 Multi Load Max elapse 多线程时最慢的时间 multi_load df[df[multi_load]True] multi_load[multi_load[elapse]multi_load[elapse].max()]multi_loadprefetch_factorsdataset_workersdata_loader_workerselapse1023True6141648.3309 Min elapse 相差的倍数的计算公式为(max−min)/min(\text{max} - \text{min}) / \text{min}(max−min)/min 时间是19.97秒比最长的时间少了 52.31秒快了2.6倍的时间所以可以看出用multi_load肯定是比single load要快的。 多线程的时间也受prefetch_factors, dataset_workers, dataloader_workers的影响。而且影响还是比较大的。 多线程时最快与最慢的相差1.42倍 df[df[elapse]df[elapse].min()]multi_loadprefetch_factorsdataset_workersdata_loader_workerselapse0True1414219.9746 下面来看是否 data_loader_workers越大越好 dataloader_workers multi_load[(multi_load[prefetch_factors]2) (multi_load[dataset_workers]2)] dataloader_workers.sort_values(data_loader_workers, inplaceTrue) dataloader_workersmulti_loadprefetch_factorsdataset_workersdata_loader_workerselapse376True22228.6076102True22424.4866144True22626.3106410True22830.3909536True221033.2621724True221236.9114946True221441.3437986True221644.4443 plt.figure(figsize(8, 5)) plt.scatter(dataloader_workers[data_loader_workers], dataloader_workers[elapse]) plt.show()从图上可以看出dataloader_workers并非越大越好dataloader_workers4时是在2-8之间是比较好的选择。随着dataloader_workers的增加所需要的时间也呈线性的增加。 下面来看是否 dataset_workers越大越好 dataset_workers multi_load[(multi_load[prefetch_factors]2) (multi_load[data_loader_workers]2)] dataset_workers.sort_values(dataset_workers, inplaceTrue) dataset_workersmulti_loadprefetch_factorsdataset_workersdata_loader_workerselapse376True22228.607675True24223.509252True26222.427049True28222.246526True210221.757837True212222.011246True214222.194735True216221.9832 plt.figure(figsize(8, 5)) plt.scatter(dataset_workers[dataset_workers], dataset_workers[elapse]) plt.show()从图上可以看出dataset_workers增加也可以明显减少数据加载所需要时间。但是当dataset_workers超过10后不再呈现出减少的趋势当达到12、14时有一点点上降。由于测试平台有限这里所应该让测试一下dataset_workers达到128或者更高的数之间是否会达到更少的数据加载时间。 下面来看是否 prefetch_factors越大越好 prefetch_factors multi_load[(multi_load[dataset_workers]2) (multi_load[data_loader_workers]2)] prefetch_factors.sort_values(prefetch_factors, inplaceTrue) prefetch_factors​ multi_loadprefetch_factorsdataset_workersdata_loader_workerselapse376True22228.6076289True42227.7318309True62228.0899141True82226.2518378True102228.6515332True122228.2445135True142226.0284134True162226.0025 plt.figure(figsize(8, 5)) plt.scatter(prefetch_factors[prefetch_factors], prefetch_factors[elapse]) plt.show()[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UUp7MHiu-1634438695527)(C:/Users/jasne/Desktop/Untitled/output_18_0.png)] 从图上可以看出prefetch_factors似乎好像越大加载的时间越少但似乎也相差不多最多的时间与最小的时间相差也仅为2.6秒。 prefetch_factors的外一个筛选条件 prefetch_factors multi_load[(multi_load[dataset_workers]10) (multi_load[data_loader_workers]4)] prefetch_factors.sort_values(prefetch_factors, inplaceTrue) prefetch_factorsmulti_loadprefetch_factorsdataset_workersdata_loader_workerselapse70True210423.3808103True410424.4975108True610424.666053True810422.505890True1010424.155592True1210424.182539True1410422.0710120True1610425.0829 plt.figure(figsize(8, 5)) plt.scatter(prefetch_factors[prefetch_factors], prefetch_factors[elapse]) plt.show()从图上可以看出prefetch_factors数量似乎对加载时间的影响似乎不太明显最多的时间与最小的时间相差也仅为2.6秒。 multi_loadprefetch_factorsdataset_workersdata_loader_workerselapse70True210423.3808103True410424.4975108True610424.666053True810422.505890True1010424.155592True1210424.182539True1410422.0710120True1610425.0829 plt.figure(figsize(8, 5)) plt.scatter(prefetch_factors[prefetch_factors], prefetch_factors[elapse])plt.show()从图上可以看出prefetch_factors数量似乎对加载时间的影响似乎不太明显最多的时间与最小的时间相差也仅为2.6秒。 结论 多线程加载数据肯定是比单线程快的 这点是不用质疑的单从计算机的运行方式就可以得出这个结论这也是并行的优势。 多线程能比单线程快多少 从上面的结果我们看到当选用合适的超参数时多线程加载相同的数据与相同的处理方法比单线程快了52.31秒快了2.6倍有多。就算是最不好的参数多线和最长的加载时间为48.33秒也比单线程的72.28秒快差不多0.5倍。 找到这台机器最快或者比较全适的越参数可作为其它机器的参考 dataset_workers 越大越好但达到了一个临界值后不会再增加了本测试平台的值为10data_loader_workers不是越大越好本测试平台最好的值为4在4左右的值都是较好的参考值。然后随着此参数的数量的增加所需要的时间也呈线性的增涨这也说明了PyTorch大data_loader_workers启动需要等待更久的时间prefetch_factors的数量似乎对数据的加载时间影响不大但最好不要是1。 本次测试没有监测内存还有CPU的使用率但在过程中观察了一下CPU使用率基本都可以达到100%。也可以把这些参数也监测起来形成更多的超参数以便参考。 注意由于在训练的过程中也是需要利用CPU的所以尽量不要太多的dataset_workers尽量不要把CPU都使用到100%而造成死机。
http://www.yutouwan.com/news/269744/

相关文章:

  • 湖南省城乡与住房建设厅网站青岛网站建设模板下载
  • 想要网站推广版医院网站建设中标
  • wordpress本地使用百度优化是什么
  • 美工做兼职在那个网站帝国网站后台编辑器没有了
  • 企业网站建设费用入哪个科目公司响应式网站建设平台
  • 火龙果写作网站WordPress全局屏蔽谷歌
  • wordpress添加多个菜单关键词seo培训
  • 做360网站优化青岛 公司 网站建设
  • 中关村在线手机参数对比报价广州网站优化哪里有
  • 抖音特效开放平台网站seo策划方案
  • 门户网站重要性襄阳市住房和城乡建设局官方网站
  • 门户网站做等级保护测评网站开发什么方式
  • 河池做网站经常做ppt的网站
  • 网站建设毕业实践设计报告淘宝运营学习
  • 网站开发+兼职挣钱吗个人电商怎么做
  • 长沙网站建设icp备中国企业排名
  • 有做敦煌网站的吗网站域名验证功能上线
  • 网站搭建接单福州网站建设方案咨询
  • 电脑商业网站怎的做苏州外贸网站建设推广服务
  • 大学生毕业设计网站门户网站建设经验总结报告
  • 如何进行网站建设和推广汕头建设局网站
  • 建设博客网站步骤天津网站设计诺亚科技
  • 上海市建设工程检测行业协会网站太原心诺做网站
  • 北京网站代理备案静态网站什么意思
  • 门户网站免费建站安康相亲平台
  • 网站推广如何做的安徽城乡建设厅网站焊工证查询
  • 建设银行手机网站首页单页营销网站后台
  • 高青网站建设yx718网站开发毕设开题报告怎么写
  • php企业网站通讯录管理系统设计一个网站策划书
  • 微机课做网站做方案还找不到素材 这里有最全的设计网站