Instalacja Tensorflow 0.9 CUDA 7.5 na ubuntu 16.04 i diabeł na ramieniu

Czy też tak macie? Diabeł siedzący na ramieniu szepcze wam do ucha „no weź zaktualizuj, przecież to zajmie chwilkę”. Tak właśnie zaczyna się historia instalacji biblioteki Tensorflow od Google pozwalająca na uczenie sieci neuronowych tzw. deep learning. Wszystko miało pójść gładko, jednak jej konfiguracja na ubuntu 16.04 jeszcze może przysporzyć wiele kłopotów.

Aktualizacja ubuntu 16.04, co mnie podkusiło

Wpis ten z jednej zawiera instrukcję instalacji wspomnianej biblioteki, a z drugiej przedstawia historię moich zmagań, walki i poświęcenia, opisuje chwile zwątpienia, załamania oraz ostatecznego triumfu. Drogi czytelniku jeżeli zależy tobie tylko na instrukcji instalacji Tensorflow 0.9 na ubuntu 16.04 to zapraszam do tego gist’a, natomiast jeżeli jesteś zainteresowany historią to proszę czytaj dalej.

Cała przygoda z instalacją Tensorflow rozpoczęła się od aktualizacji ubuntu, jak mawiają lepsze jest wrogiem dobrego, lecz nie bacząc na mądrości ludowe postanowiłem dokonać aktualizacji systemu operacyjnego mojego serwera obliczeniowego na uczelni. Swoją drogą, maszyna całkiem wydajna 64GB RAM oraz 3 karty graficzne Geforce 780 TI, całość służyła mi głównie do prowadzenia badań polegających optymalizacji algorytmów pod GPU.

Wróćmy do sedna sprawy serwer pracował pod ubuntu 14.04, lecz podkusiło mnie aby dokonać jego aktualizacji do 16.04. Tak naprawdę to podkusiła mnie zmiana wersji Pythona, który w 16.04 domyślnie jest w wersji 3.5. Czytałem tyle achów i ochów o nowszym, szybszym, stabilniejszym, elegantszym Pythonie 3.5, że postanowiłem zaktualizować całą maszynę (sic!) zamiast zaktualizować tylko Pythona. A co tam? Przecież to tylko chwila, nie?

Lecz, nie śmiejcie się jeszcze, nie jestem w cale taki głupi, z moich przygód z informatyką wiem, że zawsze coś może pójść nie tak, więc szybki research w sieci czy nie ma problemów z aktualizacją, bibliotekami itp. utwierdził mnie tyko w przekonaniu, że wszystko pójdzie szybko i gładko. Już czujecie co się święci?
Więc zachęcony pozytywnymi komentarzami, bo przecież taka aktualizacji to spowoduje, że wszystko nagle zacznie działać lepiej, szybciej, z 3 kart zrobi się 6, podwoi się ram na maszynie oraz na dodatek będę szybciej biegał, rozpocząłem proces aktualizacji. Uważnie i krok po kroku wykonywałem polecenia z tutoriala

How To Upgrade to Ubuntu 16.04 LTS from Ubuntu 14.04 LTS

Trzy magiczne komendy

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo do-release-upgrade -d

i po sprawie. Serwer zrestartowałem, następnie szybkie

$ lsb_release -a

i ku mojej radości ujrzałem

Distributor ID: Ubuntu
Description:    Ubuntu 16.04.1 LTS
Release:        16.04
Codename:       xenial

 

Aktualizacja sterownika karty graficznej NVidia na ubuntu 16.04

Czyli aktualizacja się powiodła, lecz zanim odtrąbiłem kolejny sukces w mojej karierze (już wpisywałem to do swojego CV) postanowiłem sprawdzić czy wszystko działa. Na pierwszy rzut poszły karty graficzne i jakież było moje zdziwienie gdy:

$ nvidia-smi
modprobe: FATAL: Module nvidia not found in directory /lib/modules/4.4.0-31-generic
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

Można się było tego spodziewać, nowsze jądro, więc i inne sterowniki do karty są potrzebne. Żaden problem, wyrzuciłem stare sterowniki

$ sudo apt-get purge nvidia

i zainstalowałem nowe

#Add the ppa repo
$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt-get update

#Install the recommended driver (currently nvidia-367)
$ sudo ubuntu-drivers autoinstall
$ sudo reboot

dzięki czemu moje karty zostały rozpoznane, niestety najnowszy sterownik NVidia 367.35 nie ma ma wsparcia dla wszystkich czujników dla moich kart, więc nie pokazuje wykorzystania pamięci oraz procesorów na karcie. Nic to, ważne, że karty są.

