2019년 2월 22일 금요일

ppc64le 환경에서 tensorflow 1.12를 source로부터 build 하기


Tensorflow v1.12는 IBM PowerAI toolkit v1.5.4에 포함되어 있습니다.  그러나 그건 CUDA 10.0 환경을 위해 만들어진 것이라서, CUDA 9.2 환경을 그대로 쓰고자 하는 고객분들께서는 사용하실 수 없습니다.  하지만 github의 source code로부터 직접 build하시면 간단합니다.

제가 build한 환경은 Anaconda3 5.2 (python 3.6.8) + CUDA 9.2 + NCCL 2.2 + CUDNN 7.4.1 + Redhat 7.4 ppc64le 입니다. 

먼저 아래와 같이 기초적으로 필요한 OS package들을 yum으로 설치하십시요.

[bsyu@redhat74 files]$ which python
~/anaconda3/bin/python

[bsyu@redhat74 files]$ python
Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:38:54)
[GCC 7.2.0] on linux

[bsyu@redhat74 files]$ sudo yum install java-1.8.0-openjdk-devel.ppc64le zip unzip automake autoconf make gcc patch

[bsyu@redhat74 files]$ conda install protobuf wheel numpy six

Tensorflow v1.12 build를 위해서는 bazel v0.15 이상이 필요합니다.  Bazel v0.15를 bootstrap 방식으로 먼저 build합니다.  예전에는 ppc64le 환경에서 bazel을 build하는 것이 매우 힘들었는데, 이젠 x86_64 환경에서와 똑같이 그냥 build하시면 됩니다.

[bsyu@redhat74 files]$ wget https://github.com/bazelbuild/bazel/releases/download/0.15.0/bazel-0.15.0-dist.zip

[bsyu@redhat74 files]$ mkdir bazel-0.15 && cd bazel-0.15

[bsyu@redhat74 bazel-0.15]$ unzip ../bazel-0.15.0-dist.zip

[bsyu@redhat74 bazel-0.15]$ export EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk"

[bsyu@redhat74 bazel-0.15]$ export PROTOC=~/anaconda3/bin/protoc

[bsyu@redhat74 bazel-0.15]$ ./compile.sh
....
INFO: Build completed successfully, 2371 total actions
WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
Build successful! Binary is here: /home/bsyu/files/bazel-0.15/output/bazel

이제 bazel build가 완료되었습니다.  이렇게 만든 bazel 실행파일을 아래와 같이 /usr/local/bin에 옮겨놓고 쓰시면 됩니다.

[bsyu@redhat74 bazel-0.15]$ sudo cp output/bazel /usr/local/bin

그리고 tensorflow build에 들어가기 전에, 아래와 같이 cudnn.h의 soft link를 /usr/include 밑에 만들어 줍니다.  이것이 없으면 자꾸 cudnn.h를 못 찾는다는 error("Cannot find cudnn.h under /usr/local/cuda-9.2/targets/ppc64le-linux/lib")가 나니까, 그걸 막기 위한 것입니다. 

[bsyu@redhat74 files]$ sudo ln -s /usr/local/cuda/include/cudnn.h /usr/include/cudnn.h

이제 tensorflow source code를 받습니다.

[bsyu@redhat74 files]$ git clone https://github.com/tensorflow/tensorflow.git

[bsyu@redhat74 files]$ cd tensorflow/

우리가 원하는 버전인 v1.12.0으로 checkout 합니다.

[bsyu@redhat74 tensorflow]$ git checkout tags/v1.12.0

./configure를 수행하되, 다음 몇 줄 이외에는 모두 default 값을 쓰면 됩니다.

[bsyu@redhat74 tensorflow]$ ./configure

Do you wish to build TensorFlow with CUDA support? [y/N]: y
Please specify the CUDA SDK version you want to use. [Leave empty to default to CUDA 9.0]: 9.2
Please specify the location where cuDNN 7 library is installed. Refer to README.md for more details. [Default is /usr/local/cuda]: /usr/local/cuda/lib64
Please note that each additional compute capability significantly increases your build time and binary size. [Default is: 3.5,7.0]: 6.0,7.0

그리고 temp file을 쓸 directory를 별도로 지정해두기 위해 다음과 같이 환경변수 TMP를 넉넉한 disk 공간이 있는 directory로 지정해두는 것이 좋습니다.

[bsyu@redhat74 tensorflow]$ export TMP=/data/tmp

