2018년 7월 26일 목요일

ppc64le에서 xgboost4j build하기

먼저 http://hwengineer.blogspot.com/2018/07/ppc64le-pyarrow-wheel-build.html 의 안내에 따라 pyarrow를 설치해야 합니다.  그 다음에 xgboost의 source를 받습니다. 

[root@ING data]# git clone -b h2oai  https://github.com/h2oai/xgboost.git
Cloning into 'xgboost'...
remote: Counting objects: 25961, done.
remote: Compressing objects: 100% (86/86), done.
remote: Total 25961 (delta 83), reused 78 (delta 45), pack-reused 25828
Receiving objects: 100% (25961/25961), 9.44 MiB | 4.67 MiB/s, done.
Resolving deltas: 100% (15316/15316), done.

[root@ING data]# cd xgboost

[root@ING xgboost]# git submodule init
Submodule 'cub' (https://github.com/NVlabs/cub) registered for path 'cub'
Submodule 'dmlc-core' (https://github.com/dmlc/dmlc-core) registered for path 'dmlc-core'
Submodule 'rabit' (https://github.com/dmlc/rabit) registered for path 'rabit'

[root@ING xgboost]# git submodule update --recursive
Cloning into 'cub'...
remote: Counting objects: 32642, done.
remote: Total 32642 (delta 0), reused 0 (delta 0), pack-reused 32642
Receiving objects: 100% (32642/32642), 16.46 MiB | 6.82 MiB/s, done.
Resolving deltas: 100% (28620/28620), done.
Submodule path 'cub': checked out 'b20808b1b04ec3d6a625e51fbc1eb76f337754ad'
Cloning into 'dmlc-core'...
remote: Counting objects: 4975, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 4975 (delta 7), reused 9 (delta 2), pack-reused 4952
Receiving objects: 100% (4975/4975), 1.22 MiB | 1.44 MiB/s, done.
Resolving deltas: 100% (2976/2976), done.
Submodule path 'dmlc-core': checked out '459ab734d15acd68fd437abf845c7c1730b5a38f'
Cloning into 'rabit'...
remote: Counting objects: 3174, done.
remote: Total 3174 (delta 0), reused 0 (delta 0), pack-reused 3173
Receiving objects: 100% (3174/3174), 905.56 KiB | 378.00 KiB/s, done.
Resolving deltas: 100% (2058/2058), done.
Submodule path 'rabit': checked out '87143deb4c0a34302f727ba35497e3380b2cced8'

처음에 해줄 것은 build.sh 수행, 그 다음에 make -f Makefile2 libxgboost 입니다.  여기까지 해주면 xgboost의 wheel 파일이 build 됩니다.  그 다음에 jvm-packages에 들어가서 create_jni.py를 수행하여 libxgboost4j.so를 만들어 줍니다.

[root@ING xgboost]# ./build.sh
...
build/linear/updater_coordinate.o dmlc-core/libdmlc.a rabit/lib/librabit.a  -pthread -lm  -fopenmp -lrt  -lrt
Successfully build multi-thread xgboost


[root@ING xgboost]# make -f Makefile2 libxgboost
...
copying build/lib/xgboost/build-python.sh -> build/bdist.linux-ppc64le/wheel/xgboost
copying build/lib/xgboost/libxgboost.so -> build/bdist.linux-ppc64le/wheel/xgboost
running install_egg_info
Copying xgboost.egg-info to build/bdist.linux-ppc64le/wheel/xgboost-0.72-py3.6.egg-info
running install_scripts
creating build/bdist.linux-ppc64le/wheel/xgboost-0.72.dist-info/WHEEL

[root@ING xgboost]# ls -l ./python-package/dist/xgboost-0.72-py3-none-any.whl
-rw-r--r-- 1 root root 77640590 Jul 23 14:52 ./python-package/dist/xgboost-0.72-py3-none-any.whl

[root@ING xgboost]# pip install ./python-package/dist/xgboost-0.72-py3-none-any.whl

[root@ING xgboost]# cd jvm-packages

[root@ING jvm-packages]# python create_jni.py
...
[100%] Linking CXX shared library ../lib/libxgboost4j.so
[100%] Built target xgboost4j
cd demo/regression
/root/anaconda3/bin/python mapfeat.py
/root/anaconda3/bin/python mknfold.py machine.txt 1
copying native library
mkdir -p xgboost4j/src/main/resources/lib
cp ../lib/libxgboost4j.so xgboost4j/src/main/resources/lib
copying pure-Python tracker
cp ../dmlc-core/tracker/dmlc_tracker/tracker.py xgboost4j/src/main/resources
copying train/test files
mkdir -p xgboost4j-spark/src/test/resources
cd ../demo/regression
/root/anaconda3/bin/python mapfeat.py
/root/anaconda3/bin/python mknfold.py machine.txt 1
cp ../demo/regression/machine.txt.train xgboost4j-spark/src/test/resources
cp ../demo/regression/machine.txt.test xgboost4j-spark/src/test/resources
cp ../demo/data/agaricus.txt.test xgboost4j-spark/src/test/resources
cp ../demo/data/agaricus.txt.train xgboost4j-spark/src/test/resources

[root@ING jvm-packages]# ls -l ./xgboost4j/src/main/resources/lib/libxgboost4j.so
-rwxr-xr-x 1 root root 158562656 Jul 23 15:49 ./xgboost4j/src/main/resources/lib/libxgboost4j.so

[root@ING jvm-packages]# file ./xgboost4j/src/main/resources/lib/libxgboost4j.so
./xgboost4j/src/main/resources/lib/libxgboost4j.so: ELF 64-bit LSB shared object, 64-bit PowerPC or cisco 7500, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=510aede1975d463804199edd1b74457b8e48c4f8, not stripped

위에서 생성된 libxgboost4j.so을 h2o.jar에 lib/linux64/libxgboost4j_gpu.so라는 이름으로 update해주면 됩니다.

$ mkdir -p lib/linux64

$ cp ./xgboost4j/src/main/resources/lib/libxgboost4j.so lib/linux64/libxgboost4j.so

$ jar uf h2o.jar lib/linux64/libxgboost4j.so

------------------------------

아래는 위의 build하는 과정에서 만났던 몇가지 error 및 그 회피 방법입니다.

[root@ING xgboost]# make -f Makefile2 libxgboost
...
Collecting jmespath<1.0.0,>=0.7.1 (from botocore==1.10.62->awscli>=1.11.148->-r requirements_runtime.txt (line 74))
  Using cached https://files.pythonhosted.org/packages/b7/31/05c8d001f7f87f0f07289a5fc0fc3832e9a57f2dbd4d3b0fee70e0d51365/jmespath-0.9.3-py2.py3-none-any.whl
recommonmark 0.4.0 has requirement commonmark<=0.5.4, but you'll have commonmark 0.7.5 which is incompatible.
Installing collected packages: html5lib, bleach, execnet, qtconsole, tabulate, testpath, pyasn1, rsa, jmespath, botocore, s3transfer, awscli, feather-format, graphviz
  Found existing installation: html5lib 0.9999999
Cannot uninstall 'html5lib'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.
make: *** [libxgboostp2nccl] Error 1


[root@ING xgboost]# rm -rf /root/anaconda3/lib/python3.6/site-packages/html5lib*

[root@ING xgboost]# make -f Makefile2 libxgboost
...
Installing collected packages: testpath, jmespath, botocore, pyasn1, rsa, s3transfer, awscli, feather-format, graphviz
Successfully installed awscli-1.15.63 botocore-1.10.62 feather-format-0.4.0 graphviz-0.8.4 jmespath-0.9.3 pyasn1-0.4.3 rsa-3.4.2 s3transfer-0.1.13 testpath-0.3.1
pip install -r requirements_build.txt
Could not open requirements file: [Errno 2] No such file or directory: 'requirements_build.txt'
make: *** [libxgboostp2nccl] Error 1

[root@ING xgboost]# find . -name "requirement*.txt"
./doc/requirements.txt
./requirements_buildonly.txt
./requirements_runtime.txt


[root@ING xgboost]# cp ./requirements_buildonly.txt ./requirements_build.txt

[root@ING xgboost]# make -f Makefile2 libxgboost
...
Collecting cmake>=0.8.0 (from -r requirements_build.txt (line 9))
  Cache entry deserialization failed, entry ignored
  Downloading https://files.pythonhosted.org/packages/79/06/e89052a7e65ab765bc5e279542853d043ec857e61f253973c05a80f2490f/cmake-3.11.4.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-cu87aoqb/cmake/setup.py", line 7, in <module>
        from skbuild import setup
    ModuleNotFoundError: No module named 'skbuild'

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-cu87aoqb/cmake/
make: *** [libxgboostp2nccl] Error 1


[root@ING xgboost]# vi requirements_build.txt
#cmake>=0.8.0



ppc64le 환경에서 pyarrow wheel 파일 build하기

h2o 및 h2o4gpu를 open source로부터 build하려면 xgboost4j_gpu.so가 필요합니다.  그런데 그걸 build하려면 또 pyarrow가 필요하지요.  하지만, ppc64le 아키텍처에서 pyarrow를 설치하려면 다음과 같이 error가 나는 것을 보셨을 것입니다.

$ pip install pyarrow
Collecting pyarrow
Using cached https://files.pythonhosted.org/packages/be/2d/11751c477e4e7f4bb07ac7584aafabe0d0608c170e4bff67246d695ebdbe/pyarrow-0.9.0.tar.gz
...
[ 66%] Building CXX object CMakeFiles/lib.dir/lib.cxx.o
/tmp/pip-install-kil31a/pyarrow/build/temp.linux-ppc64le-2.7/lib.cxx:592:35: fatal error: arrow/python/platform.h: No such file or directory
#include "arrow/python/platform.h"
^
compilation terminated.
make[2]: *** [CMakeFiles/lib.dir/lib.cxx.o] Error 1
make[1]: *** [CMakeFiles/lib.dir/all] Error 2
make: *** [all] Error 2
error: command 'make' failed with exit status 2

이 문제에 대해서 최근에 arrow community 도움을 받아 해결을 했습니다.

https://github.com/apache/arrow/issues/2281

좀더 간단하게는 다음과 같이 정리할 수 있습니다.

먼저, Redhat에서는 다음과 같이 사전 필요 fileset들을 설치합니다.

[dhkim@ING ~]$ sudo yum install jemalloc jemalloc-devel boost boost-devel flex flex-devel bison bison-devel

[dhkim@ING ~]$ mkdir imsi
[dhkim@ING ~]$ cd imsi

이 error를 해결하는 핵심은 먼저 arrow와 parquet-cpp를 source에서 build 하는 것입니다.

[dhkim@ING imsi]$ git clone https://github.com/apache/arrow.git

[dhkim@ING imsi]$ git clone https://github.com/apache/parquet-cpp.git

[dhkim@ING imsi]$ which python
~/anaconda2/bin/python

여기서는 anaconda2를 사용하는데, anaconda3도 동일하게 build할 수 있습니다.  먼저 conda 명령어로 다음과 같은 package들을 설치합니다.

[dhkim@ING imsi]$ conda install numpy six setuptools cython pandas pytest cmake flatbuffers rapidjson boost-cpp thrift snappy zlib gflags brotli lz4-c zstd -c conda-forge

여기서는 user home directory 밑에 dist라는 directory에 arrow와 parquet-cpp를 설치하겠습니다.

[dhkim@ING imsi]$ mkdir dist
[dhkim@ING imsi]$ export ARROW_BUILD_TYPE=release
[dhkim@ING imsi]$ export ARROW_HOME=$(pwd)/dist
[dhkim@ING imsi]$ export PARQUET_HOME=$(pwd)/dist

[dhkim@ING imsi]$ mkdir arrow/cpp/build && cd arrow/cpp/build

[dhkim@ING build]$ cmake3 -DCMAKE_BUILD_TYPE=$ARROW_BUILD_TYPE -DCMAKE_INSTALL_PREFIX=$ARROW_HOME  -DARROW_PYTHON=on -DARROW_PLASMA=on -DARROW_BUILD_TESTS=OFF  -DARROW_PARQUET=ON ..

[dhkim@ING build]$ make -j 8

[dhkim@ING build]$ make install
...
-- Installing: /home/dhkim/imsi/dist/include/arrow/python/platform.h
-- Installing: /home/dhkim/imsi/dist/include/arrow/python/pyarrow.h
-- Installing: /home/dhkim/imsi/dist/include/arrow/python/type_traits.h
-- Installing: /home/dhkim/imsi/dist/lib64/pkgconfig/arrow-python.pc

[dhkim@ING build]$ cd ~/imsi/arrow/python

[dhkim@ING python]$ MAKEFLAGS=-j8 ARROW_HOME=/home/dhkim/imsi/dist PARQUET_HOME=/home/dhkim/imsi/dist python setup.py build_ext --build-type=$ARROW_BUILD_TYPE --with-parquet --inplace

[dhkim@ING python]$ export LD_LIBRARY_PATH=/home/dhkim/imsi/dist/lib64:$LD_LIBRARY_PATH

이제 pyarrow를 build할 준비가 끝났습니다.  다만, arrow 쪽의 사소한 bug로 인해, 다음과 같이 끝에 점(.)이 달린 *.so. 라는 soft link들을 만들어주어야 합니다.

[dhkim@ING python]$ ln -s /home/dhkim/imsi/dist/lib64/libarrow_python.so.11.0.0 /home/dhkim/imsi/dist/lib64/libarrow_python.so.
[dhkim@ING python]$ ln -s /home/dhkim/imsi/dist/lib64/libarrow.so.11.0.0 /home/dhkim/imsi/dist/lib64/libarrow.so.
[dhkim@ING python]$ ln -s /home/dhkim/imsi/dist/lib64/libparquet.so.1.4.1 /home/dhkim/imsi/dist/lib64/libparquet.so.

이제 wheel file을 build 합니다.

[dhkim@ING python]$ python setup.py build_ext --build-type=release --with-parquet --bundle-arrow-cpp bdist_wheel

다음과 같이 dist directory 밑에 만들어집니다.

[dhkim@ING python]$ ls -l dist/pyarrow-0.10.1.dev687+g18a61f6-cp36-cp36m-linux_ppc64le.whl
-rw-rw-r-- 1 dhkim dhkim 7195829 Jul 26 16:03 dist/pyarrow-0.10.1.dev687+g18a61f6-cp36-cp36m-linux_ppc64le.whl

이걸 pip로 설치하고, import까지 잘 되는 것을 확인하실 수 있습니다.

[dhkim@ING python]$ pip install dist/pyarrow-0.10.1.dev687+g18a61f6-cp36-cp36m-linux_ppc64le.whl

[dhkim@ING python]$ pip list | grep pyarrow
pyarrow                           0.10.1.dev687+g18a61f6

[dhkim@ING python]$ python
Python 2.7.15 |Anaconda, Inc.| (default, May  1 2018, 23:32:32)
[GCC 7.2.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyarrow
>>>

이 과정 안 겪으셔도 되도록, 아래에 pyarrow의 python2.7용 whl과 python3.6용 whl을 google drive에 올려두겠습니다.


python3.6용 wheel


For some gentlemen who got errors like "ImportError: libarrow.so.10: cannot open shared object file: No such file or directory" from the wheel file I uploaded here...

What we need is just perseverance.


1.  First, you need to install the pyarrow*.whl in my blog, and then...

2.  Make soft links as needed.  My wheel file places awkward names like "libarrow.so." due to a bug of https://github.com/apache/arrow/issues/2281 .

[u0017649@sys-96013 pyarrow]$ ln -s /home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/libarrow.so. /home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/libarrow.so.10

[u0017649@sys-96013 ~]$ ln -s /home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/libarrow_python.so. /home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/libarrow_python.so.10

[u0017649@sys-96013 ~]$ ln -s /home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/libplasma.so. /home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/libplasma.so.10

3. Still you might get some more errors.  These will be addressed by installing OS packages. 

ImportError: libboost_system-mt.so.1.53.0: cannot open shared object file: No such file or directory
ImportError: libboost_filesystem-mt.so.1.53.0: cannot open shared object file: No such file or directory

[u0017649@sys-96013 ~]$ sudo yum install boost-system

[u0017649@sys-96013 ~]$ sudo yum install boost-filesystem

[u0017649@sys-96013 ~]$ sudo yum install boost-regex

4. You might and might not get the following weird error.  This can be addressed by upgrading numpy.  Pls refer to
https://issues.apache.org/jira/browse/ARROW-3141 .

>>> import pyarrow
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/u0017649/anaconda3/lib/python3.6/site-packages/pyarrow/__init__.py", line 50, in <module>
    import pyarrow.compat as compat
AttributeError: module 'pyarrow' has no attribute 'compat'


[u0017649@sys-96013 ~]$ pip install numpy --upgrade
Collecting numpy
  Downloading https://files.pythonhosted.org/packages/2d/80/1809de155bad674b494248bcfca0e49eb4c5d8bee58f26fe7a0dd45029e2/numpy-1.15.4.zip (4.5MB)
    100% |████████████████████████████████| 4.5MB 271kB/s
Building wheels for collected packages: numpy
  Running setup.py bdist_wheel for numpy ... done
  Stored in directory: /home/u0017649/.cache/pip/wheels/13/6b/70/4b5d7861227307f91716c31698240e08c6ec5486d9ee82a97b
Successfully built numpy
Installing collected packages: numpy
  Found existing installation: numpy 1.13.1
    Uninstalling numpy-1.13.1:
      Successfully uninstalled numpy-1.13.1
Successfully installed numpy-1.15.4


5.  And finally, Voila !

[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pyarrow
>>>



2018년 7월 13일 금요일

Redhat 7.5 ppc64le에서 CRAN-R을 source로부터 설치하기


전에 Ubuntu 16.04 ppc64le에서 CRAN-R을 설치하는 과정을 올린 바 있습니다만, 이번에는 Redhat의 경우입니다.   대부분의 과정은 비슷합니다.

먼저, Redhat EPEL에 포함된 R은 3.5 버전입니다.  이걸 쓰셔도 된다면 그냥 이걸 설치하시는 것이 편합니다. 

[root@ING ~]# yum list | grep R-core
R-core.ppc64le                      3.5.0-1.el7         epel
R-core-devel.ppc64le                3.5.0-1.el7         epel


그러나 특정 버전, 가령 3.4.1을 설치하시려면 다음과 같이 CRAN에서 source를 받아다 설치하시면 됩니다.   먼저 기존에 설치된 R 3.5 버전을 다음과 같이 삭제합니다.

[root@ING ~]# yum erase R R-core R-core-devel R-devel R-java R-java-devel libticonv-devel

이어서 기본적으로 필요한 OS package들을 설치합니다.

[root@ING test]# yum install readline-devel readline-static libX11-devel libX11-common libXt-devel libXt bzip2 bzip2-libs bzip2-devel lzma-sdk-devel lzma-sdk457-devel pcre2-devel pcre3-devel gcc-gfortran libgfortran libcurl-devel curl texlive-latex texlive-latex-fonts texlive-txfonts texlive-pxfonts texlive-fontaxes java-1.8.0-openjdk java-1.8.0-openjdk-devel java-1.8.0-openjdk-headless

이제 source를 download 받습니다.

[root@ING test]# wget https://cran.r-project.org/src/base/R-3/R-3.4.1.tar.gz

[root@ING test]# tar -zxf R-3.4.1.tar.gz

[root@ING test]# cd R-3.4.1

Build 순서는 똑같습니다.  configure - make - make install 순입니다.

[root@ING R-3.4.1]# ./configure --enable-R-shlib

[root@ING R-3.4.1]# make -j 16

[root@ING R-3.4.1]# make install

이렇게 설치하면 기본적으로 /usr/local/lib64/R 밑에 설치됩니다.

[root@ING R]# pwd
/usr/local/lib64/R

[root@ING R]# ls
bin  COPYING  doc  etc  include  lib  library  modules  share  SVN-REVISION

그러나 별도로 PATH를 잡아주지 않아도 이미 /usr/local/bin에 R이 copy되어 있으므로 그냥 그대로 쓰시면 됩니다.

[root@ING ~]# which R
/usr/local/bin/R

[root@ING ~]# R

R version 3.4.1 (2017-06-30) -- "Single Candle"
Copyright (C) 2017 The R Foundation for Statistical Computing
Platform: powerpc64le-unknown-linux-gnu (64-bit)
...
Type 'q()' to quit R.

> install.packages("knitr")

> install.packages("anim.plots")



*  저같은 경우 ./configure --enable-R-shlib 수행시 처음에는 아래와 같은 error가 발생했습니다.

configure: error: libcurl >= 7.22.0 library and headers are required with support for https

그러나 실제로 보면 아래처럼 libcurl은 이미 7.29 버전이 설치되어 있습니다.

[root@ING R-3.4.1]# yum list | grep libcurl
libcurl.ppc64le                     7.29.0-46.el7       @anaconda/7.5
libcurl-devel.ppc64le               7.29.0-46.el7       @rhel-7-for-power-9-rpms

이 error의 원인은 다음과 같이 config.log를 뒤져보면 알 수 있습니다.  즉, 환경 설정에서 PATH 변수 맨 앞에 anaconda2가 오도록 되어 있었는데, anaconda2 속에 설치된 libcurl의 버전이 낮은 것이 원인이었습니다.


[root@ING R-3.4.1]# env | grep PATH
PATH=/opt/anaconda2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/opt/DL/tensorflow/bin:/opt/DL/protobuf/bin:/opt/DL/caffe-bvlc/bin

[root@ING R-3.4.1]# grep libcurl config.log
configure:40993: checking if libcurl is version 7 and >= 7.22.0
/usr/bin/ld: warning: libssl.so.1.0.0, needed by /opt/anaconda2/lib/libcurl.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libcrypto.so.1.0.0, needed by /opt/anaconda2/lib/libcurl.so, not found (try using -rpath or -rpath-link)
/opt/anaconda2/lib/libcurl.so: undefined reference to `SSL_CTX_set_srp_username'
/opt/anaconda2/lib/libcurl.so: undefined reference to `libssh2_scp_recv2'
/opt/anaconda2/lib/libcurl.so: undefined reference to `SSL_CTX_set_srp_password'
configure:41089: error: libcurl >= 7.22.0 library and headers are required with support for https

이는 간단히 PATH 환경 변수에서 anaconda2를 제거한 뒤 configure를 수행하면 간단히 핵결됩니다.

그렇게 해도 문제가 되는 수가 있는데, 그럴 경우엔 아예 다음과 같이 어느 directory에서 libcurl.so를 찾으라고 명시적으로 지정하면 확실히 해결이 됩니다.

[bsyu@p57a22 R-3.4.1]$ ./configure --enable-R-shlib LDFLAGS="-L/usr/lib64 -lcurl"


2018년 7월 3일 화요일

PowerAI R5.2가 docker image로도 나왔습니다


PowerAI는 v1.4까지는 internet에서 자유롭게 download 받아서 쓸 수 있도록 되어 있었으나, v1.5부터는 별도로 주문을 해야 download 받을 수 있도록 바뀌었습니다.  다만 이때도 machine serial #만 넣으면 무료로 주문이 되니까 비용 부담은 없었습니다.   그래도 불편한 것은 사실이었지요.

그 점은 여전합니다만, v1.5.2, 즉 R5.2부터는 PowerAI를 포함한 docker image로도 배포가 됩니다. 

Redhat 7.5와 docker 13.1, nvidia-docker 1.0을 설치한 AC922 위에서 쓸 수 있는 이 docker image는 Ubuntu 16.04에 CUDA 9.2 기반으로 만들어져 있습니다.  그리고 그 속에 포함된 PowerAI R5.2 속에는 다음과 같은 component 들이 들어있습니다.

특히 IBM이 별도로 만들어 contribute한 Snap ML도 들어있는 것이 눈에 띕니다.


ComponentVersion
Distributed Deep Learning (DDL)1.0.0
TensorFlow1.8.0
TensorBoard1.8.0
IBM Caffe1.0.0
BVLC Caffe1.0.0
PyTorch0.4.0
Snap ML1.0.0
Spectrum MPI10.2
Bazel0.10.0
OpenBLAS0.2.20
Protobuf3.4.0

사용법은 일반 docker와 동일하며 간단합니다.  아래와 같이 pull 해서...

# docker pull ibmcom/powerai

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

# nvidia-docker run -ti --env LICENSE=yes ibmcom/powerai bash

현재 사용가능한 tag은 1.5.2-all-ubuntu16.04와 1.5.2-all-ubuntu16.04-py3이 있습니다.   가령 python3에서 tensorflow를 사용하시고자 한다면 아래와 같이 py3 tag를 붙여서 pull/run 하시면 됩니다.

# docker pull ibmcom/powerai:1.5.2-all-ubuntu16.04-py3

# nvidia-docker run -ti --env LICENSE=yes ibmcom/powerai:1.5.2-all-ubuntu16.04-py3 bash


더 자세한 내용은 아래 site를 참조하세요.

https://developer.ibm.com/linuxonpower/deep-learning-powerai/releases/

https://hub.docker.com/r/ibmcom/powerai/


Redhat ppc64le에서의 OS disk mirroring (SW RAID1)

기존 posting http://hwengineer.blogspot.com/2017/03/ppc64le-power8-ubuntu-sw-raid.html 에서는 Ubuntu ppc64le 환경에서 mdadm device (SW RAID1) 구성을 통해 2장의 내장 disk에 OS mirror를 구성하는 방법을 소개시켜 드렸습니다.  아시다시피 x86 아키텍처와는 달리 ppc64le에는 boot loader를 보관하는 PReP이라는 파티션이 디스크 맨 앞 부분에 존재해야 하는데, 이것은 mdadm으로는 mirror가 되지 않습니다.  다만 이 boot loader는 한번 설치되면 거기에 추가로 write될 일이 없으므로, dd 명령어를 통해 source에서 target으로 copy만 떠 놓으면 OS mirror를 사용하는데 지장이 없습니다.   그를 위해서 사용한 작은 trick은, OS 설치시 먼저 양쪽 disk에 PReP을 포함한 모든 파티션을 만들어놓되, mdadm device는 PReP을 뺸 나머지 device에 대해서만 걸어두는 것이었습니다. 

이제 POWER9과 V100을 장착한 AC922 서버는 현재까지는 주로 Redhat을 이용하는데, Redhat에서도 이런 OS mirror가 가능할까요 ?  불행히도 Redhat installer는 Ubuntu installer와는 약간 달라서, OS 설치시 각각의 disk에 먼저 파티션을 만든 뒤 어느 파티션을 무엇으로 사용할지 정하는 것이 아니라, 먼저 파티션 용도를 지정하면 자동으로 mirror device가 생성됩니다.  그래서 SW RAID1으로 그냥 설치하면 PReP과 /boot는 1번 disk에만 만들어지고, 2번 디스크 앞 부분에는 PReP 파티션을 만들 공간을 따로 확보할 수 없게 됩니다.






이 문제에 대한 workaround가 있습니다.  이 방법은 Kolon의 정유영 대리께서 고안해냈고, 테스트에서 1번 disk를 뽑아낸 뒤 리부팅을 해봐도 정상적으로 리부팅이 되었습니다.  수고해주신 정유영 대리께 감사드립니다.   

이 workaround의 절차를 요약하면 아래와 같습니다.

1) 먼저 Redhat installer가 시키는 대로, PReP과 /boot를 제외한 OS mirror를 mdadm device를 구성하여 완료합니다.
2) OS 설치 완료 뒤 mdadm 명령으로 2번 디스크의 mirror copy를 제거하여 blank disk로 만듭니다.
3) 그렇게 비워진 2번 disk에 1번 disk와 동일한 크기로 PReP과 /boot를 포함한 파티션들을 새로 만듭니다.
4) 그 중 PReP과 /boot에는 dd 명령을 통해 1번 disk의 원본을 copy합니다.
5) 나머지 OS용 파티션에는 mdadm 명령으로 mirror copy를 새로 add 합니다.

간단하지요 ?  다만 이렇게 할 경우, 나중에 혹시 /boot에 뭔가 write를 할 일이 있다면 그 내용을 2번째 disk에 다시 dd 명령으로 write를 해줘야 하긴 합니다.  물론 /boot에는 write가 일어날 일은 거의 없습니다.  이제 위의 내용을 좀 더 자세히 정리해놓겠습니다.



1. 2개의 디스크중 "/"와 "swap" 부분을 mdadm device (즉 SW RAID1)으로 구성 해서 설치합니다.   이때 PReP과 /boot는 제외됩니다.
 - PReP은 그렇다치고, 왜 /boot도 mdadm device로 구성이 안되는지는 의아하긴 합니다.

2. OS 설치 완료 후 OS 명령어 mdadm를 통해 MD device로 구성된  /와 swap에서 2번 디스크를 제거

# mdadm --manage /dev/md126 --remove /dev/sdb1    (swap 영역)
# mdadm --manage /dev/md127 --remove /dev/sdb2    (/ 영역)

3. 이제 텅 비게 된 2번 디스크를 1번 디스크와 동일하게 fdisk 명령을 이용해서 파티셔닝

# fdisk -l /dev/sda    (1번 disk의 파티션 상황 파악)
# fdisk /dev/sdb   (위의 정보에서 얻은 1번 disk 파티션과 동일하게 2번 disk에 파티션을 구성)
 - 특히 맨 앞에 만드는 /dev/sdb1의 disk type은 41 (PPC PReP Boot)으로 구성해줘야 합니다.

# fdisk /dev/sda
...
Command (m for help): t
Hex code (type L to list all codes): 41
Changed type of partition 'Linux' to 'PPC PReP Boot'
...

그래서 다음과 같이 두 disk가 동일한 파티션 정보를 가지도록 만듭니다.

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048       18431        8192   41  PPC PReP Boot
/dev/sda2           18432     1067007      524288   83  Linux
/dev/sda3         1067008     9455615     4194304   82  Linux swap / Solaris
/dev/sda4         9455616  1875384319   932964352    5  Extended
/dev/sda5         9457664  1875384319   932963328   8e  Linux LVM

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048       18431        8192   41  PPC PReP Boot
/dev/sdb2           18432     1067007      524288   83  Linux
/dev/sdb3         1067008     9455615     4194304   82  Linux swap / Solaris
/dev/sdb4         9455616  1875384319   932964352    5  Extended
/dev/sdb5         9457664  1875384319   932963328   8e  Linux LVM

4. 이제 mdadm 명령으로 /와 swap 파티션의 mirror 구성을 실시합니다.

# mdadm --manage /dev/md126 --add /dev/sdb3    (swap 영역)
# mdadm --manage /dev/md127 --add /dev/sdb5    (/ 영역)

5. PReP 파티션을 dd 명령으로 복사합니다.

# dd if=/dev/sda1 of=/dev/sdb1 bs=1024k

6. /boot 파티션을 dd 명령으로 복사합니다.   단, 이 경우는 먼저 신규 /boot에 filesystem을 만들고, 또 기존 /boot를 umount하고 진행해야 합니다.

먼저 기존 /boot가 어떤 type의 filesystem으로 만들어졌는지 확인합니다.  여기서는 xfs로 되어 있습니다. 

# mount | grep boot
/dev/sda2 on /boot type xfs (rw,relatime,attr2,inode64,noquota)

거기에 대응해서 동일 size로 만들어 두었던 /dev/sdb2를 xfs로 format 합니다.  (이 format superblock은 dd로 copy가 안되더라고요)

# mkfs -t xfs -f /dev/sdb2

그 다음에 반드시 먼저 기존의 /boot를 umount 하고 dd를 뜹니다.  (mount된 상태에서 dd를 뜨면 superblock이 copy 되지 않습니다.)

# umount /boot
# dd if=/dev/sda2 of=/dev/sdb2 bs=1024k

이제 보면 xfs_admin 명령으로 확인해보면 /dev/sdb2에도 /dev/sda2와 동일한 UUID가 들어가 있습니다.  이렇게 동일한 UUID를 사용하므로, /boot/grub2/grub.cfg를 굳이 수정할 필요가 없습니다.  다만 이로 인해 서버 부팅 시에 /boot로 /dev/sda2가 아니라 /dev/sdb2가 mount될 가능성도 있는데, 어차피 같은 copy이고 거기에 write가 일어날 일도 거의 없으므로 문제될 것은 없습니다.

#  xfs_admin -u /dev/sda2
UUID = 20a94402-8589-48db-b8cf-e82c16f415ee

#  xfs_admin -u /dev/sdb2
UUID = 20a94402-8589-48db-b8cf-e82c16f415ee

그리고 mount 해서 보면 원래의 /boot와 동일한 file들이 동일하게 보입니다.

# mount /dev/sda2 /boot
# mount /dev/sdb2 /mnt

# ls -l /boot
total 183444
-rw-r--r--. 1 root root   138001 Oct 17  2017 config-4.11.0-44.el7a.ppc64le
drwxr-xr-x. 3 root root       17 May 30 14:58 efi
drwx------. 5 root root      118 May 30 17:11 grub2
-rw-------. 1 root root 64932747 May 30 15:07 initramfs-0-rescue-168b61eb0f2d43cb8783c83d162b35f9.img
-rw-------. 1 root root 44154461 May 30 17:11 initramfs-4.11.0-44.el7a.ppc64le.img
-rw-------. 1 root root 22527454 May 30 15:27 initramfs-4.11.0-44.el7a.ppc64lekdump.img
-rw-r--r--. 1 root root 10382937 May 30 15:06 initrd-plymouth.img
-rw-r--r--. 1 root root   250055 Oct 17  2017 symvers-4.11.0-44.el7a.ppc64le.gz
-rw-------. 1 root root  2754018 Oct 17  2017 System.map-4.11.0-44.el7a.ppc64le
-rwxr-xr-x. 1 root root 21346760 May 30 15:07 vmlinuz-0-rescue-168b61eb0f2d43cb8783c83d162b35f9
-rwxr-xr-x. 1 root root 21346760 Oct 17  2017 vmlinuz-4.11.0-44.el7a.ppc64le

# ls -l /mnt
total 183444
-rw-r--r--. 1 root root   138001 Oct 17  2017 config-4.11.0-44.el7a.ppc64le
drwxr-xr-x. 3 root root       17 May 30 14:58 efi
drwx------. 5 root root      118 May 30 17:11 grub2
-rw-------. 1 root root 64932747 May 30 15:07 initramfs-0-rescue-168b61eb0f2d43cb8783c83d162b35f9.img
-rw-------. 1 root root 44154461 May 30 17:11 initramfs-4.11.0-44.el7a.ppc64le.img
-rw-------. 1 root root 22527454 May 30 15:27 initramfs-4.11.0-44.el7a.ppc64lekdump.img
-rw-r--r--. 1 root root 10382937 May 30 15:06 initrd-plymouth.img
-rw-r--r--. 1 root root   250055 Oct 17  2017 symvers-4.11.0-44.el7a.ppc64le.gz
-rw-------. 1 root root  2754018 Oct 17  2017 System.map-4.11.0-44.el7a.ppc64le
-rwxr-xr-x. 1 root root 21346760 May 30 15:07 vmlinuz-0-rescue-168b61eb0f2d43cb8783c83d162b35f9
-rwxr-xr-x. 1 root root 21346760 Oct 17  2017 vmlinuz-4.11.0-44.el7a.ppc64le

확인이 끝났으면 /mnt는 umount하고 사용을 시작하시면 됩니다. 
# umount /mnt

이로써 OS mirroring이 다 끝난 것입니다.