Передача проходит в 10000 раз медленнее после некоторой итерации - PullRequest
2 голосов
/ 06 февраля 2020

Я реализовал простую сеть Deconv, как и официальный учебник Pytorch по DCGAN. Я неоднократно передаю ему zeros вектор. Время спустя значительно замедляется. Мне интересно, в чем причина и как я могу ее устранить.

Код:

import torch
import torch.nn as nn
import time

# JUST TO MEASURE TIME
class Timer:
    def __init__(self, msg):
        self.msg = msg

    def __enter__(self):
        self.start = time.process_time()
        return self

    def __exit__(self, *args):
        self.end = time.process_time()
        self.interval = self.end - self.start

        print('{}: {:.5f}'.format(self.msg, self.interval))

device = torch.device("cuda")

ngf, nc, nz, batchSize = 64, 1, 6, 1<<16
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()
        self.main = nn.Sequential(
            # input is Z, going into a convolution
            nn.ConvTranspose2d( nz, ngf * 4, 4, 1, 0, bias=False),
            nn.BatchNorm2d(ngf * 4),
            nn.ReLU(True),
            # state size. (ngf*4) x 4 x 4
            nn.ConvTranspose2d(ngf * 4, ngf * 2, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf * 2),
            nn.ReLU(True),
            # state size. (ngf*2) x 8 x 8
            nn.ConvTranspose2d( ngf * 2, ngf, 4, 2, 1, bias=False),
            nn.BatchNorm2d(ngf),
            nn.ReLU(True),
            # state size. (ngf) x 16 x 16
            nn.ConvTranspose2d( ngf, nc, 4, 2, 1, bias=False),
            nn.Tanh()
            # state size. (nc) x 32 x 32
        )

    def forward(self, input):
        return self.main(input)

# Create the generator
netG = Generator().to(device)

def weights_init(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        nn.init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        nn.init.normal_(m.weight.data, 1.0, 0.02)
        nn.init.constant_(m.bias.data, 0)

netG.apply(weights_init)

# torch.backends.cudnn.benchmark=True

while True:
    with Timer('Time elapsed'):
        with torch.no_grad():
            netG(torch.zeros([batchSize, nz, 1, 1], device=device))

Результат:

Время истекло: 0.02309 Время истекло: 0.00072 Истекшее время: 0,00208 истекшее время: 0,00128 истекшее время: 0,00119 истекшее время: 0,00153 истекшее время: 0,00176 истекшее время: 0,00170 истекшее время: 0,00185 истекшее время: 0,00188 истекшее время: 0,00191 истекшее время: 0,00190 истекшее время: 0,0017 истекшее время: затраченное время 0,001 : 0,00167 Время, прошедшее: 0,00120 Время, прошедшее: 0,00168 Время, прошедшее: 0,00169 Время, прошедшее: 0,00166 Время, прошедшее: 0,00167 Время, прошедшее: 0,00171 Время, прошедшее: 0,00168 Время, прошедшее: 0,00168 Время, прошедшее: 0,00168 Время, прошедшее: 0,00173 Время: 0,00171 Время: 0,00171 Время: 0,00171 Время: 0,00171 Время: 0,00171 Истекшее время: 0,00176 Истекшее время: 0,00173 Истекшее время: 0,00171 Истекшее время: 0,00168 Истекшее время: 0,00173 Истекшее время: 0,00168 Истекшее время: 0,00178 Истекшее время: 0,00169 Истекшее время: 0,00171 Истекшее время: 0,00168 Истекшее время: 0,00168 Истекшее время: 0,00168 Истекшее время: : 0,00 173 Время истекло: 0,00154 Время истекло: 0,00170 Время истекло: 0,00167 Время истекло: 0,00224 Время истекло: 0,00117 Время истекло: 0,00175 Время истекло: 0,00168 Время истекло: 0,00173 Время истекло: 0,00169 Время истекло: 12,61379 Время истекло: 12,61379 Время истекло: 12,61379 Время: истекло Истекшее время: 12.71846 истекшее время: 12.71909 истекшее время: 12.71898 истекшее время: 12.72288 истекшее время: 12.72157 истекшее время: 12.72226 истекшее время: 12.72456 истекшее время: 12.72350 истекшее время: 12.7242 истекшее время: 12: истекшее время: 12: истекло 12.72538 Время: 12.72533 Время: 12.72510 Время: 12.72507 Время: 12.72806 Время: 12.72865 Время: 12.72764 Время: 12.72431

  • RT
  • Python версия: 3.7

1 Ответ

0 голосов
/ 07 февраля 2020

Я опробовал тот же код на своем Titan RTX и получил точно такое же поведение.

Все вызовы GPU асинхронны (как указано в комментариях jodag) и синхронизируются только при необходимости, если есть являются зависимостями. Поэтому, чтобы проверить это, я немного изменил код, чтобы фактически использовать выходные данные сети и создать зависимость, такую ​​как зависимость. Таким образом, теперь необходим вывод перед началом следующей итерации.

while True:
    with Timer('Time elapsed'):
        with torch.no_grad():
            output = netG(torch.zeros([batchSize, nz, 1, 1], device=device))
            print(output.mean())

Теперь это всегда занимает 12,8 секунды. Так что Джодаг совершенно прав. Это как-то связано с асинхронными вызовами графического процессора и тем, как pytorch обрабатывает все внутри.

...