$ nvidia-smi
Wed Jul 20 22:54:15 2016
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 367.35                 Driver Version: 367.35                    |
|-------------------------------+----------------------+----------------------+
| 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 780 Ti  Off  | 0000:03:00.0     N/A |                  N/A |
| 27%   48C    P0    N/A /  N/A |      0MiB /  3018MiB |     N/A      Default |
+-------------------------------+----------------------+----------------------+
|   1  GeForce GTX 780 Ti  Off  | 0000:04:00.0     N/A |                  N/A |
| 22%   44C    P0    N/A /  N/A |      0MiB /  3020MiB |     N/A      Default |
+-------------------------------+----------------------+----------------------+
|   2  GeForce GTX 780 Ti  Off  | 0000:08:00.0     N/A |                  N/A |
|  0%   32C    P0    N/A /  N/A |      0MiB /  3020MiB |     N/A      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0                  Not Supported                                         |
|    1                  Not Supported                                         |
|    2                  Not Supported                                         |
+-----------------------------------------------------------------------------+

 

Instalacja CUDA 7.5, cuDNN oraz Tensorflow

Idziemy więc dalej, skoro nie dział sterownik to trzeba zaktualizować CUDA toolkit, pomógł mi w tym post na formu NVidia tensorflow-cannot-find-cudnn-ubuntu-16-04-cuda7-5

$ sudo apt-get install nvidia-cuda-toolkit
$ sudo apt-get install libcupti-dev zlib1g-dev

chyba karta się odwróciła, bo to czego najbardziej się obawiałem poszło szybko i sprawnie. Co prawda biblioteki cuda zostały zainstalowane w folderze /usr/lib/nvidia-cuda-toolkit a Tensorflow domyślnie oczekuje, że będą w /usr/local/cuda/, lecz tym problemem zajmiemy się za chwilę, sprawdzam co zostało zainstalowane

$ dpkg --get-selections | grep nvidia
nvidia-367                                      install
nvidia-cuda-dev                                 install
nvidia-cuda-doc                                 install
nvidia-cuda-gdb                                 install
nvidia-cuda-toolkit                             install
nvidia-opencl-dev:amd64                         install
nvidia-opencl-icd-367                           install
nvidia-prime                                    install
nvidia-profiler                                 install
nvidia-settings                                 install

Aby uszczęśliwić Tensorflow i ułatwić sobie pracę, utworzyłem symlinki w folderze /usr/local/cuda

# Put symlinks in /usr/local/cuda
$ sudo mkdir /usr/local/cuda
$ cd /usr/local/cuda
$ sudo ln -s /usr/lib/x86_64-linux-gnu/ lib64
$ sudo ln -s /usr/include/ include
$ sudo ln -s /usr/bin/ bin
$ sudo ln -s /usr/lib/x86_64-linux-gnu/ nvvm
$ sudo mkdir -p extras/CUPTI
$ cd extras/CUPTI
$ sudo ln -s /usr/lib/x86_64-linux-gnu/ lib64
$ sudo ln -s /usr/include/ include

Należy także upewnić się czy zmienna $PATH zawiera ścieżkę do folderu /usr/local/cuda

$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/cuda/bin:/usr/local/cuda/bin

U mnie był problem, że ścieżki do cuda pojawiały się na początku, co powodowało później pewne zamieszanie z pythonem, więc wyedytowałem plik  ~/.bashrc, w którym ścieżkę do $CUDA_HOME dałem na koniec

export CUDA_HOME=/usr/local/cuda
export CUDA_ROOT=${CUDA_HOME}
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64

PATH=${PATH}:${CUDA_HOME}/bin
export PATH
....

Poza tym musiałem usunąć pozostałości po poprzednich wersjach CUDA

$ sudo rm -r /etc/profile.d/cuda_var.sh

Diabeł tkwi w wersjach cuDNN

