Если инфорация оказалась интересна и/или полезна, не побрезгуйте, оставьте комментарий ;)

понедельник, 24 февраля 2020 г.

Tensorflow на картах AMD. Как собрать. Версия 1.0

ОГОВОРОЧКА.
Прежде чем делать, как написано в этой статье, посмотрите пункт 19.  Вы можете сэкономить много времени и нервов :)

Появилась необходимость в запуске сервера с аппаратным ускорением вычислений Tensorflow. В наличие только карты AMD.

Найдена инструкция "TensorFlow Native Compilation". Постараюсь сделать ее вольное переложение на русский язык с добавлением описания граблей, на которые наступил (их совсем немного, оригинальная инструкция хорошая).

Итак, прежде всего надо скачать и поставить Ubuntu 16.04. Взять ее можно со страницы http://releases.ubuntu.com/xenial/. Авторы инструкции предупреждают, что на других версиях ОС или дистрибутивах может и заработает, но они не пробовали и ничего не гарантируют. То же самое относится к версиям ПО, например, Python (проверено на версии 3.5), которые мы будем ставить в дальнейшем.

--------------------------------------------------
ОБНОВЛЕНИЕ.
Под Ubuntu 16.04. у меня возникли проблемы с драйверами видеокарты (рекомендуемой amdgpu-pro-17.50 и другими версиями). Не ставился amdgpu-dkms (об этом ниже). Видекарты после перезагрузки пропадали из clinfo. В общем, не работало, как хотелось. Поэтому конечная конфигурация, к которой я пришел:

  • Ubuntu 18.04 
  • Python 3.6
  •  Драйвер amdgpu-pro-19.50-1011208-ubuntu-18.04

Да, не протестировано разработчиками, но работает.
--------------------------------------------------

Я ставил версию Рабочей станции (Desktop), так как настраивать сеть мне проще из графики, кроме того на этом сервере можно будет запустить браузер. Да и вообще, почему бы нет.

Также решение проверено только для карт AMD R9 Nano Fury и Intel Gen9 HD Graphics. Но у меня завелось на AMD FirePro S7100X.

1. Сделаем папку, куда будем загружать файлы:
$ mkdir ~/tensorflow-amd
$ cd ~/tensorflow-amd

2. Скачиваем драйверы OpenCL под видеокарту с сайта производителя (AMD)
$ wget --referer http://support.amd.com/ https://www2.ati.com/drivers/linux/ubuntu/amdgpu-pro-17.50-511655.tar.xz
$ tar xf amdgpu-pro-17.50-511655.tar.xz
$ ./amdgpu-pro-17.50-511655/amdgpu-pro-install --opencl=legacy --headless

--------------------------------------------------
ОБНОВЛЕНИЕ.
При компиляции и установке модулей DKMS происходила ошибка. Пример ошибки:

Building initial module for 5.3.0-26-generic
ERROR: Cannot create report: [Errno 17] File exists: '/var/crash/amdgpu-dkms.0.crash'
Error! Bad return status for module build on kernel: 5.3.0-26-generic (x86_64)
Consult /var/lib/dkms/amdgpu/19.50-967956/build/make.log for more information.


Пример вывода консоли взял здесь: https://community.amd.com/thread/248166. По ссылке есть пример лога. Не буду его сюда добавлять.

Найденное решение.
1. ставим драйверы следующим образом:
./amdgpu-pro-17.50-511655/amdgpu-pro-install --opencl=legacy --headless --no-dkms

2. ставим модули вручную
apt install amdgpu-dkms libdrm-amdgpu-amdgpu1 libdrm-amdgpu1 libdrm2-amdgpu

Решение найдено тут: https://askubuntu.com/questions/1040474/warning-amdgpu-dkms-failed-for-running-kernel-on-both-16-04-18-04

Уточнение. Это работает только для драйверов версии  драйвера 18.Q#, 19.Q#, 20.Q#.
--------------------------------------------------

Авторы пишут, что нужна конкретная версия драйверов - 17.50-511655. Более новые драйверы могут сломать в OpenCL поддержку SPIR. Установка с предложенными параметрами добавляет поддержку только вычислительных задач на видеокарту. Если нужно ускорение графики, предлагается читать документацию.

3. Проверяем, что OpenCL установился:
$ sudo apt update
$ sudo apt install clinfo
$ clinfo

Программа clinfo, как следует из названия, показывает свойства OpenCL и видеокарт

