1

我想在 CIFAR10 数据集上训练一个 CNN,并在单个节点上的多个 GPU 上使用 chainer。我尝试调整此示例以使用 ParallelUpdater,其方式与mnist 数据并行示例相同,但训练性能非常差 - 比在一个 GPU 上训练慢,即使所有 8 个 GPU 都在使用。我更改为 MultiprocessUpdater,性能(迭代次数/秒)要好得多。

坏的:

num_gpus = 8
chainer.cuda.get_device_from_id(0).use()
train_iter = chainer.iterators.SerialIterator(train, batch_size)

if num_gpus > 0:
    updater = training.updater.ParallelUpdater(
        train_iter,
        optimizer,
        devices={('main' if device == 0 else str(device)): device for device in range(num_gpus)},
    )
else:
    updater = training.updater.StandardUpdater(train_iter, optimizer, device=0)

好的:

num_gpus = 8

devices = range(num_gpus)

train_iters = [chainer.iterators.MultiprocessIterator(i, batch_size, n_processes=num_gpus) \
               for i in chainer.datasets.split_dataset_n_random(train, len(devices))]
test_iter = chainer.iterators.MultiprocessIterator(test, batch_size, repeat=False, n_processes=num_gpus)
device = 0 if num_gpus > 0 else -1  # -1 indicates CPU, 0 indicates first GPU device.

if num_gpus > 0:
    updater = training.updaters.MultiprocessParallelUpdater(train_iters, optimizer, devices=range(num_gpus))
else:
    updater = training.updater.StandardUpdater(train_iters[0], optimizer, device=device)

我还使用 ParallelUpdater 使用 8 个 GPU 运行了这个基准测试脚本,但性能也很差:https ://github.com/mitmul/chainer-cifar10/blob/master/train.py

我的问题是:我怎样才能从 ParallelUpdater 获得良好的性能,我可能做错了什么?

谢谢!

4

2 回答 2

1

使用多个 GPU 会产生一些通信开销,因此每次迭代速度可能会更慢。如果你使用数据并行方法,你可以使用更大的批量和更大的学习率,它可以加速你的训练。

于 2018-05-04T03:24:15.437 回答
1

我不是很熟悉ParallelUpdater,所以我的理解可能是错误的。

我想目的ParallelUpdater不是为了速度性能,而是它的主要目的是有效地使用内存来计算大批量梯度。

阅读源码时,模型更新是在python for循环中完成的,所以由于GIL(Global Interpreter Lock)机制,我猜它的计算本身并不是并行完成的。 https://github.com/chainer/chainer/blob/master/chainer/training/updaters/parallel_updater.py#L118

如所写,MultiprocessUpdater如果您想通过使用多个 GPU 来获得速度性能的好处,您可以使用。

此外,您可以考虑使用 ChainerMN,它是使用 chainer 进行多 GPU 训练的扩展库。

于 2018-05-04T03:33:51.417 回答