У меня есть модель нейросети Graph, которую я написал с использованием Pytorch. На моем процессоре у меня не получается фантастическая производительность c, поэтому я попытался перенести ее на графический процессор V100, к которому у меня есть доступ. В этом процессе я получил огромное снижение производительности (примерно в 10 раз медленнее).
У меня есть две идеи о том, где может быть проблема, но я хотел бы получить некоторый вклад, чтобы попытаться получить оптимальную производительность от моей модели. Первая проблема может исходить от моего пользовательского графового сверточного слоя:
class GraphConvLayer(torch.nn.Module):
"""
Based, basically, on https://arxiv.org/abs/1609.02907
Have some modifications:
https://towardsdatascience.com/how-to-do-deep-learning-on-graphs-with-graph-convolutional-networks-7d2250723780
This helped:
https://pytorch.org/docs/master/notes/extending.html
"""
def __init__(self, input_features, output_features, device, bias=True):
super(GraphConvLayer, self).__init__()
self.input_features = input_features
self.output_features = output_features
self.device = device
self.weight = nn.Parameter(torch.FloatTensor(self.input_features, self.output_features))
if bias:
self.bias = nn.Parameter(torch.FloatTensor(self.output_features))
else:
self.register_parameter('bias', None)
# Not a very smart way to initialize weights
self.weight.data.uniform_(-0.1, 0.1)
if bias is not None:
self.bias.data.uniform_(-0.1, 0.1)
def forward(self,input, adj):
# Here, we put in the forward pass:
# Our forward pass needs to be:
# D^-1 * (A + 1) * X * weights
input, adj = input.float(), adj.float()
Identity = torch.eye( len(adj[0]), device = self.device)
A_hat = adj + Identity
D = torch.sum(A_hat, dim=0)
len_D = len(D)
zero = torch.zeros(len_D,len_D, device = self.device)
mask = torch.diag(torch.ones_like(D, device = self.device))
D = mask*torch.diag(D) + (1. - mask)*zero
D_inv = torch.inverse(D)
out = torch.mm(input, self.weight)
out = torch.spmm(A_hat,out)
out = torch.spmm(D_inv, out)
if self.bias is not None:
return out + self.bias
else:
return out
return out
def extra_repr(self):
# (Optional)Set the extra information about this module. You can test
# it by printing an object of this class.
return 'node_features={}, length of weights={}, bias={}'.format(
self.node_features, self.input_features, self.bias is not None
)
В частности, на прямом проходе я делаю выбор трансформаций, которые описаны в ссылке по направлению к данным в классе. Есть ли здесь что-то, что вызывает такое большое замедление? Мне кажется, что все тензоры инициализируются на GPU.
Во-вторых, так как все мои графики имеют разные размеры, я вынужден использовать пакет размером 1. В моем обучении l oop У меня есть это:
for batch in tqdm(train_loader):
opt.zero_grad()
adjacency, features, _, nodes = batch
adjacency = adjacency.to(device)
features = features.to(device)
nodes = nodes.to(device)
output = model(features[0], adjacency[0])
loss = F.nll_loss(output, nodes[0])
loss.backward()
opt.step()
Это значит ( насколько я понимаю), что каждый отдельный фрагмент данных перемещается в GPU индивидуально, каждый l oop. Это кажется очевидной причиной неэффективности. Есть ли способ переместить все данные в память GPU одновременно, вне обучающей l oop, позволяя мне удалить adjacency = adjacency.to(device)
строк?
Любая помощь будет очень признательна.