2017-09-06 12 views
1

私はtensorflowを使ってスキップ思考モデルを実装しようとしています。現在のバージョンはhereです。現在、私は1つの私のマシンのGPU(合計2つのGPU)とGPUの情報を使用して enter image description hereResourceExhaustedErrorを理解する:テンソルと形状を割り当てるときのOOM

私がモデルにデータを供給しようとしているとき

2017-09-06 11:29:32.657299: I tensorflow/core/common_runtime/gpu/gpu_device.cc:940] Found device 0 with properties: 
name: GeForce GTX 1080 Ti 
major: 6 minor: 1 memoryClockRate (GHz) 1.683 
pciBusID 0000:02:00.0 
Total memory: 10.91GiB 
Free memory: 10.75GiB 

はしかし、私はOOMを得ています。私は次のようにデバッグしよう:

私は大体程度240Mbすべての場合tf.float32を使用して、私はsess.run(tf.global_variables_initializer())

logger.info('Total: {} params'.format(
     np.sum([ 
      np.prod(v.get_shape().as_list()) 
      for v in tf.trainable_variables() 
     ]))) 

を実行し、2017-09-06 11:29:51,333 INFO main main.py:127 - Total: 62968629 paramsを得た直後に次のコードを使用します。 tf.global_variablesの出力は私のトレーニング・フレーズで

[<tf.Variable 'embedding/embedding_matrix:0' shape=(155229, 200) dtype=float32_ref>, 
<tf.Variable 'encoder/rnn/gru_cell/gates/kernel:0' shape=(400, 400) dtype=float32_ref>, 
<tf.Variable 'encoder/rnn/gru_cell/gates/bias:0' shape=(400,) dtype=float32_ref>, 
<tf.Variable 'encoder/rnn/gru_cell/candidate/kernel:0' shape=(400, 200) dtype=float32_ref>, 
<tf.Variable 'encoder/rnn/gru_cell/candidate/bias:0' shape=(200,) dtype=float32_ref>, 
<tf.Variable 'decoder/weights:0' shape=(200, 155229) dtype=float32_ref>, 
<tf.Variable 'decoder/biases:0' shape=(155229,) dtype=float32_ref>, 
<tf.Variable 'decoder/previous_decoder/rnn/gru_cell/gates/kernel:0' shape=(400, 400) dtype=float32_ref>, 
<tf.Variable 'decoder/previous_decoder/rnn/gru_cell/gates/bias:0' shape=(400,) dtype=float32_ref>, 
<tf.Variable 'decoder/previous_decoder/rnn/gru_cell/candidate/kernel:0' shape=(400, 200) dtype=float32_ref>, 
<tf.Variable 'decoder/previous_decoder/rnn/gru_cell/candidate/bias:0' shape=(200,) dtype=float32_ref>, 
<tf.Variable 'decoder/next_decoder/rnn/gru_cell/gates/kernel:0' shape=(400, 400) dtype=float32_ref>, 
<tf.Variable 'decoder/next_decoder/rnn/gru_cell/gates/bias:0' shape=(400,) dtype=float32_ref>, 
<tf.Variable 'decoder/next_decoder/rnn/gru_cell/candidate/kernel:0' shape=(400, 200) dtype=float32_ref>, 
<tf.Variable 'decoder/next_decoder/rnn/gru_cell/candidate/bias:0' shape=(200,) dtype=float32_ref>, 
<tf.Variable 'global_step:0' shape=() dtype=int32_ref>] 

で、私はその形状(164652, 3, 30)あるデータ配列を持っている、すなわちsample_size x 3 x time_step、ここ3は前の文、現在の文と次の文を意味します。このトレーニングデータのサイズは約57Mbで、loaderに格納されています。それから私は文章を取得するにはジェネレータ関数を書く使用し、

