当前位置: 首页 > 后端技术 > Python

Python算法提速的四种方法(一)PyTorch出品

时间:2023-03-26 00:46:45 Python

CDA数据分析师相信大家在做一些算法的时候,经常会被庞大的计算量所带来的巨大的计算量所需要的时间所折磨数据的。接下来我们重点介绍四种方法,帮助你加快Python的计算时间,减少算法的等待时间。下面给大家介绍一下PyTorch的内容。1.简介在PyTorch模块中,我将展示如何使用torch和check,初始化GPU设备pycuda,以及如何使算法更快。PyTorch是一个基于Torch的机器学习库。它得到了Facebook人工智能研究小组的支持。由于其简单性、动态图形以及本质上是Python的事实,它在开发后变得非常流行。在速度上还是相差不远,在很多情况下可以说表现的非常好。pycuda允许您从python访问Nvidia的CUDA并行计算API。2、如何查看cuda是否可用?要检查是否有cuda可用的设备Torch,您只需运行以下代码:importtorchtorch.cuda.is_available()True3.如何获取有关您的cuda设备的更多信息?要获取有关设备的基本信息,您可以使用torch.cuda。但是,要获取有关设备的更多信息,您可以使用pycuda,这是一个围绕CUDA库开发的python包装器。您可以使用:importtorchimportpycuda.driverascudacuda.init()获取默认设备的IDtorch.cuda.current_device()0cuda.Device(0).name()#'0'是您的GPU的IDTeslaK80或者你可以这样使用它:torch.cuda.get_device_name(0)#Getnamedevicewithid'0'#'TeslaK80'我写了一个简单的类来获取有关cuda兼容GPU的信息:一个简单的类要知道你的cuda设备importpycuda.driverascudaimportpycuda.autoinit#mustuseitsfunctioncuda.init()#needtouseitsfunctionclassaboutCudaDevices():def__init__(self):passdefnum_devices(self):"""returnconnection设备数量。"""returncuda.Device.count()defdevices(self):"""获取所有连接设备的信息。"""num=cuda.Device.count()print("%ddevice(s)found:"%num)foriinrange(num):print(cuda.Device(i).name(),"(Id:%d)"%i)defmem_info(self):"""获得了所有设备的可用内存和总内存。"""available,total=cuda.mem_get_info()print("Available:%.2fGBnTotal:%.2fGB"%(available/1e9,total/1e9))defattributes(self,device_id=0):"""GetDeviceIdAttributes=device_id"""returncuda.Device(device_id).get_attributes()def__repr__(self):"""类代表连接到它们的设备数量。"""num=cuda.Device.count()string=""string+=("%ddevice(s)found:n"%num)foriinrange(num):string+=("%d)%s(Id:%d)n"%((i+1),cuda.Device(i).name(),i))string+=("Memory:%.2fGBn"%(cuda.Device(i).total_memory()/1e9))returnstringyoucanprintoutbytypingitsname(__repr__):aboutCudaDevices()1设备(s):1)TeslaK80(Id:0)Memory:12.00GB要获取当前内存使用情况,可以使用pyTorch函数:importtorchreturnsthecurrentGPUmemoryusageforagivendevice(inbytes)当前GPUtorch.cuda.memory_allocated()函数管理的内存以字节为单位用于给定设备的缓存分配器torch.cuda.memory_cached()运行应用程序后,可以使用一个简单的命令来清除缓存:释放所有未占用的缓存内存当前由缓存分配器持有,以便它可以被其他GPU应用程序使用,并且可以在NVIDIA-SMItorch.cuda.empty_cache()中查看但是,使用此命令不会释放张量占用的GPU内存,因此它可以't增加PyTorch可用的GPU内存量这些备忘录ry方法仅适用于GPU。所以这才是真正需要它的地方。4.如何存储张量并在GPU上运行它们在.cuda函数上运行模型。如果你想在CPU上存储一些东西,你可以简单地写代码:a=torch.DoubleTensor([1.,2.])向量存储在CPU上,你对它执行的任何操作都是在CPU上执行的.要将其传输到GPU,只需执行以下操作。cuda:a=torch.FloatTensor([1.,2.]).cuda()或者,a=torch.cuda.FloatTensor([1.,2.])这将为它选择默认设备,可以通过以下方式查看:torch.cuda.current_device()#0或者,您也可以执行以下操作:a.get_device()#0您也可以发送模型到GPU设备。例如,考虑一个简单的模块nn.Sequential:sq=nn.Sequential(nn.Linear(20,20),nn.ReLU(),nn.Linear(20,4),nn.Softmax())发送到GPU设备,只需执行:model=sq.cuda()你可以检查它是否在GPU设备上,为此你必须检查它的参数是否在GPU设备上,例如:可以在这里讨论:http://discuss.pytorch.org/t/how-to-check-if-model-is-on-cudanext(model.parameters()).is_cudaTrue5.多GPU时如何选择和使用GPU?您可以为当前应用程序/存储选择一个GPU,它可以与您为上一个应用程序/存储选择的不同。在第(2)部分已经看到,我们可以使用pycuda获取所有兼容cuda的设备及其Id,这里不再赘述。考虑到您有3个cuda兼容设备,您可以像这样初始化张量并将其分配给特定设备。cuda0=torch.device('cuda:0')cuda1=torch.device('cuda:1')cuda2=torch.device('cuda:2')如果你只使用'cuda',张量/模型将是发送到默认(当前)设备。(默认值=0)x=torch.Tensor([1.,2.],device=cuda1)或x=torch.Tensor([1.,2.]).to(cuda1)或x=torch.Tensor([1.,2.]).cuda(cuda1)notes:如果你想改变默认设备,请使用:torch.cuda.set_device(2)#如果你只想使用设备Id是'2'32个GPU,那么你必须设置环境变量CUDA_VISIBLE_DEVICES等于“0,2”,如果你只想使用第一和第三个GPU,现在如果你想检查有多少个GPU,它会显示Two(0,1)importosos.environ["CUDA_VISIBLE_DEVICES"]="0,2"当你对这些Tensor进行任何操作时,无论你选择什么设备,都可以进行操作,结果会保存在一台设备上的相同张量。x=torch.Tensor([1.,2.]).to(cuda2)y=torch.Tensor([3.,4.]).to(cuda2)这个Tensor(张量)只会保存在'cuda2'其中z=x+y如果您有多个GPU,您可以在它们之间分配应用程序的工作,但它们之间的通信会产生开销。不过,如果不需要传递太多信息,可以试试。其实还有一个问题。默认情况下,PyTorch中的所有GPU操作都是异步的。虽然在CPU和GPU之间或两个GPU之间复制数据时确实会发生必要的同步,但如果您借助命令torch.cuda.Stream()创建自己的数据流,那么您将必须处理指令同步举个PyTorch文档中的例子,这是不正确的:cuda=torch.device('cuda')s=torch.cuda.Stream()#Createanewdatastream。A=torch.empty((100,100),device=cuda).normal_(0.0,1.0)withtorch.cuda.stream(s):因为sum()可能在normal_()结束之前开始执行!B=torch.sum(A)如果您想充分利用多个GPU,那么您可以:将所有GPU用于不同的任务/应用程序将每个GPU用于集成或堆栈中的一个模型,每个GPU都有一个副本数据(如果可能),因为大部分处理是在拟合模型期间完成的,所以在每个GPU中使用带有切片输入的每个GPU和模型副本。每个GPU单独计算结果并将其结果发送到目标GPU以进行进一步计算等。6.数据并行性在数据并行性中,我们将数据(从数据生成器获得的一批数据)拆分为更小的mini-batches数据,然后将其发送到多个GPU进行并行计算。在PyTorch中,数据并行性是使用torch.nn.DataParallel实现的,我们将通过一个简单的示例来了解它的实际应用。为此,我们将不得不使用nn.parallel的一些功能:复制:模块在多个设备上复制。分散:输入在这些设备之间分配第一维。收集:输入收集并连接这些设备的第一维。parallel_apply:将我们从Scatter中得到的一组分布式输入输入到对应的分布式Module中,我们通过拷贝得到。将模块复制到设备ID中的设备replicas=nn.parallel.replicate(module,device_ids)将输入分发到设备ID中的设备inputs=nn.parallel.scatter(input,device_ids)将模型应用于相应的输入outputs=nn.parallel.parallel_apply(replicas,inputs)从所有设备收集结果到output_deviceresult=nn.parallel.gather(outputs,output_device)或者,简单地说:model=nn.DataParallel(model,device_ids=device_ids)result=model(input)7.数据并行比较TrainingSetData+Valw/DataLoader+DataAugmentationofRealDatainSSDTrainingSetW/ComprehensiveDatainMemory现在,你可以清楚地看到,即使必须在Parallelprocessing开始和结束时也绝对有帮助与主人沟通。并且仅在多GPU情况下,PyTorch在所有结果中都比Chainer更快地交付结果。Pytorch只需调用一次DataParallel即可轻松实现。8.torch.multiprocessingtorch.multiprocessing是Pythonmultiprocessing模块的包装器,其API与原始模块100%兼容。因此,您可以在此处使用Python的多处理模块中的Queue'、Pipe'、Array'等。此外,为了使其更快,他们添加了一个方法share_memory_(),它允许数据进入任何进程都可以直接使用它的状态,因此将该数据作为参数传递给不同的进程不会复制那个数据。您可以共享Tensors、模型参数,并根据需要在CPU或GPU上共享。来自Pytorch的警告:(关于在GPU上共享)CUDAAPI要求导出到其他进程的分配只要被其他进程使用就保持有效。您应该小心并确保您共享的CUDA张量在必要时不会超出范围。这对于共享模型参数应该不是问题,但在传递其他类型的数据时应该小心。请注意,此限制不适用于共享CPU内存。您可以在此处的“池和进程”部分中使用上面的方法,为了更快,您可以使用share_memory_()方法在所有进程之间共享一个Tensor(例如)而不被复制。importtorch.multiprocessingasmpdeftrain(model):fordata,labelsindata_loader:optimizer.zero_grad()loss_fn(model(data),labels).backward()optimizer.step()#这一步将更新共享参数模型=nn.Sequential(nn.Linear(n_in,n_h1),nn.ReLU(),nn.Linear(n_h1,n_out))model.share_memory()#需要'fork'方法来处理进程=[]foriinrange(4):#号的进程p=mp.Process(target=train,args=(model,))p.start()processes.append(p)forpinprocesses:p.join()Wewill下一期继续看Python中另一种加速计算的方法——Numba。疫情当下,往日匆忙的脚步终于慢下来,是时候好好想想自己的职业规划和人生规划了。未雨绸缪,未雨绸缪,为未来积蓄能量——蓄势待发!(1)更多优质内容和精彩资讯,访问:https://www.cda.cn/?seo(2)搜索CDA小程序,随时随地浏览最新资讯和优质课程手机: