2017-09-06 1 views
1

J'essaie de mettre en œuvre un modèle de pensée de saut en utilisant tensorflow et une version actuelle est placé here. enter image description hereComprendre le ResourceExhaustedError: MOO lors de l'allocation du tenseur avec la forme

Actuellement, j'utilise un GPU de ma machine (2 processeurs graphiques au total) et l'info GPU est

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 

Cependant, je suis OOM quand je suis en train de fournir des données au modèle. J'essaie de déboguer comme suit:

J'utilise l'extrait suivant juste après que je lance 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() 
     ]))) 

et ai 2017-09-06 11:29:51,333 INFO main main.py:127 - Total: 62968629 params, à peu près au sujet 240Mb si tout en utilisant tf.float32. La sortie de tf.global_variables est

[<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>] 

Dans mon expression de formation, j'ai un tableau de données dont la forme est (164652, 3, 30), à savoir sample_size x 3 x time_step, le 3 signifie ici la phrase précédente, peine actuelle et la phrase suivante. La taille de ces données d'apprentissage est d'environ 57Mb et est stockée dans un loader. Puis-je utiliser écrire une fonction de générateur pour obtenir les phrases, ressemble

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 

La boucle de formation ressemble

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: 
     ... 

Je suis un OOM. Si je commente l'ensemble du corps try (non pour alimenter les données), le script fonctionne très bien.

Je n'ai aucune idée de pourquoi j'ai obtenu OOM dans une telle échelle de données. En utilisant nvidia-smi J'ai toujours eu

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 | 
+-----------------------------------------------------------------------------+ 

Je ne peut pas voir la utilisation réelle GPU de mon script depuis tensorflow vole toujours toute la mémoire au début. Et le vrai problème ici est que je ne sais pas comment déboguer cela. J'ai lu des articles sur OOM sur StackOverflow. La plupart d'entre eux se sont produits lors de l'alimentation d'un grand ensemble de données de test au modèle et l'alimentation des données par petits lots peut éviter le problème. Mais je ne vois pas pourquoi une si petite combinaison de données et param aspire dans mon 11Gb 1080Ti, puisque l'erreur, il essaie juste d'allouer une matrice de taille [3840 x 155229]. (La matrice de sortie du décodeur, 3840 = 30(time_steps) x 128(batch_size), 155229 est 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: 

Toute aide sera appréciée. Merci d'avance.

Répondre

1

Divisons les problèmes un par un:

A propos tensorflow à allouer toute la mémoire à l'avance, vous pouvez utiliser l'extrait de code ci-dessous pour laisser allouer tensorflow mémoire chaque fois qu'il est nécessaire. Alors que vous pouvez comprendre comment les choses vont.

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

Deuxième chose au sujet de la taille, Comme il n'y a aucune information sur la taille de votre réseau, nous ne pouvons pas estimer ce qui va mal. Cependant, vous pouvez également déboguer pas à pas tout le réseau. Par exemple, créez un réseau avec une seule couche, obtenez sa sortie, créez une session et alimentez une fois les valeurs et visualisez la quantité de mémoire que vous consommez. Itérer cette session de débogage jusqu'à ce que vous voyiez le point où vous sortez de la mémoire.

S'il vous plaît être conscient que la sortie 3840 x 155229 est vraiment, vraiment une grande sortie. Cela signifie ~ 600M neurones, et ~ 2.22GB par couche seulement. Si vous disposez de couches de taille similaire, elles s'additionneront rapidement pour remplir votre mémoire GPU.

Aussi, ce n'est que pour la direction avant, si vous utilisez cette couche pour l'entraînement, la propagation arrière et les couches ajoutées par optimiseur multiplieront cette taille par 2. Donc, pour la formation, vous consommez ~ 5 Go seulement pour la couche de sortie .

Je vous suggère de réviser votre réseau et essayer de réduire la taille du lot/paramètres pour adapter votre compte modèle GPU

+0

Merci pour votre réponse! Je vais essayer le 'gpu_options' bientôt. A propos de la taille du réseau, n'est pas l'extrait 'np.sum ([np.prod (v.get_shape(). As_list()) pour v dans tf.trainable_variables()])' obtention du nombre entier '(62968629)' params du réseau? Doublé avec les gradients, total '2 * 62968629 * 4/1024/1024/1024 -> 0.47G'. Et, j'ai seulement '1' couche dans mon encodeur, et' 1' couche dans mes '2' décodeurs. Le '3840 x 155229' est la sortie du décodeur, pas à propos des params, donc je pense que ça ne doublerait pas lors de la propagation arrière? – Edityouprofile

+0

Ce calcul est correct pour l'inférence. Je pensais que vous avez fait une couche entièrement connecté, mon mauvais. Cependant, pour la formation, vous devez utiliser tf.global_variables() plutôt que trainable_variables() comme optimiseurs et tous les autres appendices que vous implémentez ajouteront des paramètres plus invisibles. –

+0

Merci encore. J'ai imprimé le résultat de 'tf.global_variables()' et 'tf.trainable_variables()' et j'ai mis à jour la question. Dans ma situation, ce dernier ne manque que du tenseur 'global_step' par rapport au premier. – Edityouprofile