이제 bazel을 이용하여 tensorflow build에 들어갑니다.  이 과정은 시간이 오래 걸리니까 nohup & 을 쓰시는 것이 좋습니다.   그리고 의외로 system memory를 많이 잡아먹습니다.  저는 16GB memory가 있는 POWER8 가상머신에서 했는데, active memory를 거의 9GB 쓰는 것 같습니다.   4GB memory만 있는 가상머신에서 build하려니 killed 되던데, 아마 메모리 부족으로 죽는 것 같았어요.

[bsyu@redhat74 tensorflow]$ bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
...
INFO: Build completed successfully, 1180 total actions

성공적으로 완료되었습니다.  이제 wheel file을 생성합니다.

[bsyu@redhat74 tensorflow]$ ./bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
...
Fri Feb 22 22:05:17 KST 2019 : === Output wheel file is in: /tmp/tensorflow_pkg

이제 wheel file이 /tmp/tensorflow_pkg 밑에 생성되었습니다.   다음과 같이 확인합니다.

[bsyu@redhat74 tensorflow]$ ls -l /tmp/tensorflow_pkg
-rw-rw-r-- 1 bsyu bsyu 171252634 Feb 22 22:05 tensorflow-1.12.0-cp36-cp36m-linux_ppc64le.whl

이제 이 wheel file을 pip 명령으로 설치하면 됩니다.  이 과정 중에서 tensorflow에 필요한 grpcio 등의 python package들을 추가로 internet에서 download 하여 설치하므로, 만약 internet이 없는 환경이라면 intranet에 있는 PYPI repository에서 그런 package들을 download 할 수 있도록 설정이 필요합니다.

[bsyu@redhat74 tensorflow]$ pip install /tmp/tensorflow_pkg/tensorflow-1.12.0-cp36-cp36m-linux_ppc64le.whl