Tensorflow wymaga biblioteki cuDNN (https://developer.nvidia.com/cudnn), aby ją ściągnąć należy się zarejestrować i zalogować do NVidia developer, następnie wypełnić szybką ankietę i otrzymamy dostęp do kolejnych wersji, w chwili pisania posta dostępne są cuDNN versions

Poziom frustracji wzrasta z każdą komendą

Od tego momentu, zaczęły padać same fucki, ku..y, ja jeb.e i wiele innych pięknie brzmiących słów zaczerpniętych z gwary podsklepowej. Wszystko za sprawą mojej ślepej chęci optymalizowania wszystkiego i próbowania nowych rzeczy. Zgadnijcie, którą wersję wybrałem cuDNN? No, nie zgadliście to nie jest v5.1 RC, aż taki głupi nie jestem, padło na v5 for CUDA 7.5.  A dlaczego? Bo naczytałem się, że o parę procent poprawili wydajność w stosunku do starej, stabilnej, sprawdzonej, przetestowanej przez miliony instalacji wersji v4.

No i zaczęła się moja droga krzyżowa. Żadna z udostępnionych przez Google gotowych zbudowanych paczek nie wspiera cuDNN v5, zostaje tylko własna kompilacja. Więc jako stary wyga, któremu żadne gcc nie jest straszne, robię git clone tensorflow, mam kod. Doczytuję w dokumentacji, że do zbudowania potrzebne jest narzędzie bazel (#wtf), nigdy z niego nie korzystałem, lecz piszą, że jest super wydajne, więc płynę dalej. Instaluję bazel, szukam procedury instalacji i bazel wspiera tylko ubuntu 14.04 i 15.10. Dobra szukam w sieci jak to ustrojstwo zainstalować, mam, na blogu jakiegoś chińczyka napisane jest, że wystarczy ściągnąć paczkę deb i będzie działać. A więc ściągam instaluje i boom, okazuje się że potrzebuje openjdk. Zaszedłem już daleko, szybkie apt-get install openjdk załatwi sprawę.

Niestety nie załatwiło.

Domyślne openjdk-9-jdk nie chce się zainstalować, ok 1h węszenia w sieci pozwala mi stwierdzić, że nikomu się nie instaluje. Uff, jest to jakieś pocieszenie. Znalazłem sposób, aby w końcu zainstalować i na usta znowu pocisnęły się niecenzuralne słowa. Żona kazała mi z tym laptopem z domu się wynosić, jak mam zamiar tak dalej się zachowywać, a koty to się już same wyniosły.

Ożeż, Bazel nie współpracuje z openjdk-9-jdk, trzeba zainstalować openjdk-8-jdk. Zainstalowałem, wykonuje kolejne komendy z dokumentacji od Google

bazel build -c opt --config=cuda //tensorflow/cc:tutorials_example_trainer

Po ok 10 minutach, błędy kompilacji. A czegóż się spodziewałeś? Kolejne 2h walki z problemem, edycja kodu itp. I nagle olśnienie. Po co mi cuDNN v5, wrzuć wersję v4. Po zmarnowanych ok 4h, wykorzystanie cuDNN v4  pozwoliło mi na zainstalowanie Tensorflow z gotowej paczki przygotowanej przez Google.

Przestroga dla reszty – Nie idźcie tą drogą, kompilacja tensorflow to zuo.

Światełko w tunelu cuDNN v4

Instalacja cuDNN jest bardzo prosta, ściągamy ze strony NVidi odpowiednią paczkę, rozpakowujemy i kopiujemy pliki do odpowiednich folderów. Pomocny może okazać się post how-can-i-install-cudnn-on-ubuntu-16-04

$ tar xzvf cudnn-7.0-linux-x64-v4.0-prod.tg
$ cd cuda
$ sudo cp include/cudnn.h /usr/include
$ sudo cp lib64/libcudnn* /usr/lib/x86_64-linux-gnu/
$ sudo chmod a+r /usr/lib/x86_64-linux-gnu/libcudnn*

Następnie zgodnie z dokumentacją od Google (https://www.tensorflow.org/versions/r0.9/get_started/os_setup.html#virtualenv-installation), stworzyłem przy pomocy virtualenv lokalne środowisko z pythonem 3.5 i w nim zainstalowałem Tensorflow 0.9 z wsparciem dla GPU.

$ virtualenv -p python3 tfenv
$ source tfenv/bin/activate

# Ubuntu/Linux 64-bit, GPU enabled, Python 3.5 
# Requires CUDA toolkit 7.5 and CuDNN v4. For other versions, see "Install from sources" below.
(tfenv)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-0.9.0-cp35-cp35m-linux_x86_64.whl
(tfenv)$ pip3 install --upgrade $TF_BINARY_URL

Na koniec przetestowałem czy wszystko gra. Stworzyłem skrypt testowy test_tf.py

import tensorflow as tf
tf_session = tf.Session()
x = tf.constant(1)
y = tf.constant(1)
print(tf_session.run(x + y))

i uruchmiłem go

$ python test_tf.py

W terminalu ujrzałem:

(tfenv)$ python test_tensorflow.py
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 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 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:924] 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 780 Ti
major: 3 minor: 5 memoryClockRate (GHz) 1.0845
pciBusID 0000:08:00.0
Total memory: 2.95GiB
Free memory: 2.88GiB
W tensorflow/stream_executor/cuda/cuda_driver.cc:572] creating context when one is currently active; existing: 0x260d110
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:924] 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 1 with properties:
name: GeForce GTX 780 Ti
major: 3 minor: 5 memoryClockRate (GHz) 1.0845
pciBusID 0000:04:00.0
Total memory: 2.95GiB
Free memory: 2.88GiB
W tensorflow/stream_executor/cuda/cuda_driver.cc:572] creating context when one is currently active; existing: 0x2a39af0
I tensorflow/stream_executor/cuda/cuda_gpu_executor.cc:924] 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 2 with properties:
name: GeForce GTX 780 Ti
major: 3 minor: 5 memoryClockRate (GHz) 1.0845
pciBusID 0000:03:00.0
Total memory: 2.95GiB
Free memory: 2.88GiB
I tensorflow/core/common_runtime/gpu/gpu_init.cc:126] DMA: 0 1 2
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 0:   Y Y Y
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 1:   Y Y Y
I tensorflow/core/common_runtime/gpu/gpu_init.cc:136] 2:   Y Y Y
I tensorflow/core/common_runtime/gpu/gpu_device.cc:806] Creating TensorFlow device (/gpu:0) -> (device: 0, name: GeForce GTX 780 Ti, pci bus id: 0000:08:00.0)
I tensorflow/core/common_runtime/gpu/gpu_device.cc:806] Creating TensorFlow device (/gpu:1) -> (device: 1, name: GeForce GTX 780 Ti, pci bus id: 0000:04:00.0)
I tensorflow/core/common_runtime/gpu/gpu_device.cc:806] Creating TensorFlow device (/gpu:2) -> (device: 2, name: GeForce GTX 780 Ti, pci bus id: 0000:03:00.0)
2

