使用GPU,哪些内容需要to(device)

目录

模型.to(device)

数据张量.to(device)

1、模型to(device)

2、但是数据那么多,哪些数据需要to(device)呢

网络接收数据的to(device) 

 其他数据to(device)

3、损失函数是否要to(device)呢

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

模型.to(device)

数据张量.to(device)

模型要么在CPU上跑要么在GPU上跑

如果没有统一,就会出现下面的报错

RuntimeError: Expected all tensors to be on the same device, but found at least two devices, cpu and cuda:0! (when checking argument for argument batch1 in method wrapper_CUDA_baddbmm)

1、模型to(device)

我们通常遇到的形式如下


class Model(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 32, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 5, 1, 2),
            nn.MaxPool2d(2),
            nn.Flatten(),
            nn.Linear(64*4*4, 64),
            nn.Linear(64, 10)
        )
 
    def forward(self, x):
        x = self.model(x)
        return x
 
 
model = Model()


 那么只需要将模型的实例化对象to(device)就可以了

model=model.to(device)

model.to(device)的本质是将model网络里面的参数放到device中

2、但是数据那么多,哪些数据需要to(device)呢

我们将数据和模型to(device)的原因在于要将数据和模型都放在GPU上运算,换句话说,这里的数据是模型中运行的数据。

我们要确保的是模型中用到数据要和模型在一个device(GPU或者CPU)上面,其他的数据不需要管。

网络接收数据的to(device) 

我们一般见到的情况如下:(这里的模型是net)

        input_q = torch.from_numpy(input_q).long().to(device)
        input_qa = torch.from_numpy(input_qa).long().to(device)
        target = torch.from_numpy(target_1).float().to(device)
        if pid_flag:
            pid_one_seq = pid_data[:, idx * batch_size: (idx + 1) * batch_size]
            input_pid = np.transpose(pid_one_seq[:, :])
            input_pid = torch.from_numpy(input_pid).long().to(device)

            loss, pred, true_ct = net(input_q, input_qa, target, input_pid)
        else:
            loss, pred, true_ct = net(input_q, input_qa, target)

在将数据放在模型里之前就已经将其放到GPU上了

那可不可以在模型里面接受之后再to(device)

可以的 

    def forward(self, q_data, qa_data, target, pid_data=None):
        q_data= q_data.to(device)
        qa_data=qa_data.to(device)
        target=target.to(device)
        pid_data=pid_data.to(device)

 其他数据to(device)

一般情况对网络接收数据to(device)就可以了,网络处理过程中的数据一般都是从网络接收数据演变出来的,不需要再单独to(device)

凡事都有例外

x1 = torch.arange(seqlen).expand(seqlen, -1).to(device)

 比如说这条代码

他不是从网络接受数据中演变出来的,并且它还要参与网络后面的计算,那么他就需要单独to(device) 

3、损失函数是否要to(device)呢

我在查找哪些内容需要放到GPU上的时候,查到两种答案:

1、模型、数据张量

2、模型、数据张量和损失函数

所以现在的问题就变成了损失函数是否需要to(device)

看到了这样一个答案,觉得非常有道理

通常不需要

简单地说,损失函数接收一个或多个输入tensor,如果输入tensor本身就是在gpu上,则输出tensor自然就在gpu上。

构建网络时,需要主动to或cuda的包括模型输入tensor,以及对应的Module(网络模型)对象。模型输入tensor是数据不用多说,Module对象使用.cuda是为了将模型内部的数据(即每个子叶Module的Parameter或Buffer成员变量)递归地传入gpu。

再进一步,如CrossEntropyCriterion等pytorch自带的loss类(或称loss layer)虽然也是Module的子类,但是这些类的成员变量不含Parameter对象或Buffer对象,所以无需to或cuda处理。Module对象是否持有数据,在设计上也是区分network layer和loss layer的关键。

链接:https://www.zhihu.com/question/314169571/answer/618862874


 

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁灵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值