Processing /tmp/tensorflow_pkg/tensorflow-1.12.0-cp36-cp36m-linux_ppc64le.whl
Requirement already satisfied: numpy>=1.13.3 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorflow==1.12.0) (1.15.4)
Requirement already satisfied: keras-applications>=1.0.6 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorflow==1.12.0) (1.0.7)
Requirement already satisfied: keras-preprocessing>=1.0.5 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorflow==1.12.0) (1.0.9)
Requirement already satisfied: six>=1.10.0 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorflow==1.12.0) (1.12.0)
Requirement already satisfied: protobuf>=3.6.1 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorflow==1.12.0) (3.6.1)
Collecting termcolor>=1.1.0 (from tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/8a/48/a76be51647d0eb9f10e2a4511bf3ffb8cc1e6b14e9e4fab46173aa79f981/termcolor-1.1.0.tar.gz
Collecting astor>=0.6.0 (from tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/35/6b/11530768cac581a12952a2aad00e1526b89d242d0b9f59534ef6e6a1752f/astor-0.7.1-py2.py3-none-any.whl
Collecting grpcio>=1.8.6 (from tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/90/2e/f432e69f86961393c22a6c4490aafdbb94533deba33f5ea2d5651770aa21/grpcio-1.18.0.tar.gz (14.6MB)
    100% |████████████████████████████████| 14.6MB 3.4MB/s
Collecting absl-py>=0.1.6 (from tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/31/bc/ab68120d1d89ae23b694a55fe2aece2f91194313b71f9b05a80b32d3c24b/absl-py-0.7.0.tar.gz (96kB)
    100% |████████████████████████████████| 102kB 11.7MB/s
Collecting tensorboard<1.13.0,>=1.12.0 (from tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/07/53/8d32ce9471c18f8d99028b7cef2e5b39ea8765bd7ef250ca05b490880971/tensorboard-1.12.2-py3-none-any.whl (3.0MB)
    100% |████████████████████████████████| 3.1MB 8.6MB/s
Collecting gast>=0.2.0 (from tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/4e/35/11749bf99b2d4e3cceb4d55ca22590b0d7c2c62b9de38ac4a4a7f4687421/gast-0.2.2.tar.gz
Requirement already satisfied: wheel>=0.26 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorflow==1.12.0) (0.32.3)
Requirement already satisfied: h5py in /home/bsyu/anaconda3/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow==1.12.0) (2.7.1)
Requirement already satisfied: setuptools in /home/bsyu/anaconda3/lib/python3.6/site-packages (from protobuf>=3.6.1->tensorflow==1.12.0) (39.1.0)
Requirement already satisfied: werkzeug>=0.11.10 in /home/bsyu/anaconda3/lib/python3.6/site-packages (from tensorboard<1.13.0,>=1.12.0->tensorflow==1.12.0) (0.12.2)
Collecting markdown>=2.6.8 (from tensorboard<1.13.0,>=1.12.0->tensorflow==1.12.0)
  Downloading https://files.pythonhosted.org/packages/7a/6b/5600647404ba15545ec37d2f7f58844d690baf2f81f3a60b862e48f29287/Markdown-3.0.1-py2.py3-none-any.whl (89kB)
    100% |████████████████████████████████| 92kB 14.6MB/s
Building wheels for collected packages: termcolor, grpcio, absl-py, gast
  Running setup.py bdist_wheel for termcolor ... done
  Stored in directory: /home/bsyu/.cache/pip/wheels/7c/06/54/bc84598ba1daf8f970247f550b175aaaee85f68b4b0c5ab2c6
  Running setup.py bdist_wheel for grpcio ... done
  Stored in directory: /home/bsyu/.cache/pip/wheels/e5/22/5a/fa5c03beb66ecc2658e73673175e748ac37385614d52430877
  Running setup.py bdist_wheel for absl-py ... done
  Stored in directory: /home/bsyu/.cache/pip/wheels/90/db/f8/2c3101f72ef1ad434e4662853174126ce30201a3e163dcbeca
  Running setup.py bdist_wheel for gast ... done
  Stored in directory: /home/bsyu/.cache/pip/wheels/5c/2e/7e/a1d4d4fcebe6c381f378ce7743a3ced3699feb89bcfbdadadd
Successfully built termcolor grpcio absl-py gast
jupyter 1.0.0 requires qtconsole, which is not installed.
distributed 1.21.8 requires msgpack, which is not installed.
gevent 1.3.0 has requirement greenlet>=0.4.13, but you'll have greenlet 0.4.12 which is incompatible.
Installing collected packages: termcolor, astor, grpcio, absl-py, markdown, tensorboard, gast, tensorflow
Successfully installed absl-py-0.7.0 astor-0.7.1 gast-0.2.2 grpcio-1.18.0 markdown-3.0.1 tensorboard-1.12.2 tensorflow-1.12.0 termcolor-1.1.0

이제 보시는 바와 같이 tensorflow가 설치되었습니다.

[bsyu@redhat74 tensorflow]$ pip list | grep tensor
tensorboard                        1.12.2
tensorflow                         1.12.0

이걸 GPU가 있는 서버에서 테스트하는 방법은 다음과 같습니다.

[bsyu@redhat74 tensorflow]$ cd ..

[bsyu@redhat74 files]$ python
Python 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:34:02)
[GCC 7.3.0] on linux

>>> import tensorflow as tf
/home/bsyu/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters

>>> sess=tf.Session()
2019-02-22 22:14:15.250972: E tensorflow/stream_executor/cuda/cuda_driver.cc:300] failed call to cuInit: CUDA_ERROR_UNKNOWN: unknown error
2019-02-22 22:14:15.251021: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:150] kernel driver does not appear to be running on this host (redhat74): /proc/driver/nvidia/version does not exist

제가 GPU가 없는 서버에서 이걸 수행했기 때문에 위에서는 error가 났습니다만, GPU가 장착된 서버에서는 error가 없어야 하고 nvidia-smi로 보았을 때 python이 GPU를 점거하는 것으로 보일 것입니다.

여기서 build된 tensorflow wheel 파일과 site-packages directory 전체를 tar로 말아서 아래의 google drive에 올려두겠습니다.

tensorflow wheel 파일 : https://drive.google.com/open?id=1plqSuw9WnWuOPJCPEiVYSp3uK3IilQMy

CUDA 9.2의 AC922 서버에 tensorflow 1.12.0 설치하기


IBM POWER9 processor 기반의 GPU서버인 AC922을 2018년에 도입하셨던 고객분들은 대개 CUDA 9.2를 사용하고 계실 것입니다.  이 상황에서 아래와 같이 tensorflow를 포함한 기존 python package들의 버전을 올려야 하는 필요성이 있을 수 있습니다.

변경전
pandas 0.23.4  --> 0.24.0
tensorflow 1.8.0  --> 1.12.0
keras 2.2.2  --> 2.2.4
numpy 1.15.2  --> 1.16.1
scikit-learn 0.20.0  --> 0.20.2
scipy 1.0.0  --> 1.2.0

이게 가능할까요 ?  예 물론 가능합니다.  AC922 서버가 인터넷에 연결되어 있거나, 또는 사내 intranet에 PYPI (python repository) mirror본이 구성되어 있다면 쉽습니다.  (Tensorflow를 제외한 나머지 package들은) 아래와 같이 pip install --upgrade 명령을 통해 간단히 수행됩니다.

$ pip install --upgrade pandas==0.24.0
$ pip install --upgrade keras==2.2.4
$ pip install --upgrade numpy==1.16.1
$ pip install --upgrade scikit-learn==0.20.2
$ pip install --upgrade scipy==1.2.0

예를 들어 numpy는 아래와 같이 upgrade 됩니다.  설치 과정 때 nmon으로 시스템 모니터링을 해보면 cc1 (compiler)가 CPU를 열심히 쓰고 있는 것을 보실 수 있습니다.

[u0017649@sys-97058 files]$ pip install --upgrade numpy==1.16.1
Collecting numpy==1.16.1
  Downloading https://files.pythonhosted.org/packages/2b/26/07472b0de91851b6656cbc86e2f0d5d3a3128e7580f23295ef58b6862d6c/numpy-1.16.1.zip (5.1MB)
    100% |????????????????????????????????| 5.1MB 3.7MB/s
Building wheels for collected packages: numpy
  Running setup.py bdist_wheel for numpy ... done
  Stored in directory: /home/u0017649/.cache/pip/wheels/04/64/e1/283a3672c2865608968594c02a6923311f44d033bcece2683b
Successfully built numpy
jupyter 1.0.0 requires qtconsole, which is not installed.
distributed 1.21.8 requires msgpack, which is not installed.
gevent 1.3.0 has requirement greenlet>=0.4.13, but you'll have greenlet 0.4.12 which is incompatible.
Installing collected packages: numpy
  Found existing installation: numpy 1.13.3
    Uninstalling numpy-1.13.3:
      Successfully uninstalled numpy-1.13.3
Successfully installed numpy-1.16.1
You are using pip version 10.0.1, however version 19.0.2 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.


문제는 tensorflow입니다.  Tensorflow는 불행히도 아직 1.12 버전이 ppc64le 아키텍처 상에서는 PYPI로부터는 pip로 설치가 안 됩니다.  하지만 이것도 큰 문제는 아닙니다.  Tensorflow는 open source니까, 그냥 github에서 source code를 받아서 직접 build하시면 됩니다.

원래 IBM은 작년 11월에 나온 PowerAI toolkit v1.5.4에서 tensorflow 1.12를 지원합니다.  그러나 이 PowerAI v1.5.4는 CUDA 10.0을 필요로 합니다.  따라서 이 PowerAI v1.5.4에 포함된 tensorflow를 쓰시려면 기존의 CUDA 9.2 환경을 뒤집어 엎고 CUDA 10.0으로 upgrade를 하셔야 합니다.  이건 기존에 쓰시던 다른 python package들과도 연관되는 일이니 그렇게 간단히 진행하실 일은 아니지요.

그래서 제가 tensorflow v1.12를 Redhat 7.4 ppc64le 플랫폼에서 python 3.6.8 + CUDA 9.2 환경용으로 build했고, 그 wheel file을 아래 google drive에 올려놓았습니다.  제가 가난하여 GPU 서버가 없는지라 test된 것은 아니라는 점은 양해 부탁드립니다. 

tensorflow v1.12 wheel file  --> https://drive.google.com/open?id=1plqSuw9WnWuOPJCPEiVYSp3uK3IilQMy

위의 wheel file을 download 받아서 아래 명령으로 설치하시면 됩니다.

[u0017649@sys-97058 files]$ pip install /tmp/tensorflow-1.12.0-cp36-cp36m-linux_ppc64le.whl

단 위의 tensorflow-*.whl 파일을 설치하실 때 pip가 termcolor, astor, grpcio 등의 필요 python package들을 추가로 internet에서 download하여 설치하므로, 만약 internet이 없는 환경이라면 intranet에 있는 PYPI repository에서 그런 package들을 download 할 수 있도록 설정이 필요하다는 점 유의하십시요.

설치가 끝난 뒤 확인하는 방법은 다음과 같습니다.

[bsyu@redhat74 tensorflow]$ pip list | grep tensor
tensorboard                        1.12.2
tensorflow                         1.12.0

[bsyu@redhat74 files]$ python
Python 3.6.8 |Anaconda, Inc.| (default, Dec 30 2018, 01:34:02)
[GCC 7.3.0] on linux

>>> import tensorflow as tf
/home/bsyu/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters

>>> sess=tf.Session()
2019-02-22 22:14:15.250972: E tensorflow/stream_executor/cuda/cuda_driver.cc:300] failed call to cuInit: CUDA_ERROR_UNKNOWN: unknown error
2019-02-22 22:14:15.251021: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:150] kernel driver does not appear to be running on this host (redhat74): /proc/driver/nvidia/version does not exist