def iter_batches(self, batch_size=128, time_major=True, shuffle=True): 

    num_samples = len(self._sentences) 
    if shuffle: 
     samples = self._sentences[np.random.permutation(num_samples)] 
    else: 
     samples = self._sentences 

    batch_start = 0 
    while batch_start < num_samples: 
     batch = samples[batch_start:batch_start + batch_size] 

     lens = (batch != self._vocab[self._vocab.pad_token]).sum(axis=2) 
     y, x, z = batch[:, 0, :], batch[:, 1, :], batch[:, 2, :] 
     if time_major: 
      yield (y.T, lens[:, 0]), (x.T, lens[:, 1]), (z.T, lens[:, 2]) 
     else: 
      yield (y, lens[:, 0]), (x, lens[:, 1]), (z, lens[:, 2]) 
     batch_start += batch_size 

のようなトレーニング・ループが

for epoch in num_epochs: 
    batches = loader.iter_batches(batch_size=args.batch_size) 
    try: 
     (y, y_lens), (x, x_lens), (z, z_lens) = next(batches) 
     _, summaries, loss_val = sess.run(
     [train_op, train_summary_op, st.loss], 
     feed_dict={ 
      st.inputs: x, 
      st.sequence_length: x_lens, 
      st.previous_targets: y, 
      st.previous_target_lengths: y_lens, 
      st.next_targets: z, 
      st.next_target_lengths: z_lens 
     }) 
    except StopIteraton: 
     ... 

のように見えるその後、私はOOMを得たに見えます。私が全部try本文(データをフィードしない)をコメントアウトすると、スクリプトは正常に動作します。

私はなぜこのような小さなデータスケールでOOMを取得したのかわかりません。 nvidia-smi使用私はいつも

Wed Sep 6 12:03:37 2017 
+-----------------------------------------------------------------------------+ 
| NVIDIA-SMI 384.59     Driver Version: 384.59     | 
|-------------------------------+----------------------+----------------------+ 
| GPU Name  Persistence-M| Bus-Id  Disp.A | Volatile Uncorr. ECC | 
| Fan Temp Perf Pwr:Usage/Cap|   Memory-Usage | GPU-Util Compute M. | 
|===============================+======================+======================| 
| 0 GeForce GTX 108... Off | 00000000:02:00.0 Off |     N/A | 
| 0% 44C P2 60W/275W | 10623MiB/11172MiB |  0%  Default | 
+-------------------------------+----------------------+----------------------+ 
| 1 GeForce GTX 108... Off | 00000000:03:00.0 Off |     N/A | 
| 0% 43C P2 62W/275W | 10621MiB/11171MiB |  0%  Default | 
+-------------------------------+----------------------+----------------------+ 

+-----------------------------------------------------------------------------+ 
| Processes:              GPU Memory | 
| GPU  PID Type Process name        Usage  | 
|=============================================================================| 
| 0  32748 C python3          10613MiB | 
| 1  32748 C python3          10611MiB | 
+-----------------------------------------------------------------------------+ 

を得た私tensorflowは常に先頭に、すべてのメモリを盗むため、は私のスクリプトの実際 GPUの使用状況を見ることができません。実際の問題はここで私はこれをデバッグする方法がわかりません。

OOMについてのいくつかの記事をStackOverflowで読んだことがあります。それらのほとんどは、大きなテストセットデータをモデルに送り、小さなバッチでデータを供給すると問題を回避することができました。しかし、なぜ私は11Gbの1080Tiでこのような小さなデータとパラメータの組み合わせがうまくいかないのか、なぜならそれはちょうど[3840 x 155229]というサイズの行列を割り当てようとするエラーなので、私はそうしません。 (デコーダの出力マトリックス3840 = 30(time_steps) x 128(batch_size),155229はvocab_sizeです)。

2017-09-06 12:14:45.787566: W tensorflow/core/common_runtime/bfc_allocator.cc:277] ********************************************************************************************xxxxxxxx 
2017-09-06 12:14:45.787597: W tensorflow/core/framework/op_kernel.cc:1158] Resource exhausted: OOM when allocating tensor with shape[3840,155229] 
2017-09-06 12:14:45.788735: W tensorflow/core/framework/op_kernel.cc:1158] Resource exhausted: OOM when allocating tensor with shape[3840,155229] 
    [[Node: decoder/previous_decoder/Add = Add[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](decoder/previous_decoder/MatMul, decoder/biases/read)]] 
2017-09-06 12:14:45.790453: I tensorflow/core/common_runtime/gpu/pool_allocator.cc:247] PoolAllocator: After 2857 get requests, put_count=2078 evicted_count=1000 eviction_rate=0.481232 and unsatisfied allocation rate=0.657683 
2017-09-06 12:14:45.790482: I tensorflow/core/common_runtime/gpu/pool_allocator.cc:259] Raising pool_size_limit_ from 100 to 110 
Traceback (most recent call last): 
    File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1139, in _do_call 
    return fn(*args) 
    File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/client/session.py", line 1121, in _run_fn 
    status, run_metadata) 
    File "/usr/lib/python3.6/contextlib.py", line 88, in __exit__ 
    next(self.gen) 
    File "/usr/local/lib/python3.6/dist-packages/tensorflow/python/framework/errors_impl.py", line 466, in raise_exception_on_not_ok_status 
    pywrap_tensorflow.TF_GetCode(status)) 
tensorflow.python.framework.errors_impl.ResourceExhaustedError: OOM when allocating tensor with shape[3840,155229] 
    [[Node: decoder/previous_decoder/Add = Add[T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](decoder/previous_decoder/MatMul, decoder/biases/read)]] 
    [[Node: GradientDescent/update/_146 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_2166_GradientDescent/update", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/cpu:0"]()]] 

During handling of the above exception, another exception occurred: 

助けてください。前もって感謝します。

答えて

1

はのは、問題を一つずつ分けてみましょう:

tensorflowについて、事前にすべてのメモリを割り当てるために、あなたはそれが必要とされるたびtensorflowがメモリを割り当てるようにする次のコードスニペットを使用することができます。物事がどのように進行しているのか理解できるように。お使いのネット​​ワークのサイズに関する情報がないとサイズについて

gpu_options = tf.GPUOptions(allow_growth=True) 
session = tf.InteractiveSession(config=tf.ConfigProto(gpu_options=gpu_options)) 

2つ目は、 は、我々は間違って何が起こっているかを推定することはできません。ただし、代わりにすべてのネットワークを段階的にデバッグすることもできます。たとえば、1つのレイヤーだけでネットワークを作成し、その出力を取得し、セッションを作成して値を1回フィードし、消費するメモリ量を視覚化します。メモリから外れている箇所が見えるまで、このデバッグセッションを繰り返します。

3840 x 155229の出力は本当に大きな出力です。これは〜600Mニューロンを意味し、1層あたり〜2.22GBしか意味しません。似たようなサイズのレイヤーがあれば、それらのレイヤーはすべてGPUメモリをかなり速く満たすために追加されます。

また、これは順方向のみです。トレーニング用にこのレイヤーを使用している場合、オプティマイザによって追加されたバックプロパゲーションとレイヤーは、このサイズに2を掛けます。したがって、トレーニングの場合、出力レイヤー。

私はあなたのネットワークを修正し、バッチサイズ/パラメータがGPU

に答えるため
+0

感謝をモデルに合うようにカウント削減しようとすることをお勧め!すぐに 'gpu_options'を試してみます。ネットワークのサイズについては、tf.trainable_variables()のvの 'np.sum([np.prod(v.get_shape()。as_list()])'数値を取得する '(62968629)'ネットワークのparams?グラデーションで2倍になり、合計で '2 * 62968629 * 4/1024/1024/1024 - > 0.47G'となります。私のエンコーダには '1'層しかなく、' 2'デコーダには '1'層しかありません。 '3840 x 155229'はデコーダの出力であり、paramsではないので、逆伝搬すると倍精度にならないと思いますか? – Edityouprofile

+0

この計算は推論に適しています。私はあなたが完全につながった層を作ったと思った。しかし、トレーニングのためには、オプティマイザとしてtrainable_variables()ではなくtf.global_variables()を使用する必要があり、実装する他のすべての付録では、目に見えないパラメータが追加されます。 –

+0

もう一度ありがとうございます。私は 'tf.global_variables()'と 'tf.trainable_variables()'の結果を表示し、質問を更新しました。私の状況では、後者は 'global_step'テンソルが前者に比べて不足しています。 – Edityouprofile

関連する問題