Najważniejsze, że Tensor rozpoznał i wczytał biblioteki od CUDA, rozpoznał moje trzy karty oraz na końcu dał poprawy wynik „2”. Mogłem ogłosić pełne zwycięstwo.

Wnioski na przyszłość

Czego mnie nauczyło to doświadczenie, podejrzewam, że niczego. Przecież już wielokrotnie przerabiałem podobny scenariusz, diabeł siedzący na ramieniu co rusz mi podpowiada „now weź, zaktualizuj, pójdzie szybko, to tylko jedno polecenie”. I wklepujesz to jedno polecenie, chwilę się zastanawiasz, ba nawet zadajesz sam sobie pytanie, a co jeżeli coś pójdzie nie tak, lecz po chwili i tak naciskasz enter. I gdzieś jakby w dole słyszysz rubaszny śmiech. Niby jestem mądrzejszy, bardziej doświadczony, przecież sprawdzam w sieci czy dana aktualizacja może zaszkodzić, lecz na palcach jednej ręki mogę policzyć te bezproblemowe sytuacje.

 

5 Comments Instalacja Tensorflow 0.9 CUDA 7.5 na ubuntu 16.04 i diabeł na ramieniu

  1. Witek

    Artykuł ciekawy i przydatny. Trochę odbiegając od tematu, mam pytanie czy warto instalować TFlearn (czyli nakładkę na TensorFlow ułatwiającą korzustanie z TF w Pythonie) ??????

    Reply
    1. ksopyla

      Na chwilę obecną moja odpowiedź brzmi nie wiem, TFLearn mam na liście TODO.
      Z tego co wiem to dużo czerpie z filozofi Scikit-learn, z którą akurat pracuje mi się dobrze, spójne api, zachowywana kompatybilność wstecz i bardzo stabilna. Jednak jest stosunkowo zamknięta pod względem funkcjonalnym tzn. ma gotowe komponenty do wykorzystania, ale czasami potrzeba czegoś niestandardowego szczególnie w badaniach i trzeba wgryzać się w szczegóły.

      Podsumowując, mogą wyrazić jedynie moje przypuszczenia, że z TFlearn jest podobnie, więc jeżeli potrzebujesz gotowych komponentów do wykorzystania to będzie idealna.
      Wiele dobrego słyszałem o bibliotece Keras i u mnie na liście do przetestowania jest wyżej, śledzę jej autora na Twiterze i dosyć często jest aktualizowana o nowe metody, architektury itp.

  2. Tcaffe

    zastanawialem sie do czego to mozna by uzyc i stwierdzam, ze znalazlem jedno zastosowanie (po za traceniem czasu i pradu).
    Rozwiazanie captcha Aero2. na githubie sa dane.

    Zastanawialem sie nad prostym kolko i krzyzyk i okazuje sie, ze to albo dosc potezne narzedzie (glebokosc ruchow, trzeba by zdrowo opisac plansze) albo gdy wrzucimy po prostu 9 pol (+1 kto teraz gra) i poprosimy o 9 pol wyniku to …. nic nie dostaniemy. Glebokie uczenie jest za slabe nawet na tak marna gre. Chyba, ze jak mowie dodamy odrebne uczenie dla kazdych tripletow pol ale wtedy to niewiele tego uczenia zostaje 😉

    zagranie w cos rownie prostego wlasciwie wymagalo by rownie wielkich nakladow na przygotowania.

    Reply

Ciekawe, wartościowe, podziel się proszę opinią!

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.