제가 GPU가 없는 서버에서 이걸 수행했기 때문에 위에서는 error가 났습니다만, GPU가 장착된 서버에서는 error가 없어야 하고 nvidia-smi로 보았을 때 python이 GPU를 점거하는 것으로 보일 것입니다.


PS1.  혹시 위의 wheel file 설치가 무슨 이유로든 잘 안 될 경우에 대비하여, 최후의 수단으로 tensorflow 및 위에 언급된 버전의 전체 python package들을 포함한 anaconda3 directory 전체를 tar로 말아서 아래의 google drive에 올려두겠습니다.

anaconda3 directory 전체의 tarball : https://drive.google.com/open?id=1vnmi8t2L_XKgRqfhQbBQbJgjVU7vNGav

위의 anaconda3_tf1.12.tgz를 다음과 같이 기존 anaconda3 directory 위치 또는 $HOME 밑에서 풀어놓으면 됩니다.  기존의 anaconda3 directory는 mv 명령으로 잠시 다른 이름으로 바꿔 놓으셨다가, 혹시 이 새로운 anaconda3가 정상 작동하지 않을 경우 다시 원복시키시기를 권고드립니다.

[root@sys-97264 opt]# ls
anaconda3   at11.0  ibm

[root@sys-97264 opt]# tar -zcpsf opt_anaconda3_tf1.12.tgz ./anaconda3


