当前位置: 首页 > 科技观察

它比原始版本快110倍,PyTorch的CPU-to-GPU张量迁移工具是开源的

时间:2023-03-18 18:55:18 科技观察

机器学习。有一个限速环节,就是tensor从CPU迁移到GPU。很多计算只能在CPU上进行,然后迁移到GPU上进行后续的训练工作。因此,如果迁移速度过慢,会拖累整个模型的训练效率。最近有开发者开源了一个PyTorch的CPU->GPU迁移工具,比原来的版本快了110倍。神经网络的训练往往需要很多环节的加速,这就是为什么我们逐渐使用GPU代替CPU,使用各种算法来加速机器学习过程。然而,在很多情况下,GPU不能做CPU做的很多事情。例如训练wordembeddings时,计算是在CPU上进行的,然后需要将训练好的wordembeddings转移到GPU上进行训练。在此过程中,张量传输会变得非常缓慢,成为机器学习训练的瓶颈。面对这样的问题,在很多优化方法中,都是尽可能把操作放在GPU上(比如数据预处理,wordembedding等直接放在GPU上),努力减少与GPU之间的数据交互二、因为这些环节非常耗时。机器之心曾经报过这样一个教程,把数据预处理放在了GPU上,减少了很多时间。以上例子表明,如果能够做好CPU和GPU之间的迁移,可以帮助开发者更好的优化机器学习模型,让CPU、GPU等硬件更好的完成工作。最近,有开发者开源了一款名为SpeedTorch的工具。这个工具库可以实现高达110倍的CPU到GPU迁移加速。项目地址:https://github.com/Santosh-Gupta/SpeedTorch项目背景作者说创建SpeedTorch库的初衷是为了帮助训练大量的embedding向量,而GPU可能很难将这些embeddings保存在内存。为了解决这个问题,他发现将其中一些嵌入托管在CPU上有助于将它们保存在GPU上。嵌入式系统采用稀疏训练,只有一部分参数参与前馈/更新操作,其余参数闲置。于是作者想,为什么不在训练过程中关掉这些闲置的参数呢?这就需要具备快速的CPU→GPU数据迁移能力。随着CPU→GPU迁移的加速,除了加速张量从CPU到GPU的迁移,开发者还可以实现很多新的功能。将SpeedTorch库嵌入到数据管道中,实现CPU和GPU之间快速的双向数据交互;通过CPU存储将模型的训练参数增加近2倍(闲置参数存储在CPU中,需要更新时再移至GPU,可扩展模型整体参数量);Adadelta、Adamax、RMSprop、Rprop、ASGD、AdamW和Adam优化器用于训练稀疏嵌入向量。之前只有SpraseAdam、Adagrad和SGD适合稀疏嵌入训练。那么,实现如此惊人加速的库是如何做到的呢?SpeedTorch背后的技术SpeedTorch之所以如此之快,是因为它基于Cupy。CuPy是一个借助CUDAGPU库在NVIDIAGPU上实现Numpy数组的库。基于Numpy数组的实现,GPU自带的多个CUDA核心可以带来更好的并行加速。CuPy接口是Numpy的镜像,在大多数情况下,它可以作为Numpy的直接替代品。用户只需将Numpy代码替换为兼容的CuPy代码,即可实现GPU加速。CuPy支持Numpy的大部分数组操作,包括索引、广播、数组数学和各种矩阵转换。有了如此强大的底层支持,再加上一些优化手段,SpeedTorch的速度可以达到110倍。如何使用SpeedTorch可以通过pip安装。在导入SpeedTorch之前,您需要安装并导入Cupy。安装步骤如下:!pipinstallSpeedTorchimportcupyimportSpeedTorch使用SpeedTorch加速CPU→GPU数据迁移下面的colabnotebook展示了如何使用DataGadget加载数据到SpeedTorch,以及如何将数据移入/移出Pytorchcuda变量。代码示例:https://colab.research.google.com/drive/185Z5Gi62AZxh-EeMfrTtjqxEifHOBXxF使用非稀疏优化器(在本例中为Adamax)通过SpeedTorch进行稀疏训练SkipGram_ModelRegular=SkipGramModelRegular(numEmbeds=number_items,emb_dimension=128,sparseB=True)use_cuda=torch.cuda.is_available()如果use_cuda:SkipGram_ModelRegular.cuda()optimizer=optim.SparseAdam(SkipGram_ModelRegular.parameters())runningLoss=0runnngTime=0batch_size=512negSamp=64numPos=4skip_windowsow=int()targets=torch.ones(batch_size,numPos+negSamp,dtype=torch.float32).cuda()foriinrange(500):batch,labels,negz=generate_batch(batch_size=batch_size,skip_window=skip_window,negRate=negSamp)batchTensor=torch.from_numpy(批次)LabelTensor=torch.from_numpy(labels)negTensor=torch.from_numpy(negz)pos_u=Variable(torch.LongTensor(LabelTensor.long()))pos_v=Variable(torch.LongTensor(batchTensor.long())))neg_v=Variable(torch.LongTensor(negTensor.long()))ifuse_cuda:pos_u=pos_u.cuda()pos_v=pos_v.cuda()neg_v=neg_v.cuda()optimizer.zero_grad()loss=SkipGram_ModelRegular.forward(pos_u,pos_v,neg_v,targets)runningLoss=runningLoss+loss.data.item()loss.backward()optimizer.step()代码示例:https://colab.research.google.com/drive/1ApJR3onbgQWM3FBcBKMvwaGXIDXlDXOt上面展示了如何以常规方式训练word2vec,然后展示了如何使用SpeedTorch训练相同的数据-在通常不支持稀疏训练的优化器上,因为嵌入变量包含每个部分中的所有嵌入。上面有更新,可以在初始化的时候设置sparse=False。性能部分记录了Cupy/PyTorch张量和PyTorch变量之间的数据迁移速度。其中需要迁移128维的embedding向量,共131072个32位浮点数。以下代码用于测试工作。所有测试均使用TeslaK80GPU。测试代码链接:https://colab.research.google.com/drive/1b3QpfSETePo-J2TjyO6D2LgTCjVrT1lu下表是对结果的总结。在相同情况下,将数据从PyTorchCUDA张量传输到CUDAPyTorch嵌入式变量比SpeedTorch更快,但对于所有其他传输类型,SpeedTorch更快。SpeedTorch对于常规GPU和CPU固定张量与Pytorch一样快,因为两个步骤的总和转移到CudaPytorch嵌入和从中转移。从表中可以看出,SpeedTorch确实比PyTorch自带的数据迁移方式要快很多。