4. Дальше предлагается поставить нужные пакеты для сборки. Но выполнив код в указанной последовательности, у меня не взлетело. Потому что по умолчанию будет использован pip для Python 2.7. А нам нужен Python 3.5. Поэтому выполняем команды
sudo apt update
sudo apt install git cmake gcc build-essential libpython3-all-dev ocl-icd-opencl-dev opencl-headers openjdk-8-jdk python3 python3-dev python3-pip zlib1g-dev

5. Проверяем версии Python и pip:
$ python -V
Python 2.7.17
$ python3 -V
Python 3.5.2
$ python3.5 -V
Python 3.5.2
$ pip -V
pip 9.0.1 from /usr/lib/python2.7/dist-packages (python 2.7)
$ pip3 -V
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.5)
$ pip3.5 -V
pip3.5: команда не найдена

И смотрим пути к ним:
$ which python
/usr/bin/python
$ which python3
/usr/bin/python3
$ which python3.5
/usr/bin/python3.5
$ which pip
/usr/bin/pip
$ which pip3
/usr/bin/pip3
$ which pip3.5
Назначаем пседонимы, рекомендация авторов:
$ alias python=python3.5
$ alias pip=pip3.5

В моем случае pip3.5 не существовало (выдавалась ошибка, что команда не найдена) и я использовал вариант:
$ alias python=python3
$ alias pip=pip3

Можно прописать полные пути:
$ alias python=/usr/bin/python3.5
$ alias pip=/usr/bin/pip3

Я сразу не проверил, если ли файл pip3.5. Поэтому при сборке Tensorflow у меня использовался pip (версия 2.7), а не pip3, и собранный пакет wheel не поставился. pip писал о несовместимости версий. Пришлось исправлять ошибку и пересобирать пакет Tensorflow (небыстрый процесс).

6. Необязательный, но рекомендуемый шаг. Добавить наши псевдонимы в настройки интерпретатора команд bash. Я так понял, что есть разные рекомендации, какой файл использовать для собственных настроек bash (~/.bash_profile, ~/.profile, ~/.bashrc или ~/.bash_aliase). Я остановился на ~/.bashrc. Открываем файл в редакторе:
$ nano ~/.bashrc

Добавляем псевдонимы:
alias python=/usr/bin/python3.5
alias pip=/usr/bin/pip3

Если я здесь не прав, и надо добавлять команды в другой файл, напишите, исправлю. 
7. Итак, теперь ставим пакеты для Python'a
$ pip install -U --user numpy==1.14.5 wheel==0.31.1 six==1.11.0 mock==2.0.0 enum34==1.1.6

8. Скачиваем ComputeCpp. Мое понимание такое. Есть стандартный высокоуровневый набор интерфейсов SYCL для запуска задач на устройствах с поддержкой OpenCL. Этот слой нужен для написания универсального кода, не зависящего от реализации OpenCL и используемого оборудования. ComputeCpp - это открытая реализация интерфейсов SYCL (которые тоже открытый стандарт).

Необходимо зарегистрироваться на сайте https://developer.codeplay.com/computecppce/latest/download. Затем скачать подходящий файл: Ubuntu 16.04 > 64bit > Latest computecpp-ce-*-ubuntu.16.04-64bit.tar.gz.

9. Распаковываем и ставим:
$ export CCPP_VERSION=1.3.0
$ tar -xf ComputeCpp-CE-${CCPP_VERSION}-Ubuntu.16.04-64bit.tar.gz

$ sudo mv ComputeCpp-CE-${CCPP_VERSION}-Ubuntu-16.04-x86_64 /usr/local/computecpp
$ export COMPUTECPP_TOOLKIT_PATH=/usr/local/computecpp
$ export LD_LIBRARY_PATH+=:/usr/local/computecpp/lib /usr/local
$ /computecpp/bin/computecpp_info

Команды export здесь и далее лучше продублировать в ~/.bashrc

Команда computecpp_info покажет найденные устройства (видеокарты). Если появилась ошибка "error while loading shared libraries: libOpenCL.so" (у меня такого не было), значит, не встал драйвер OpenCL. Если устройство "untested" (у меня так), то, значит, тестов с ним не проводилось, но работать, скорее всего будет.

10. Ставим Bazel. Это инструмент для сборки и тестирования ПО.
$ wget https://github.com/bazelbuild/bazel/releases/download/0.16.1/bazel_0.16.1-linux-x86_64.deb
$ sudo apt install -y ./bazel_0.16.1-linux-x86_64.deb bazel version

