Revenir au contenu principal

TensorFlow™ sur Databricks

Illustration

Utiliser un GPU

Un GPU (processeur graphique) est un composant présent sur la plupart des ordinateurs modernes. Il est conçu pour effectuer les calculs nécessaires aux graphismes en 3D. Les GPU sont principalement utilisés par les jeux vidéos pour calculer la position des polygones et afficher le jeu. Pour résumer sommairement, un GPU est un vaste ensemble de petits processeurs qui effectuent des calculs parallèles en très grande quantité. C'est presque un superordinateur* miniature !

Si les « CPU » d'un processeur graphique sont relativement lents, ils sont très nombreux et spécialisés dans le traitement numérique. Autrement dit, un GPU est capable d'effectuer un grand nombre de tâches de calcul numérique simples simultanément. Et par chance, c'est exactement ce qu'ont besoin de faire de nombreux algorithmes de machine learning.

Vous n'avez pas de GPU ?

Les ordinateurs modernes (depuis une dizaine d'années) possèdent un GPU, même s'il est intégré à la carte-mère. C'est tout à fait suffisant pour ce tutoriel.

Vous devez savoir de quel type de carte graphique vous disposez. Les utilisateurs de Windows peuvent suivre ces instructions – nous conseillons aux autres de consulter la documentation de leur système.

Utilisateurs de cartes autres que Nvidia

Si d'autres cartes graphiques peuvent être compatibles, ce tutoriel n'a été testé que sur une carte graphique Nvidia récente. Si vous avez un autre type de carte graphique, je vous recommande d'acheter ou d'emprunter une carte graphique Nvidia pour vous former. Si cela pose un réel problème, contactez votre établissement pour voir s'il peut vous aider. Si vous n'avez pas de solution, n'hésitez pas à lire ce tutoriel et à l'essayer sur un CPU classique. Vous pourrez transposer vos connaissances par la suite.

* Remarque : pas tout à fait un superordinateur, mais les points communs sont nombreux.

Installation de TensorFlow pour GPU

Si vous n'avez pas déjà installé TensorFlow pour GPU, commençons par cela. Les instructions de la Leçon 1 n'en parlaient pas, donc si vous n'avez pas pris l'initiative d'activer la prise en charge du GPU, elle est toujours désactivée.

Je vous recommande de créer un nouvel environnement Anaconda plutôt que d'essayer de modifier le précédent.

Avant de commencer

Consultez les instructions d'installation officielles de TensorFlow, mais aussi celles d'Anaconda. La principale différence entre ce tutoriel et ce que nous avons fait à la Leçon 1 réside dans le fait que vous avez besoin de la version GPU de TensorFlow. Mais avant d'installer TensorFlow dans cet environnement, vous devez activer l'exploitation du GPU sur votre ordinateur avec CUDA et CuDNN. La documentation officielle de TensorFlow décrit ce processus étape par étape, mais je recommande ce tutoriel si vous essayez de configurer une installation récente d'Ubuntu. En effet, au moment de la rédaction de ce tutoriel (juillet 2016), CUDA n'a pas encore été adapté à la version la plus récente d'Ubuntu, et le processus est beaucoup plus manuel.

Utiliser votre GPU

C'est assez simple en réalité. Du moins sur le plan de la syntaxe. Remplacez simplement ceci :

 

# Setup operations

with tf.Session() as sess:
    # Run your code

 

Par cela :

 

with tf.device("/gpu:0"):
    # Setup operations

with tf.Session() as sess:
    # Run your code

 

Cette nouvelle ligne crée un nouveau gestionnaire de contexte qui indique à TensorFlow comment effectuer ces opérations sur le GPU.

Prenons un exemple concret. Le code ci-dessous crée une matrice aléatoire dont la taille est définie par la ligne de commande. Nous pouvons exécuter le code sur un CPU ou un GPU à l'aide des options de la ligne de commande :

 

import sys
import numpy as np
import tensorflow as tf
from datetime import datetime

device_name = sys.argv[1]  # Choose device from cmd line. Options: gpu or cpu
shape = (int(sys.argv[2]), int(sys.argv[2]))
if device_name == "gpu":
    device_name = "/gpu:0"
else:
    device_name = "/cpu:0"

with tf.device(device_name):
    random_matrix = tf.random_uniform(shape=shape, minval=0, maxval=1)
    dot_operation = tf.matmul(random_matrix, tf.transpose(random_matrix))
    sum_operation = tf.reduce_sum(dot_operation)


startTime = datetime.now()
with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as session:
        result = session.run(sum_operation)
        print(result)

# It can be hard to see the results on the terminal with lots of output -- add some newlines to improve readability.
print("\n" * 5)
print("Shape:", shape, "Device:", device_name)
print("Time taken:", datetime.now() - startTime)

print("\n" * 5)

 

Vous pouvez exécuter ceci dans la ligne de commande :

python matmul.py gpu 1500

Cela va utiliser le CPU avec une matrice de 1 500 au carré. Utilisez ce qui suit pour réaliser la même opération sur le CPU :

python matmul.py cpu 1500

La première chose que vous allez remarquer en exécutant le code orienté GPU est une augmentation considérable de la sortie, par rapport à un script TensorFlow normal. Voici ce que montre mon ordinateur, avant d'afficher les résultats d'une quelconque opération.

 

I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcublas.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcudnn.so.5 locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcufft.so locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcuda.so.1 locally
I tensorflow/stream_executor/dso_loader.cc:108] successfully opened CUDA library libcurand.so locally
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:925] successful NUMA node read from SysFS had negative value (-1), but there must be at least one NUMA node, so returning NUMA node zero
I tensorflow/core/common_runtime/gpu/gpu_init.cc:102] Found device 0 with properties: 
name: GeForce GTX 950M
major: 5 minor: 0 memoryClockRate (GHz) 1.124
pciBusID 0000:01:00.0
Total memory: 3.95GiB
Free memory: 3.50GiB
I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0:   Y 
I tensorflow/core/common_runtime/gpu/gpu_device.cc:838] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 950M, pci bus id: 0000:01:00.0)

 

