#python #multithreading #pytorch #python-multiprocessing #reinforcement-learning
#python #многопоточность #pytorch #python-многопроцессорная обработка #подкрепление-обучение
Вопрос:
Я реализую архитектуру ACER, которая выполняет асинхронное обновление параметров как A3C. Глядя на существующие реализации PyTorch, я часто вижу, что обновление параметров выполняется следующим образом
# Transfers gradients from thread-specific model to shared model
def _transfer_grads_to_shared_model(model, shared_model):
for param, shared_param in zip(model.parameters(), shared_model.parameters()):
if shared_param.grad is not None:
return
shared_param._grad = param.grad
Я понимаю, что если shared_param.grad не равен None, это означает, что другой поток добавил градиент в модель, поэтому мы возвращаемся, чтобы не перезаписывать его.
Мои вопросы таковы:
- Таким образом, мы «отбрасываем» некоторые вычисленные градиенты, я прав?
- Почему мы не используем механизм блокировки при обновлении общих параметров модели? Это позволило бы избежать одновременного обновления параметров двумя потоками. Поскольку потоки тратят большую часть своего времени на выполнение шагов в среде и обновление своих локальных моделей, добавление блокировки для общего обновления модели может оказать незначительное влияние на производительность. Прав ли я в этом? Если да, то почему это не делается на практике?
- Что произойдет, если поток вызывает
optimizer.step()
shared_model, в то время как другой поток копирует в него градиенты?
Другая реализация, которую я нашел, делает это так:
def copy_gradients_from(model, shared_model):
for shared_parameter, parameter in zip(shared_model.parameters(), model.parameters()):
shared_parameter._grad = parameter.grad
который не проверяет наличие существующих градиентов, а также вызывается без какого-либо Lock
механизма.