Авторы пишут, что unzip должен быть версии <= 6.0.0. У меня в Ubuntu как раз был 6.0.0.

Каждая версия Tensorflow привязана к версиям компилятора GCC, Python и Bazel. Таблица соответствия тут
https://www.tensorflow.org/install/source#tested_build_configurations
На момент написания статьи версия Tensorflow в репозитории http://github.com/codeplaysoftware/tensorflow (см. пункт 11) была 1.9. Соответствующая версия Bazel 0.11.0. Но в оригинальной статье предлагается использовать 0.16.0. Я вначале, не зная о таблице версий, скачал последний Bazel (2.2.0). Он сразу вывалился с ошибкой при попытке собрать Tensorflow. Версия 0.16.1 сборку осуществляет.

Страница со сборками различных версий:
https://github.com/bazelbuild/bazel/releases

Страница на сайте Bazel с инструкцией, как его ставить стандартным для Ubuntu методом (apt install):
https://docs.bazel.build/versions/master/install-ubuntu.html

11. И, наконец, добрались до TensorFlow. Качаем с GitHub
$ git clone http://github.com/codeplaysoftware/tensorflow
$ cd tensorflow

12. Экпортируем нужные переменные окружения:

$ export CC_OPT_FLAGS=-march=native
$ export PYTHON_BIN_PATH=/usr/bin/python3.5
$ export USE_DEFAULT_PYTHON_LIB_PATH=1
$ export TF_NEED_JEMALLOC=1
$ export TF_NEED_MKL=0
$ export TF_NEED_GCP=0
$ export TF_NEED_HDFS=0
$ export TF_ENABLE_XLA=0
$ export TF_NEED_CUDA=0
$ export TF_NEED_VERBS=0
$ export TF_NEED_MPI=0
$ export TF_NEED_GDR=0
$ export TF_NEED_AWS=0
$ export TF_NEED_S3=0
$ export TF_NEED_KAFKA=0
$ export TF_DOWNLOAD_CLANG=0
$ export TF_SET_ANDROID_WORKSPACE=0
$ export TF_NEED_OPENCL_SYCL=1
$ export TF_NEED_COMPUTECPP=1
$ export TF_SYCL_PRESET=AMD_GPU

У авторов оригинальной статьи один экспорт отличается
$ export PYTHON_BIN_PATH=/usr/bin/python

В моем случае, это привело к тому, что использовался python 2.7 вместо 3.5 (см. пункт 5).


Другие возможные значения - INTEL_GPU, ARM_GPU или POWER_VR.

В первоисточнике рассмотрены дополнительные необязательные параметры. Пока я ими не пользовался.

13. Сборка

$ ./configure
$ bazel build --verbose_failures --jobs=6 --config=sycl --config=opt //tensorflow/tools/pip_package:build_pip_package

Если меняли переменные окружения (export), то надо заново запускать ./configure. Авторы рекомендуют не менять значения переменных, чтобы пересборка не начиналась с нуля. Я не менял, но собиралось всё равно с нуля.

Параметр --jobs=X. Это количество потоков для сборки. У меня 16 ядер  = 2 процессора * 8 ядер (не проверял, включен ли гипертрединг). Когда поставил значение 16, сборка выпала с ошибкой. Когда поставил 14, всё заработало. Авторы пишут, что значение должно быть строго меньше количества потоков. Видимо, в моем случае можно поставить 15.

14. Установка. Директория, куда положится готовый пакет (любая существующая, можно и просто $HOME):

$ export TF_WHL_DIR=$HOME/tensorflow-amd
Сборка pip-пакета:
$ bazel-bin/tensorflow/tools/pip_package/build_pip_package $TF_WHL_DIR

Установка:$ pip install --user $TF_WHL_DIR/tensorflow-1.9.0-cp35-cp35m-linux_x86_64.whl

Внимание! В названии файла важны значения после "cp": tensorflow-1.9.0-cp35-cp35m-linux_x86_64.whl. Это версия Python'a. Из-за неверных путей к интерпретатору Python в переменных окружения у меня получился пакет tensorflow-1.9.0-cp27-cp27m-linux_x86_64.whl. И он не поставился. Пришлось пересобирать.

15. Ставим пакеты для Python'a