Si votre code ne produit pas un résultat de nature similaire à celui-ci, vous n'exécutez pas le TensorFlow pour GPU. Autrement, si vous recevez une erreur du type ImportError: libcudart.so.7.5: cannot open shared object file: No such file or directory (Erreur d'importation : libcudart.so.7.5 : impossible d'ouvrir le fichier d'objet partagé : aucun fichier ou répertoire de ce type), alors vous n'avez pas installé correctement la bibliothèque CUDA. Dans ce cas, vous devrez revenir aux instructions d'installation de CUDA.

Essayez d'exécuter le code ci-dessus sur le CPU et le GPU en augmentant lentement le chiffre. Commencez par 1 500, puis essayez 3 000, 4 500, et ainsi de suite. Vous découvrirez que le CPU commence à mettre beaucoup de temps, tandis que le GPU réalise cette opération très rapidement !

Si vous avez plusieurs GPU, vous pouvez utiliser n'importe lequel d'entre eux. Les GPU sont indexés à partir de zéro – le code ci-dessus accède au premier GPU. Si vous utilisez le périphérique gpu:1, le code utilisera le deuxième GPU, et ainsi de suite. Vous pouvez également envoyer une partie de votre calcul à un GPU et une autre à un autre GPU. Sachez également que vous pouvez accéder aux CPU de votre machine de la même façon : utilisez simplement cpu:0 (ou un autre numéro).

Quels types d'opérations dois-je envoyer au GPU ?

De façon générale, si l'étape du processus peut être décrite sous la forme « effectue cette opération mathématique des milliers de fois », envoyez-la au GPU. Cela s'applique par exemple aux multiplications de matrice et au calcul de l'inverse d'une matrice. Les opérations de base sur les matrices sont d'ailleurs d'excellentes candidates pour les GPU. De façon générale (et très simplifiée), les autres opérations doivent être réalisées sur le CPU.

Changer de périphérique et utiliser des GPU a également un coût. Les GPU n'ont pas un accès direct au reste de votre ordinateur (excepté pour l'affichage, bien sûr). Pour cette raison, si vous exécutez une commande sur un GPU, vous devez d'abord copier toutes les données sur ce GPU, effectuer l'opération et copier à nouveau les résultats dans la mémoire principale de votre ordinateur. TensorFlow gère tout cela en coulisse : le code reste simple, mais le travail doit tout de même se faire.

Les GPU ne peuvent pas accueillir toutes les opérations. Si vous recevez l'erreur suivante, c'est que vous essayez de réaliser une opération incompatible avec un GPU :

 

Cannot assign a device to node 'PyFunc': Could not satisfy explicit device specification '/device:GPU:1' because no devices matching that specification are registered in this process;

 

Dans ce cas, vous devez changer de périphérique manuellement pour basculer sur un CPU pour cette opération, ou configurer TensorFlow pour qu'il change automatiquement de périphérique dans cette situation. Pour ce faire, définissez allow_soft_placement sur True dans la configuration, au cours de la création de la session. Le prototype se présente comme suit :

 

with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)):
    # Run your graph here

 

Je recommande également de consigner la position des périphériques lorsque vous utilisez des GPU, de façon à faciliter le débogage des problèmes liés à l'utilisation des périphériques. De cette manière, l'utilisation des périphériques est inscrite dans le journal : vous pouvez voir à quel moment les changements se produisent et en quoi ils affectent le graphe.

 

with tf.Session(config=tf.ConfigProto(allow_soft_placement=True, log_device_placement=True)):
    # Run your graph here

 

  1. Configurez votre ordinateur de manière à utiliser le GPU pour TensorFlow (ou trouvez un ordinateur à emprunter si vous n'avez pas de GPU récent).
  2. Essayez d'exécuter les solutions de l'exercice précédent sur le GPU. Quelles opérations peuvent être réalisées sur un GPU, et lesquelles sont incompatibles ?
  3. Créez un programme qui réalise des opérations sur le GPU et le CPU. Utilisez le code de profilage que nous avons vu à la Leçon 5 pour évaluer l'impact de l'échange de données avec le GPU.
  4. Envoyez-moi votre code ! J'adorerais voir des exemples de votre code, de quelle façon vous utilisez TensorFlow et quelles astuces vous avez découvertes.