Асинхронный градиентный спуск поддерживается в выпуске TensorFlow с открытым исходным кодом, даже не изменяя график. Самый простой способ сделать это состоит в выполнении нескольких параллельных шагов параллельно:
loss = ...
# Any of the optimizer classes can be used here.
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
sess = tf.Session()
sess.run(tf.initialize_all_variables())
def train_function():
# TODO: Better termination condition, e.g. using a `max_steps` counter.
while True:
sess.run(train_op)
# Create multiple threads to run `train_function()` in parallel
train_threads = []
for _ in range(NUM_CONCURRENT_STEPS):
train_threads.append(threading.Thread(target=train_function))
# Start the threads, and block on their completion.
for t in train_threads:
t.start()
for t in train_threads:
t.join()
Этот пример устанавливает NUM_CONCURRENT_STEPS
звонков в sess.run(train_op)
. Поскольку между этими потоками нет координации, они работают асинхронно.
Это на самом деле более сложный для достижения синхронного параллельного обучения (в настоящее время), так как это требует дополнительного согласования для обеспечения того, чтобы все реплики прочитать ту же версию параметров, и что все их обновлений становятся видимыми одновременно , multi-GPU example for CIFAR-10 training выполняет синхронные обновления, создавая несколько копий «башни» на графике обучения с общими параметрами и явно усредняя градиенты через башни перед применением обновления.
N.B. Код в этом ответе помещает все вычисления на одно и то же устройство, которое не будет оптимальным, если на вашем компьютере установлено несколько графических процессоров. Если вы хотите использовать все свои графические процессоры, следуйте примеру multi-GPU CIFAR-10 model и создайте несколько «башен» с их операциями, прикрепленными к каждому графическому процессору. Код будет выглядеть примерно следующим образом:
train_ops = []
for i in range(NUM_GPUS):
with tf.device("/gpu:%d" % i):
# Define a tower on GPU `i`.
loss = ...
train_ops.append(tf.train.GradientDescentOptimizer(0.01).minimize(loss))
def train_function(train_op):
# TODO: Better termination condition, e.g. using a `max_steps` counter.
while True:
sess.run(train_op)
# Create multiple threads to run `train_function()` in parallel
train_threads = []
for train_op in train_ops:
train_threads.append(threading.Thread(target=train_function, args=(train_op,))
# Start the threads, and block on their completion.
for t in train_threads:
t.start()
for t in train_threads:
t.join()
Обратите внимание, что вы можете найти его удобно использовать "variable scope" для облегчения переменного обмена между башнями.
Мне просто жаль, что я не был достаточно умен, чтобы понять этот вопрос. Удачи. – GojiraDeMonstah