Lc0 — Compilation sur Ubuntu 18.04 — Deuxième partie

Mis à jour le 13/03/2023

Compilation du moteur d'échecs neuronal Lc0 version 0.28 sur Ubuntu 18.04 avec prise en charge des GPU pour les cartes graphiques NVIDIA.

Dans le billet précédent nous avons vu comment compiler le moteur d'échecs neuronal [Lc0] sur Ubuntu 18.04. Pour ses calculs Lc0 utilise alors les ressources du CPU. Lc0 peut tourner plus rapidement et jouer au échecs à un plus haut niveau en utilisant les ressources GPU d'une carte graphique NVIDIA.

Pour cela avant de lancer la compilation il faut installer CUDA (Compute Unified Device Architecture) et cuDNN (CUDA Deep Neural Network) :

  • NVIDIA CUDA Toolkit fourni un environnement de développement pour créer des applications qui utilisent les processeurs graphiques (GPU, Graphics Processing Unit) des cartes Nvidia.
  • NVIDIA CUDA Deep Neural Network (cuDNN) est une bibliothèque de primitives accélérées par GPU pour une utilisation avec des réseaux de neurones profonds.
À lire
Pour une présentation de CUDA et des différences entre CPU et GPU on pourra consulter cet exposé en français de 2013.

Installation de CUDA et cuDNN

Nous ne détaillerons pas ici l'installation de CUDA et cuDNN, il faut créer un compte pour rejoindre le NVIDIA Developer Program et suivre les instructions. Nous avons installé CUDA 11.5 et cuDNN 8.2.4.

  1. Avant de lancer la compilation de Lc0 il est bon de vérifier que la commande nvcc (Nvidia C Compiler) est bien trouvée :
    nvcc --version
    Ce qui donne :
    nvcc: NVIDIA (R) Cuda compiler driver
    Copyright (c) 2005-2021 NVIDIA Corporation
    Built on Mon_Sep_13_19:13:29_PDT_2021
    Cuda compilation tools, release 11.5, V11.5.50
    Build cuda_11.5.r11.5/compiler.30411180_0
    

Compilation

  1. On peut alors lancer la compilation de Lc0 comme vu dans le billet précédent :
    ./build.sh
    Les traces de compilation débutent par des lignes qui indiquent que CUDA et cuDNN ont bien été trouvés :
    ...
    Library cublas found: YES
    Library cudnn found: YES
    Library cudart found: YES
    Program /usr/local/cuda/bin/nvcc found: YES (/usr/local/cuda/bin/nvcc)
    ...
    
  2. On peut alors tester l'exécutable lc0 :
    cd build/release/
    Puis :
    ./lc0
    Ce qui donne :
       _
    |   _ | |
    |_ |_ |_| v0.28.0 built Nov  6 2021
    Found pb network file: ./754042.pb.gz
    Creating backend [cudnn-auto]...
    Switching to [cudnn]...
    No CUDA-capable devices detected
    
    Le message No CUDA-capable devices detected est normal, car nous somme sur une machine virtuelle qui n'a pas accès aux ressources GPU de la machine hôte.

Lancement du benchmark

  1. Après avoir copié l'exécutable lc0 sur la machine hôte (un portable Acer sous Ubuntu 21.10 avec une carte graphique NVIDIA GeForce GTX 1650 Ti) et le réseau de neurones 754042.pb.gz (récupéré au billet précédent) nous pouvons lancer le benchmark avec la commande :
     ./lc0 benchmark
    Et on obtient :
           _
    |   _ | |
    |_ |_ |_| v0.28.0 built Nov  6 2021
    Found pb network file: ./754042.pb.gz
    Creating backend [cudnn-auto]...
    Switching to [cudnn-fp16]...
    CUDA Runtime version: 11.5.0
    Cudnn version: 8.2.4
    GPU: NVIDIA GeForce GTX 1650 Ti
    GPU memory: 3.82031 GiB
    GPU clock frequency: 1485 MHz
    GPU compute capability: 7.5
    
    Position: 1/34 rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
    Benchmark time 437 ms, 2 nodes, 50 nps, move e2e4
    Benchmark time 499 ms, 6 nodes, 58 nps, move e2e4
    Benchmark time 561 ms, 14 nodes, 85 nps, move e2e4
    Benchmark time 608 ms, 21 nodes, 99 nps, move e2e4
    Benchmark time 652 ms, 31 nodes, 121 nps, move e2e4
    Benchmark time 697 ms, 53 nodes, 177 nps, move e2e4
    Benchmark time 700 ms, 64 nodes, 211 nps, move e2e4
    Benchmark time 725 ms, 69 nodes, 211 nps, move e2e4
    Benchmark time 753 ms, 89 nodes, 250 nps, move e2e4
    Benchmark time 798 ms, 131 nodes, 326 nps, move e2e4
    Benchmark time 903 ms, 205 nodes, 405 nps, move e2e4
    Benchmark time 1038 ms, 325 nodes, 507 nps, move e2e4
    Benchmark time 1202 ms, 486 nodes, 603 nps, move e2e4
    Benchmark time 1413 ms, 718 nodes, 706 nps, move e2e4
    Benchmark time 1731 ms, 1040 nodes, 780 nps, move e2e4
    Benchmark time 2080 ms, 1418 nodes, 842 nps, move e2e4
    Benchmark time 2460 ms, 1884 nodes, 913 nps, move e2e4
    Benchmark time 2701 ms, 2119 nodes, 919 nps, move e2e4
    Benchmark time 2974 ms, 2435 nodes, 944 nps, move e2e4
    Benchmark time 3518 ms, 3075 nodes, 985 nps, move e2e4
    Benchmark time 4062 ms, 3703 nodes, 1010 nps, move e2e4
    Benchmark time 4608 ms, 4395 nodes, 1043 nps, move e2e4
    Benchmark time 4905 ms, 4784 nodes, 1061 nps, move e2e4
    Benchmark time 5152 ms, 5040 nodes, 1060 nps, move e2e4
    Benchmark time 5697 ms, 5699 nodes, 1075 nps, move e2e4
    Benchmark time 6241 ms, 6338 nodes, 1084 nps, move e2e4
    Benchmark time 6785 ms, 7016 nodes, 1098 nps, move e2e4
    Benchmark time 7331 ms, 7699 nodes, 1110 nps, move e2e4
    Benchmark time 7875 ms, 8354 nodes, 1117 nps, move e2e4
    Benchmark time 8420 ms, 9019 nodes, 1124 nps, move e2e4
    Benchmark time 8965 ms, 9677 nodes, 1129 nps, move e2e4
    Benchmark time 9509 ms, 10348 nodes, 1135 nps, move e2e4
    Benchmark time 10000 ms, 10783 nodes, 1122 nps, move e2e4
    bestmove e2e4
    ...
    ...
    
    Le GPU est donc bien pris en compte !
  2. Pendant que le benchmark tourne on peut monitorer la carte NVIDIA avec un rafraîchissement toutes les secondes par la commande :
    nvidia-smi -l 1
    Qui donne par exemple :
    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 510.85.02    Driver Version: 510.85.02    CUDA Version: 11.6     |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |                               |                      |               MIG M. |
    |===============================+======================+======================|
    |   0  NVIDIA GeForce ...  Off  | 00000000:01:00.0 Off |                  N/A |
    | N/A   46C    P3    29W /  N/A |    897MiB /  4096MiB |    100%      Default |
    |                               |                      |                  N/A |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                                  |
    |  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
    |        ID   ID                                                   Usage      |
    |=============================================================================|
    |    0   N/A  N/A      1183      G   /usr/lib/xorg/Xorg                  4MiB |
    |    0   N/A  N/A      7236      C   ./lc0                             889MiB |
    +-----------------------------------------------------------------------------+
    
    100% des ressources du GPU sont utilisées.
  3. Pour avoir la consommation de GPU par process utiliser la commande :
    watch -n 1 nvidia-smi pmon -c 1
    Qui donne :
    # gpu        pid  type    sm   mem   enc   dec   command
    # Idx          #   C/G     %     %     %     %   name
        0       1183     G     -     -     -     -   Xorg
        0       7994     C    98     9     -     -   lc0
    
    C'est donc bien Lc0 qui utilise presque tout le GPU !

Télécharger

 lc0-v0.28.2-linux.tgz

L'archive contient les fichiers suivants :

  • lc0-v0.28.2-linux-cpu : Lc0 version 0.28.2 sans support GPU NVIDIA.
  • lc0-v0.28.2-linux-gpu-cuda11.8 : Lc0 version 0.28.2 avec support GPU NVIDIA (compilée avec CUDA 11.8 et cuDNN 8.2.4).
  • 754042.pb.gz : réseau de neurones (le même que celui des releases 0.28).

Pour la version 0.29 voir le billet Lc0 - Compilation sur Ubuntu 18.04 de Lc0 v0.29 .