Red Huang

Red Huang

kerasを使用して複数のGPUで高速トレーニングを行います。

複数の GPU を使用して効率的なトレーニングを行うための keras#

現在、研究室のコンピュータには高性能な GPU が 3 枚搭載されていますが、keras を最大限に活用するためにはコードを変更する必要があります。

現在の環境は、keras を tensorflow バックエンドと python3 で使用しています。
GPU は 3 枚の 1080ti です。

以前のネットワークアーキテクチャは Sequential アーキテクチャでした(簡単に紹介します)。

image

そのため、各バッチは GPU にタスクを割り当てて実行されます。

つまり、各 GPU に均等に分配されます。

しかし、全ての GPU を十分に活用することはできません。

そのため、バッチを GPU の数(3 つの場合は 3 等分)に分割し、すべてのバッチの結果を結合して 1 つの出力にすることで、計算速度を向上させることができます(もちろん、各 GPU の出力制限もあります)。

以下のコードを使用して、x を(n_gpus)等分に分割します。ただし、この時点では x は実際の数値ではなく、テンソル(まだ実行されていない値)です。

def slice_batch(x, n_gpus, part):
    sh = K.shape(x)
    L = sh[0] // n_gpus
    if part == n_gpus - 1:
        return x[part * L:]
    return x[part * L:(part + 1) * L] 

その後、モデルを以下の関数に渡すと、現在のモデルに(n_gpus)個のラムダレイヤーが追加され、入力に接続されます。

そして、これらの結果をすべて結合して出力にします(バッチの軸で結合します)。

def to_multi_gpu(model, n_gpus=3):
    with tf.device('/cpu:0'):
        print(model.input_shape)
        x = Input(model.input_shape[1:], name="input")

    towers = []
    for g in range(n_gpus):
        with tf.device('/gpu:' + str(g)):
            slice_g = Lambda(slice_batch, lambda shape: shape, arguments={'n_gpus': n_gpus, 'part': g})(x)
            towers.append(model(slice_g))

    with tf.device('/cpu:0'):
        merged = Concatenate(axis=0)(towers)

    return Model(inputs=[x], outputs=[merged]) 

使用後の結果は以下の図のようになります。
image

このテクニックを使用しなかった場合のトレーニング時間は

160 エポック:23 分

このテクニックを使用して 3 つの GPU に均等に分配した場合のトレーニング時間は

160 エポック:9 分

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。