$ pip install -U --user numpy==1.14.5 wheel==0.31.1 six==1.11.0 mock==2.0.0 enum34==1.1.6 portpicker==1.2.0
$ pip install -U --user scipy==1.1.0
$ pip install -U --user scikit-learn==0.20.2
$ pip install -U --user --no-deps sklearn

16. Запуск теста на производительность:

$ git clone http://github.com/tensorflow/benchmarks
$ cd benchmarks
$ git checkout cnn_tf_v1.9_compatible
# Allow the SYCL device as a valid option
$ sed -i "s/'cpu', 'gpu'/'cpu', 'gpu', 'sycl'/"
 scripts/tf_cnn_benchmarks/benchmark_cnn.py
$ python scripts/tf_cnn_benchmarks/tf_cnn_benchmarks.py --num_batches=10 --local_parameter_device=sycl --device=sycl --batch_size=1 --forward_only=true --model=alexnet --data_format=NHWC

17. Запуск тестов. Полная версия

$ bazel test --test_lang_filters=cc,py --test_timeout 1500 --verbose_failures --jobs=1 --config=sycl --config=opt -- //tensorflow/... -//tensorflow/compiler/... -//tensorflow/contrib/distributions/... -//tensorflow/contrib/lite/... -//tensorflow/contrib/session_bundle/... -//tensorflow/contrib/slim/... -//tensorflow/contrib/verbs/... -//tensorflow/core/distributed_runtime/... -//tensorflow/core/kernels/hexagon/... -//tensorflow/go/... -//tensorflow/java/... -//tensorflow/python/debug/... -//tensorflow/stream_executor/...

Или сокращенная (только на Tensorflow)
$ bazel test --test_timeout 1500 --verbose_failures --jobs=1 --config=sycl --config=opt -- //tensorflow/python/kernel_tests/...

18. Полезные ссылки и другие полезности:
Руководство по Tensorflow 1.x. Проверка, что используеся  GPU.
https://github.com/tensorflow/docs/blob/master/site/en/r1/guide/using_gpu.md

Набор тестов для проверки, задействована ли  видеокарта. Надергал их из руководств и форумов:

import tensorflow as tf
print('----------------------------------------------------------')
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

print('----------------------------------------------------------')

with tf.device('/SYCL:0'):
    a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
    b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
    c = tf.matmul(a, b)

with tf.Session() as sess:
    print (sess.run(c))

print('----------------------------------------------------------')

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())

print('----------------------------------------------------------')
import tensorflow as tf
if tf.test.gpu_device_name():
    print('Default GPU Device: {}'.format(tf.test.gpu_device_name()))
else:
    print("Please install GPU version of TF")

print('----------------------------------------------------------')

Обратите внимание, наше устройство не "GPU:0", как указано во многих руководствах и советах, а "SYCL:0".

19. А может вам все эти мучения и не нужны? Ведь есть же AMD ROCm
Установка ROCm
https://github.com/RadeonOpenCompute/ROCm/blob/master/README.md#Machine-Learning-and-High-Performance-Computing-Software-Stack-for-AMD-GPU

Установка Tensorflow
https://rocm-documentation.readthedocs.io/en/latest/Deep_learning/Deep-learning.html?highlight=tensorflow#tensorflow-more-resources

 Вся просто, быстро и понятно... если ваша видеокарта поддерживается.
  • GFX8 GPUs
    • "Fiji" chips, such as on the AMD Radeon R9 Fury X and Radeon Instinct MI8
    • "Polaris 10" chips, such as on the AMD Radeon RX 580 and Radeon Instinct MI6
  • GFX9 GPUs
    • "Vega 10" chips, such as on the AMD Radeon RX Vega 64 and Radeon Instinct MI25
    • "Vega 7nm" chips, such as on the Radeon Instinct MI50, Radeon Instinct MI60 or AMD Radeon VII
  • GFX8 GPUs
    • "Polaris 11" chips, such as on the AMD Radeon RX 570 and Radeon Pro WX 4100
    • "Polaris 12" chips, such as on the AMD Radeon RX 550 and Radeon RX 540
  • GFX7 GPUs
    • "Hawaii" chips, such as the AMD Radeon R9 390X and FirePro W9100
 А если вам повезло так же как мне и у вас карты на базе
  • AMD "Carrizo" and "Bristol Ridge" APUs
  • AMD "Raven Ridge" APU
  • "Tonga", "Iceland", "Vega M", and "Vega 12" GPUs
то вам путь к пункту 1.

Статья редактируется по мере нахождения и исправления граблей.

Комментариев нет: