У меня есть большой код машинного обучения, который я пишу в течение нескольких месяцев, и я начал процесс распараллеливания данных для работы с несколькими графическими процессорами. Начнем с того, что код отлично работает при использовании одного графического процессора; проблема возникает при использовании нескольких графических процессоров.
Ошибка следующая: RuntimeError: Ожидалось, что все тензоры будут на одном устройстве, но обнаружено как минимум два устройства: cuda:1 и cuda: 0! (при проверке аргумента для индекса аргумента в методе Wrapper_CUDA__index_select)
Фрагменты соответствующего кода можно найти ниже: Модель файл
from tqdm.notebook import trange
from datetime import datetime
import glob
import sys
import os
def train(loader,model,parameters,PIN_MEMORY=False):
model.train()
total_loss = 0.0
model = nn.DataParallel(model, device_ids=[0, 1]).cuda()
#model = model.to(parameters['device'])
optimizer = torch.optim.AdamW(model.module.processor.parameters(), lr=parameters['LEARN_RATE'])
#model = model.to(parameters['device'])
loss_fn = torch.nn.MSELoss()
for i,data in enumerate(loader, 0):
optimizer.zero_grad(set_to_none=True)
#data = data.to(parameters['device'], non_blocking=PIN_MEMORY)
data = data.cuda()
#encoding = model.encoder(data)
#proc = model.processor(encoding.module)
#atom_contrib, bond_contrib, angle_contrib = model.decoder(proc.module)
atom_contrib, bond_contrib, angle_contrib = model(data)
all_sum = atom_contrib.sum() + bond_contrib.sum() + angle_contrib.sum()
loss = loss_fn(all_sum, data.y[0][0])
loss.backward()
optimizer.step()
total_loss += loss.item()
return total_loss / len(loader)
def run_training(data,parameters,model):
follow_batch = ['x_atm', 'x_bnd', 'x_ang'] if hasattr(data['training'][0], 'x_ang') else ['x_atm']
loader_train = DataLoader(data['training'], batch_size=parameters['BATCH_SIZE'], shuffle=True, follow_batch=follow_batch)
loader_valid = DataLoader(data['validation'], batch_size=parameters['BATCH_SIZE'], shuffle=False)
L_train, L_valid = [], []
min_loss_train = 1.0E30
min_loss_valid = 1.0E30
stats_file = open(os.path.join(parameters['model_dir'],'loss.data'),'w')
stats_file.write('Training_loss Validation loss\n')
stats_file.close()
for ep in range(parameters['num_epochs']):
stats_file = open(os.path.join(parameters['model_dir'], 'loss.data'), 'a')
print('Epoch ',ep,' of ',parameters['num_epochs'])
sys.stdout.flush()
loss_train = train(loader_train, model, parameters);
L_train.append(loss_train)
loss_valid = test_non_intepretable(loader_valid, model, parameters)
L_valid.append(loss_valid)
stats_file.write(str(loss_train) + ' ' + str(loss_valid) + '\n')
if loss_train < min_loss_train:
min_loss_train = loss_train
if loss_valid < min_loss_valid:
min_loss_valid = loss_valid
if parameters['remove_old_model']:
model_name = glob.glob(os.path.join(parameters['model_dir'], 'model_*'))
if len(model_name) > 0:
os.remove(model_name[0])
now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
print('Min train loss: ', min_loss_train, ' min valid loss: ', min_loss_valid, ' time: ', now)
torch.save(model.state_dict(), os.path.join(parameters['model_dir'], 'model_' + str(now)))
stats_file.close()
if loss_train < parameters['train_tolerance'] and loss_valid < parameters['train_tolerance']:
print('Validation and training losses satisy set tolerance...exiting training loop...')
break
Существует много других файлов, но я думаю, что они подходят для этой конкретной проблемы, но я буду рад включить их в код, если это необходимо. Мои данные хранятся в виде графика и группируются с помощью DataLoader и выглядят следующим образом (при пакетировании по два за раз):
В частности, data.h_atm = self.embed_atm(data.x_atm). Чтобы кратко объяснить, что я пытаюсь сделать, я загружаю в Dataloader набор графиков, которые группируются, а затем передаются в модель для обучения:
Насколько я понимаю, я отправил пакетные данные в графический процессор, а параметры моей модели находятся в графическом процессоре, и DataParallel должен позаботиться о разделении моих данных и автоматической отправке всех данных на каждый графический процессор.
Мой вопрос можно разбить на несколько частей: (1) Верно ли это понимание? (2) Действительно ли мой код выглядит так, как будто он делает это, и (3) имеет ли эта ошибка какое-либо отношение к этому, и если нет, то о чем эта ошибка пытается мне сказать? Я не ожидаю, что кто-нибудь исправит мой код за меня, но мне хотелось бы понять, почему возникает эта ошибка, потому что я думаю, что неправильно понимаю основную логику того, как DataParallel принимает мои данные и отправляет их в графический процессор. Я рад предоставить любую информацию, которая может вам понадобиться, чтобы лучше понять эту проблему.
Я попытался лучше понять разрывающуюся строку: data.h_atm = self.embed_atm(data.x_atm ) распечатав, где на самом деле находится data.x_atm внутри функции пересылки, что должно быть после того, как DataParallel разделил данные, и я получаю это для всех тензоров:
Я думаю, это говорит мне о том, что все мои данные находятся на графическом процессоре 0, несмотря на то, что модель находится как на графическом процессоре 0, так и на 1 (при работе на двух графических процессорах), что я и делаю. Я подтвердил это, используя nvidia-smi и наблюдая, как оба графических процессора потребляют примерно половину памяти. Я также пробовал различные комбинации вызова X.to_device('cuda') или X.cuda(), где X - данные моего графика, но, похоже, ничто не имеет никакого значения для тензорной распечатки. .
У меня есть большой код машинного обучения, который я пишу в течение нескольких месяцев, и я начал процесс распараллеливания данных для работы с несколькими графическими процессорами. Начнем с того, что код отлично работает при использовании одного графического процессора; проблема возникает при использовании нескольких графических процессоров. Ошибка следующая: RuntimeError: Ожидалось, что все тензоры будут на одном устройстве, но обнаружено как минимум два устройства: cuda:1 и cuda: 0! (при проверке аргумента для индекса аргумента в методе Wrapper_CUDA__index_select) Фрагменты соответствующего кода можно найти ниже: [b]Модель файл[/b] [code]import torch from torch import nn from functools import partial import copy
from ..mlp import MLP from ..basis import gaussian, bessel from ..conv import GatedGCN
class Encoder(nn.Module): """ALIGNN/ALIGNN-d Encoder. The encoder must take a PyG graph object `data` and output the same `data` with additional fields `h_atm`, `h_bnd`, and `h_ang` that correspond to the atom, bond, and angle embedding.
The input `data` must have three fields `x_atm`, `x_bnd`, and `x_ang` that describe the atom type (in onehot vectors), the bond lengths, and bond/dihedral angles (in radians). """
self.atm_bnd_convs = nn.ModuleList([copy.deepcopy(GatedGCN(dim, dim)) for _ in range(num_convs)]) self.bnd_ang_convs = nn.ModuleList([copy.deepcopy(GatedGCN(dim, dim)) for _ in range(num_convs)])
stats_file = open(os.path.join(parameters['model_dir'],'loss.data'),'w') stats_file.write('Training_loss Validation loss\n') stats_file.close() for ep in range(parameters['num_epochs']): stats_file = open(os.path.join(parameters['model_dir'], 'loss.data'), 'a') print('Epoch ',ep,' of ',parameters['num_epochs']) sys.stdout.flush() loss_train = train(loader_train, model, parameters); L_train.append(loss_train) loss_valid = test_non_intepretable(loader_valid, model, parameters) L_valid.append(loss_valid) stats_file.write(str(loss_train) + ' ' + str(loss_valid) + '\n') if loss_train < min_loss_train: min_loss_train = loss_train if loss_valid < min_loss_valid: min_loss_valid = loss_valid if parameters['remove_old_model']: model_name = glob.glob(os.path.join(parameters['model_dir'], 'model_*')) if len(model_name) > 0: os.remove(model_name[0]) now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') print('Min train loss: ', min_loss_train, ' min valid loss: ', min_loss_valid, ' time: ', now) torch.save(model.state_dict(), os.path.join(parameters['model_dir'], 'model_' + str(now))) stats_file.close() if loss_train < parameters['train_tolerance'] and loss_valid < parameters['train_tolerance']: print('Validation and training losses satisy set tolerance...exiting training loop...') break [/code] Существует много других файлов, но я думаю, что они подходят для этой конкретной проблемы, но я буду рад включить их в код, если это необходимо. Мои данные хранятся в виде графика и группируются с помощью DataLoader и выглядят следующим образом (при пакетировании по два за раз): [code]Graph_DataBatch(atoms=[2], edge_index_G=[2, 89966], edge_index_A=[2, 1479258], x_atm=[5184, 5], x_atm_batch=[5184], x_atm_ptr=[3], x_bnd=[89966], x_bnd_batch=[89966], x_bnd_ptr=[3], x_ang=[1479258], x_ang_batch=[1479258], x_ang_ptr=[3], mask_dih_ang=[1479258], atm_amounts=[6], bnd_amounts=[6], ang_amounts=[6], y=[179932, 1])[/code] Проблемная строка находится в кодировщике во время его функции пересылки: [code]def forward(self, data): # Embed atoms data.h_atm = self.embed_atm(data.x_atm)
return data [/code] В частности, data.h_atm = self.embed_atm(data.x_atm). Чтобы кратко объяснить, что я пытаюсь сделать, я загружаю в Dataloader набор графиков, которые группируются, а затем передаются в модель для обучения: [code]def train(loader,model,parameters,PIN_MEMORY=False): model.train() total_loss = 0.0 model = nn.DataParallel(model, device_ids=[0, 1]).cuda() #model = model.to(parameters['device']) optimizer = torch.optim.AdamW(model.module.processor.parameters(), lr=parameters['LEARN_RATE'])
#model = model.to(parameters['device']) loss_fn = torch.nn.MSELoss() for i,data in enumerate(loader, 0): optimizer.zero_grad(set_to_none=True) #data = data.to(parameters['device'], non_blocking=PIN_MEMORY) data = data.cuda() #encoding = model.encoder(data) #proc = model.processor(encoding.module) #atom_contrib, bond_contrib, angle_contrib = model.decoder(proc.module) atom_contrib, bond_contrib, angle_contrib = model(data) [/code] Насколько я понимаю, я отправил пакетные данные в графический процессор, а параметры моей модели находятся в графическом процессоре, и DataParallel должен позаботиться о разделении моих данных и автоматической отправке всех данных на каждый графический процессор. Мой вопрос можно разбить на несколько частей: (1) Верно ли это понимание? (2) Действительно ли мой код выглядит так, как будто он делает это, и (3) имеет ли эта ошибка какое-либо отношение к этому, и если нет, то о чем эта ошибка пытается мне сказать? Я не ожидаю, что кто-нибудь исправит мой код за меня, но мне хотелось бы понять, почему возникает эта ошибка, потому что я думаю, что неправильно понимаю основную логику того, как DataParallel принимает мои данные и отправляет их в графический процессор. Я рад предоставить любую информацию, которая может вам понадобиться, чтобы лучше понять эту проблему. Я попытался лучше понять разрывающуюся строку: data.h_atm = self.embed_atm(data.x_atm ) распечатав, где на самом деле находится data.x_atm внутри функции пересылки, что должно быть после того, как DataParallel разделил данные, и я получаю это для всех тензоров: [code]tensor([[1., 0., 0., 0., 0.],[/code] [code][1., 0., 0., 0., 0.],[/code] [code][1., 0., 0., 0., 0.],[/code] [code]...,[/code] [code][0., 0., 1., 0., 0.],[/code] [code][0., 0., 1., 0., 0.],[/code] [code][0., 0., 1., 0., 0.]], device='cuda:0')[/code] Я думаю, это говорит мне о том, что все мои данные находятся на графическом процессоре 0, несмотря на то, что модель находится как на графическом процессоре 0, так и на 1 (при работе на двух графических процессорах), что я и делаю. Я подтвердил это, используя nvidia-smi и наблюдая, как оба графических процессора потребляют примерно половину памяти. Я также пробовал различные комбинации вызова X.to_device('cuda') или X.cuda(), где X - данные моего графика, но, похоже, ничто не имеет никакого значения для тензорной распечатки. .
Я написал программу CUDA, которая выполняет обработку последовательности символов. Программа обрабатывает все последовательности символов параллельно, при условии, что все последовательности имеют одинаковую длину. Я...
Я работаю над задачей по тонкой настройке ламы. Когда я тренируюсь на одном графическом процессоре, программа работает нормально.
import os
os.environ = 0
os.environ = false
device = torch.device( cuda:0 if torch.cuda.is_available() else cpu )...
Я собрал фиктивную модель молнии Pytorch специально для сравнения времени, необходимого для завершения обучения с несколькими графическими процессорами (3 графических процессора, использующих DDP, называемых 3G) и обучения с одним графическим...
У меня возникли проблемы с его компиляцией с помощью AMD Radeon R7 M360. Я скомпилировал его с многоядерным процессором, как показано ниже, но может кто-нибудь сказать мне, как скомпилировать его с графическим процессором? Я пробовал...
Я пытаюсь написать приложение opencl C++ на старом ноутбуке с Ubuntu. Он имеет два графических процессора, которые отображаются, когда я запускаю lspci | grep VGA:
00:02.0 VGA compatible controller: Intel Corporation 3rd Gen Core processor Graphics...