如何在 PyTorch 中使用多处理? [英] How to use multiprocessing in PyTorch?

查看:29
本文介绍了如何在 PyTorch 中使用多处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用具有复杂损失函数的 PyTorch.为了加速代码,希望可以使用PyTorch多处理包.

I'm trying to use PyTorch with complex loss function. In order to accelerate the code, I hope that I can use the PyTorch multiprocessing package.

第一次试验,我将 10x1 的特征放入神经网络并得到 10x4 的输出.

The first trial, I put 10x1 features into the NN and get 10x4 output.

之后,我想将 10x4 参数传递给函数来做一些计算.(以后的计算会很复杂.)

After that, I want to pass 10x4 parameters into a function to do some calculation. (The calculation will be complex in the future.)

计算后,该函数总共会返回一个 10x1 的数组.该数组将被设置为 NN_energy 并计算损失函数.

After calculating, the function will return a 10x1 array in total. This array will be set as NN_energy and calculate loss function.

另外,我也想知道有没有另一种方法可以创建一个backwardable数组来存储NN_energy数组,而不是使用

Besides, I also want to know if there is another method to create a backward-able array to store the NN_energy array, instead of using

NN_energy = net(Data_in)[0:10,0]

非常感谢.

完整代码:

import torch
import numpy as np
from torch.autograd import Variable 
from torch import multiprocessing

def func(msg,BOP):
    ans = (BOP[msg][0]+BOP[msg][1]/BOP[msg][2])*BOP[msg][3]
    return ans

class Net(torch.nn.Module):
    def __init__(self, n_feature, n_hidden_1, n_hidden_2, n_output):
        super(Net, self).__init__()
        self.hidden_1 = torch.nn.Linear(n_feature , n_hidden_1)  # hidden layer
        self.hidden_2 = torch.nn.Linear(n_hidden_1, n_hidden_2)  # hidden layer
        self.predict  = torch.nn.Linear(n_hidden_2, n_output  )  # output layer

    def forward(self, x):
        x = torch.tanh(self.hidden_1(x))      # activation function for hidden layer
        x = torch.tanh(self.hidden_2(x))      # activation function for hidden layer
        x = self.predict(x)                   # linear output
        return x

if __name__ == '__main__': # apply_async
    Data_in      = Variable( torch.from_numpy( np.asarray(list(range( 0,10))).reshape(10,1) ).float() )
    Ground_truth = Variable( torch.from_numpy( np.asarray(list(range(20,30))).reshape(10,1) ).float() )

    net = Net( n_feature=1 , n_hidden_1=15 , n_hidden_2=15 , n_output=4 )     # define the network
    optimizer = torch.optim.Rprop( net.parameters() )
    loss_func = torch.nn.MSELoss()  # this is for regression mean squared loss 
    NN_output = net(Data_in)   
    args = range(0,10)
    pool = multiprocessing.Pool()
    return_data = pool.map( func, zip(args, NN_output) )
    pool.close()
    pool.join()

    NN_energy = net(Data_in)[0:10,0]  
    for i in range(0,10):
        NN_energy[i] = return_data[i]

    loss = torch.sqrt( loss_func( NN_energy , Ground_truth ) )     # must be (1. nn output, 2. target) 
    print(loss)

错误信息:

文件"C:ProgramDataAnaconda3libsite-packages orchmultiprocessing eductions.py",第 126 行,在 reduce_tensor 中raise RuntimeError("怯懦地拒绝序列化需要 grad 的非叶张量,"

File "C:ProgramDataAnaconda3libsite-packages orchmultiprocessing eductions.py", line 126, in reduce_tensor raise RuntimeError("Cowardly refusing to serialize non-leaf tensor which requires_grad, "

RuntimeError: Cowardly 拒绝序列化非叶张量requires_grad,因为 autograd 不支持交叉进程边界.如果你只是想传输数据,调用 detach() on序列化前的张量(例如,将其放入队列).

RuntimeError: Cowardly refusing to serialize non-leaf tensor which requires_grad, since autograd does not support crossing process boundaries. If you just want to transfer the data, call detach() on the tensor before serializing (e.g., putting it on the queue).

推荐答案

首先,Torch Variable API 已经弃用很久了,请不要使用它.

First of all, Torch Variable API is deprecated since a very long time, just don't use it.

接下来,torch.from_numpy( np.asarray(list(range( 0,10))).reshape(10,1) ).float() 在很多层面上都是错误的:list 的 >np.asarray 没有用,因为无论如何都会执行一个副本,并且 np.arraylist 作为输入设计.然后,np.arange 可用于将范围作为 numpy 数组返回,它也可用于 Torch.接下来,为 reshape 指定两个维度既无用又容易出错,你可以简单地做 reshape((-1, 1)),或者更好的 unsqueeze(-1).这是简化的表达式 torch.arange(10, dtype=torch.float32, requires_grad=True).unsqueeze(-1).

Next, torch.from_numpy( np.asarray(list(range( 0,10))).reshape(10,1) ).float() is wrong at many levels: np.asarray of list is useless since a copy will be performed anyway, and np.array takes list as input by design. Then, np.arange is available to return a range as numpy array, and it is also available on Torch. Next, specifying both dimension for reshape is useless and error prone, you could simply do reshape((-1, 1)), or even better unsqueeze(-1). Here is the simplified expression torch.arange(10, dtype=torch.float32, requires_grad=True).unsqueeze(-1).

如果可以使用批处理,则使用多处理池是一种不好的做法.它将更加高效和可读.事实上,并行执行 N 个小代数运算总是更慢,而且是更大的单个代数运算,在 GPU 上甚至更多.更重要的是,多处理不支持计算梯度,因此会出现错误.然而,这部分是正确的,因为它自 1.6.0 以来就支持 cpu 上的张量.祝您好运,查看官方发布更新日志.

Using multiprocessing pool is a bad practice if using batch processing is possible. It will be both way more efficient and readable. Indeed, performing N small algebraic operations in parallel is always slower and a larger single algebraic operation, and even more on GPU. More importantly, computing the gradient is not supported by multiprocessing, hence the error that you get. Yet, this is partially true, because it is supports for tensors on cpu since 1.6.0. Have a lok, to the official release changelog.

您能否发布一个更具代表性的示例,说明 func 方法可能是什么,以确保您真的需要它?

Could you post a more representative example of what func method could be to make sure you really need it ?

注意:您正在寻找的分布式 autograd 现在在 Pytorch 中可用,作为自 1.6.0 以来在 beta 中可用的实验性功能.查看官方文档.

NB: Distributed autograd as you are looking is now available in Pytorch as an experimental feature available in beta since 1.6.0. Have a look to the official documentation.

这篇关于如何在 PyTorch 中使用多处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