이 opt_anaconda3_tf1.12.tgz를 다른 서버에 올려놓은 뒤에 풀어놓아 보았습니다.  먼저 기존 anaconda3를 다른 이름으로 바꿔놓습니다.

[root@sys-97269 ~]# cd /opt

[root@sys-97269 ~]# mv anaconda3 anaconda3_org

[root@sys-97269 opt]# tar -zxvpsf /tmp/opt_anaconda3_tf1.12.tgz

[root@sys-97269 opt]# which python
/opt/anaconda3/bin/python

아래와 같이 잘 작동하는 것을 보실 수 있습니다.

[root@sys-97269 opt]# pip list | egrep 'pandas|Keras|numpy|scikit-learn|scipy|tensorflow'
Keras                              2.2.4
Keras-Applications                 1.0.7
Keras-Preprocessing                1.0.9
numpy                              1.16.1
numpydoc                           0.8.0
pandas                             0.24.0
scikit-learn                       0.20.2
scipy                              1.2.0
tensorflow                         1.12.0

[root@sys-97269 opt]# cd
[root@sys-97269 ~]# which python
/opt/anaconda3/bin/python

[root@sys-97269 ~]# python
Python 3.6.5 |Anaconda, Inc.| (default, Apr 29 2018, 16:38:54)
[GCC 7.2.0] on linux

>>> import keras
/opt/anaconda3/lib/python3.6/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
Using TensorFlow backend.
>>> import numpy
>>> import pandas
>>> import tensorflow
>>>


PS2.  혹시 위의 anaconda3 directory를 통째로 풀어놓는 것이 무슨 이유에서든 잘 안될 경우에 대비해서, 아래 site에 해당 tensorflow 등의 pacakge들을 모두 갖춘 CUDA 9.2를 설치한 Redhat 7.5 ppc64le 기반의 docker image를 올려놓았습니다.

https://hub.docker.com/r/bsyu/rhel75_ppc64le_cuda92_tf1.12_py3

다음과 같이 받아서 사용하시면 됩니다.

[u0017649@sys-97269 ~]$ sudo docker pull bsyu/rhel75_ppc64le_cuda92_tf1.12_py3:v0.2