2018년 10월 5일 금요일

IBM이 자랑하는 POWER9 + V100 GPU의 조합이 H2O DriverlessAI에 어떤 도움이 될까 ?

H2O Driverless AI는 model training 중 GPU에서 돌리는 것이 더 효과적이라고 판단될 때마다 필요에 따라 드문드문 GPU를 사용합니다.   이는 우측 하단의 "GPU usage" tab을 클릭하면 아래와 같이 보실 수 있습니다.



물론 nvidia-smi 에서도 모니터링하실 수 있습니다.   GPU 1개당 1개의 process가 수행되는 것이 아니라, GPU 메모리가 허용하는 한 필요에 따라 GPU 1개당 여러 개의 process들이 수행되기도 합니다.

Fri Oct  5 03:36:45 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 396.26                 Driver Version: 396.26                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  On   | 00000002:01:00.0 Off |                    0 |
| N/A   34C    P0    64W / 300W |    455MiB / 16280MiB |     40%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  On   | 00000003:01:00.0 Off |                    0 |
| N/A   36C    P0    77W / 300W |    455MiB / 16280MiB |     38%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  On   | 0000000A:01:00.0 Off |                    0 |
| N/A   32C    P0    71W / 300W |    455MiB / 16280MiB |     40%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  On   | 0000000B:01:00.0 Off |                    0 |
| N/A   36C    P0    64W / 300W |    455MiB / 16280MiB |     38%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0     94004      C   ...el-running(prot=False)-XGBoostModel-fit   445MiB |
|    1     94011      C   ...el-running(prot=False)-XGBoostModel-fit   445MiB |
|    2     94044      C   ...el-running(prot=False)-XGBoostModel-fit   445MiB |
|    3     94126      C   ...el-running(prot=False)-XGBoostModel-fit   445MiB |
+-----------------------------------------------------------------------------+


과연 여기서 NVLink가 어느 정도의 효과를 발휘할까요 ?  그것을 확인하는 가장 쉽고 생생한 방법은 nvprof 명령을 이용하여 DriverlessAI process들이 GPU를 어떻게 사용하는지 profile을 떠보는 것입니다.

먼저, DAI의 홈 디렉토리에 있는 start-dai.sh를 다음과 같이 수정합니다.  원래의 line은 #으로 막아놓았고, 아래 붉은색의 명령어들이 새로 삽입된 nvprof 명령어입니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# cat start-dai.sh
#!/bin/bash

if [ "x${RUN_DAI_CREATE_PIDFILE}" == "x1" ]; then
# python -m h2oai &
 /usr/local/cuda-9.2/bin/nvprof --log-file /tmp/nvprof1.%p.txt --export-profile /tmp/nvprof1.%p.nvvp --print-gpu-trace --profile-child-processes python -m h2oai &
    echo $! > ${RUN_DAI_PIDFILE_DIR}/dai.pid
else
# exec python -m h2oai
    exec /usr/local/cuda-9.2/bin/nvprof --log-file /tmp/nvprof1.%p.txt --export-profile /tmp/nvprof1.%p.nvvp --print-gpu-trace --profile-child-processes python -m h2oai
fi


위와 같이 해놓고 kill-dai.sh를 수행하여 기존 DAI를 stop시킨 뒤, run-dai.sh를 수행하여 DAI를 새로 구동한 뒤에 큼직한 dataset으로 training을 해봅니다.   이때, 다음과 같이 child process마다 txt와 nvvp로 텍스트와 바이너리 로그 파일이 생성되는 것을 보실 수 있습니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ls -l /tmp/nvprof1*
...
-rw-r--r-- 1 root root 170096640 Oct  5 03:16 /tmp/nvprof1.83368.nvvp
-rw-r--r-- 1 root root 233180816 Oct  5 03:22 /tmp/nvprof1.83368.txt
-rw-r--r-- 1 root root 180073472 Oct  5 03:16 /tmp/nvprof1.83405.nvvp
-rw-r--r-- 1 root root 246428557 Oct  5 03:20 /tmp/nvprof1.83405.txt
...

이 중 하나를 CUDA에 딸려 있는 NVIDIA Visual Profiler (NVVP)로 분석해보면 다음과 같습니다.




"CUDA memcpy HtoD" (Host to Device, 즉 서버 CPU에서 GPU로의 memcpy도 9 GB/s에 가깝고 DtoD (GPU간의 memcpy)는 134 GB/s에 가깝게 사용되는 것을 보실 수 있습니다.

특히 8개의 GPU를 장착한 일반 x86 기반 GPU 서버들은 NVLink를 1개씩만 이용하여 연결되므로 GPU간의 통신은 이론상 50 GB/s, CPU와 GPU간의 통신은 이론상 32 GB/s가 최대인 것에 비해, IBM AC922은 3개의 NVLink를 aggregation시켜 CPU와 GPU이나 GPU끼리나 모두 150 GB/s로 연결된 것이 H2O DriverlessAI의 운용에 크게 유리하다는 것을 쉽게 보실 수 있습니다.


H2O DriverlessAI에서 제공하는 python client program 수행

H2O DAI는 training한 모델을 이용하는 client program을 python 혹은 MOJO(java) 형태로 제공해줍니다.  먼저번 posting에서 train된 모델에 대한 python client program을 download 받기 위해서는 "Download python scoring pipeline"이라는 메뉴를 click하면 됩니다.   scoring.zip이라는 zip 파일을 web browser로 download 받을 수 있습니다. 



서버 상에서는 이 파일은 다음과 같이 임시 directory에 생성되어 있으니 그걸 download 받아서 사용해도 됩니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ls -l ./tmp/h2oai_experiment_copikupa/scoring_pipeline/scorer.zip
-rw-rw----+ 1 root root 95622433 Oct  4 21:40 ./tmp/h2oai_experiment_copikupa/scoring_pipeline/scorer.zip

[root@p57a22 dai-1.3.1-linux-ppc64le]# cp ./tmp/h2oai_experiment_copikupa/scoring_pipeline/scorer.zip /home/data

이것의 압축을 풀면 다음과 같이 train된 model을 포함하는 wheel 파일과 함께, python client program을 구성하는 python code 및 shell program들이 들어 있습니다.

[root@p57a22 data]# unzip scorer.zip
Archive:  scorer.zip
   creating: scoring-pipeline/
  inflating: scoring-pipeline/scoring.thrift
  inflating: scoring-pipeline/requirements.txt
  inflating: scoring-pipeline/environment.yml
  inflating: scoring-pipeline/example.py
  inflating: scoring-pipeline/http_server.py
  inflating: scoring-pipeline/tcp_server.py
  inflating: scoring-pipeline/example_client.py
  inflating: scoring-pipeline/run_http_client.sh
  inflating: scoring-pipeline/datatable-0.6.0.dev252-cp36-cp36m-linux_ppc64le.whl
  inflating: scoring-pipeline/h2o4gpu-0.2.0.9999%2Bmaster.129ef59-cp36-cp36m-linux_ppc64le.whl
  inflating: scoring-pipeline/h2oaicore-1.3.1-cp36-cp36m-linux_ppc64le.whl
  inflating: scoring-pipeline/README.txt
  inflating: scoring-pipeline/run_example.sh
 extracting: scoring-pipeline/tcp_server_requirements.txt
 extracting: scoring-pipeline/http_server_requirements.txt
  inflating: scoring-pipeline/run_tcp_server.sh
  inflating: scoring-pipeline/run_http_server.sh
 extracting: scoring-pipeline/client_requirements.txt
  inflating: scoring-pipeline/run_tcp_client.sh
  inflating: scoring-pipeline/thrift_post_processing.py
  inflating: scoring-pipeline/common-functions.sh
  inflating: scoring-pipeline/scoring_h2oai_experiment_copikupa-1.0.0-py3-none-any.whl
 extracting: scoring-pipeline/h2oai_experiment_summary_copikupa.zip

이 파일들을 다른 서버로 옮겼다고 가정하시지요.  이건 training이 아니라 train된 model을 이용한 prediction (또는 inferencing)이니까, 굳이 GPU가 달려있지 않은 일반 서버로도 충분합니다.

먼저 해당 서버에도 먼저번 posting과 같이, DAI의 TAR SH 파일을 download 받아 설치합니다.

[root@p57a22 data]# wget https://s3.amazonaws.com/artifacts.h2o.ai/releases/ai/h2o/dai/rel-1.3.1-12/ppc64le-centos7/dai-1.3.1-linux-ppc64le.sh

이것을 수행하면 그 directory를 DRIVERLESS_AI_HOME으로 하여 필요한 binary engine이 설치됩니다.  다른 directory에 설치하고 싶으시면 다음과 같이 설치하고자 하는 directory 이름을 직접 적어도 됩니다.

[root@p57a22 data]# ./dai-1.3.1-linux-ppc64le.sh /usr/local/dai-1.3.1-linux-ppc64le

설치된 directory로 들어가보면 start와 stop에 필요한 shell script와 함께 각종 jar 및 python 파일들이 들어있습니다.  기본적으로 H2O DriverlessAI는 python과 java로 되어 있으며, 독자적인 python engine (v3.6.1)과 jre (v1.8)을 가지고 있습니다.  물론 이것들은 산업 표준 그대로의 것들입니다.

[root@p57a22 data]# cd /usr/local/dai-1.3.1-linux-ppc64le

[root@p57a22 dai-1.3.1-linux-ppc64le]# ls
bin             cuda-9.2                  h2o.jar      log                 README_TAR_SH.txt  src
BUILD_INFO.txt  dai-env.sh                include      mojo2-runtime.jar   README.txt         start-dai.sh
config.toml     docs                      jre          procsy              README_WSL.txt     start-h2o.sh
cpu-only        h2oai_autoreport          kill-dai.sh  python              run-dai.sh         start-procsy.sh
cuda-8.0        h2oai-dai-connectors.jar  lib          README_DOCKER.txt   sample_data        VERSION.txt
cuda-9.0        h2oai_scorer              LICENSE      README_RPM_DEB.txt  share              vis-data-server.jar

dai-env.sh를 수행하면 필요한 환경 변수들이 자동 설정됩니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ./dai-env.sh
======================================================================
DRIVERLESS_AI_HOME is /usr/local/dai-1.3.1-linux-ppc64le
DRIVERLESS_AI_CONFIG_FILE is /usr/local/dai-1.3.1-linux-ppc64le/config.toml
DRIVERLESS_AI_JAVA_HOME is /usr/localdai-1.3.1-linux-ppc64le/jre
JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
CUDA Version is cuda-9.2
DRIVERLESS_AI_H2O_XMX is 233580m
DRIVERLESS_AI_H2O_PORT is 54321
DRIVERLESS_AI_PROCSY_PORT is 8080
OMP_NUM_THREADS is 16
OPENBLAS_MAIN_FREE is 1
LANG is en_US.UTF-8
MAGIC is /usr/local/dai-1.3.1-linux-ppc64le/share/misc/magic
HOME is /root
uid=0(root) gid=0(root) groups=0(root),2001(powerai)
======================================================================

확실히 하기 위해 PATH를 분명히 다시 export하고, 새로 설치한 DriverlessAI engine의 python을 쓰는 것인지 확인합니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# export PATH=/usr/local/dai-1.3.1-linux-ppc64le/python/bin:$PATH

[root@p57a22 dai-1.3.1-linux-ppc64le]# export PYTHONPATH=/usr/local/dai-1.3.1-linux-ppc64le/lib/python3.6/site-packages

[root@p57a22 dai-1.3.1-linux-ppc64le]# which pip
/usr/local/dai-1.3.1-linux-ppc64le/python/bin/pip

이제 pip 명령으로 보면 이 DAI의 PYTHONPATH에 pyarrow 등 필요 package들이 이미 설치가 된 것을 보실 수 있습니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# pip list | grep pyarrow
pyarrow (0.9.0)

이제 남은 것은 아까 train된 모델을 담은 wheel 파일을 pip로 설치하는 것입니다.

[root@p57a22 scoring-pipeline]# pip install /home/data/scoring-pipeline/scoring_h2oai_experiment_copikupa-1.0.0-py3-none-any.whl
Processing ./scoring_h2oai_experiment_copikupa-1.0.0-py3-none-any.whl
Installing collected packages: scoring-h2oai-experiment-copikupa
Successfully installed scoring-h2oai-experiment-copikupa-1.0.0

이제 다음과 같이 H2O DAI의 license를 export 해주고 환경변수 SCORING_PIPELINE_INSTALL_DEPENDENCIES를 0으로 export 해줍니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# export DRIVERLESS_AI_LICENSE_KEY="ZEL-GSl7nd0...MDE4LzEwLzIyCg=="

[root@p57a22 dai-1.3.1-linux-ppc64le]# export SCORING_PIPELINE_INSTALL_DEPENDENCIES=0

이제 환경변수 설정을 해주는 dai-env.sh와 함께 run_example.sh을 수행해보면 다음과 같이 나옵니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ./dai-env.sh /home/data/scoring-pipeline/run_example.sh
======================================================================
DRIVERLESS_AI_HOME is /usr/local/dai-1.3.1-linux-ppc64le
DRIVERLESS_AI_CONFIG_FILE is /usr/local/dai-1.3.1-linux-ppc64le/config.toml
DRIVERLESS_AI_JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
CUDA Version is cuda-9.2
DRIVERLESS_AI_H2O_XMX is 233580m
DRIVERLESS_AI_H2O_PORT is 54321
DRIVERLESS_AI_PROCSY_PORT is 8080
OMP_NUM_THREADS is 16
OPENBLAS_MAIN_FREE is 1
LANG is en_US.UTF-8
MAGIC is /home/data/dai-1.3.1-linux-ppc64le/share/misc/magic
HOME is /root
uid=0(root) gid=0(root) groups=0(root),2001(powerai)
======================================================================
Creating virtual environment...
...

---------- Score Row ----------
[7.788316249847412]
[7.006689071655273]
[21.045005798339844]
[21.044675827026367]
[11.887664794921875]
---------- Score Frame ----------
   Holiday Parks Occupancy rate (percent)
0                                7.788316
1                                7.006689
2                               21.045006
3                               21.044676
4                               11.887665
5                                8.289392
6                                9.870693
7                               20.901302
8                                6.830247
9                               34.114899
---------- Get Per-Feature Prediction Contributions for Row ----------
[[-2.5961287021636963, -0.6367928981781006, -2.0373380184173584, -0.0076079904101789, 0.012887582182884216, 0.0021535237319767475, -0.6188143491744995, 0.0005846393178217113, 13.669371604919434]]
---------- Get Per-Feature Prediction Contributions for Frame ----------
   contrib_0_Time~get_dayofyear  contrib_1_TargetLag:1  contrib_1_TargetLag:7  \
0                     -2.596129              -0.636793              -2.037338
1                     -2.503755              -2.222152              -2.128783
2                     -2.007713               5.645916               2.868525
3                      5.954381              -1.163898               2.224814
4                     -2.241865              -2.073594               3.084045
5                     -1.311869              -2.307918              -2.090618
6                     -0.312522              -1.869532              -1.919978
7                     -2.004388               5.625261               2.855450
8                     -2.512271              -1.851307              -2.055076
9                     12.943974               4.565596               2.292724

   contrib_1_TargetLag:12  contrib_1_TargetLag:23  contrib_1_TargetLag:24  \
0               -0.007608                0.012888                0.002154
1                0.049226                0.012719                0.005904
2                0.035909                0.052717                0.010889
3               -0.005368               -0.058491                0.007430
4                0.097049                0.017581                0.005795
5                0.044280                0.019071                0.007741
6               -0.006849                0.017562                0.007540
7               -0.008142               -0.006090               -0.003598
8               -0.012190                0.012719                0.003869
9               -0.007709               -0.006148               -0.027283

   contrib_1_TargetLag:27  \
0               -0.618814
1                0.145105
2                0.768746
3                0.415227
4               -0.665447
5                0.258045
6                0.282250
7                0.779280
8               -0.426931
9                0.690188

   contrib_2_InteractionDiv:Hotels Occupancy rate (percent):Total Occupancy rate (percent)  \
0                                           0.000585
1                                          -0.020946
2                                           0.000645
3                                           0.001209
4                                          -0.005272
5                                           0.001292
6                                           0.002849
7                                          -0.005841
8                                           0.002059
9                                          -0.005811

   contrib_bias
0     13.669372
1     13.669372
2     13.669372
3     13.669372
4     13.669372
5     13.669372
6     13.669372
7     13.669372
8     13.669372
9     13.669372
---------- Transform Frames ----------
---------- Retrieve column names ----------
('Time', 'Total Occupancy rate (percent)', 'Hotels Occupancy rate (percent)')
---------- Retrieve transformed column names ----------
['0_Time~get_dayofyear', '1_TargetLag:1', '1_TargetLag:7', '1_TargetLag:12', '1_TargetLag:23', '1_TargetLag:24', '1_TargetLag:27', '2_InteractionDiv:Hotels Occupancy rate (percent):Total Occupancy rate (percent)']


똑같은 일을 해주는 것이지만, 이걸 TCP server / client 형태로 구현해놓은 shell script도 있습니다.  먼저 아래와 같이 run_tcp_server.sh를 수행해주고...


[root@p57a22 dai-1.3.1-linux-ppc64le]# ./dai-env.sh /home/data/scoring-pipeline/run_tcp_server.sh
======================================================================
DRIVERLESS_AI_HOME is /usr/local/dai-1.3.1-linux-ppc64le
DRIVERLESS_AI_CONFIG_FILE is /usr/local/dai-1.3.1-linux-ppc64le/config.toml
DRIVERLESS_AI_JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
CUDA Version is cuda-9.2
DRIVERLESS_AI_H2O_XMX is 233580m
DRIVERLESS_AI_H2O_PORT is 54321
DRIVERLESS_AI_PROCSY_PORT is 8080
OMP_NUM_THREADS is 16
OPENBLAS_MAIN_FREE is 1
LANG is en_US.UTF-8
MAGIC is /usr/local/dai-1.3.1-linux-ppc64le/share/misc/magic
HOME is /root
uid=0(root) gid=0(root) groups=0(root),2001(powerai)
==========================================================
...
TCP scoring service listening on port 9090...


이 상태에서 다른 terminal에서 run_tcp_client.sh를 수행해주면 다음과 같이 나옵니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ./dai-env.sh /home/data/scoring-pipeline/run_tcp_client.sh
======================================================================
DRIVERLESS_AI_HOME is /usr/local/dai-1.3.1-linux-ppc64le
DRIVERLESS_AI_CONFIG_FILE is /usr/local/dai-1.3.1-linux-ppc64le/config.toml
DRIVERLESS_AI_JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
JAVA_HOME is /usr/local/dai-1.3.1-linux-ppc64le/jre
CUDA Version is cuda-9.2
DRIVERLESS_AI_H2O_XMX is 233580m
DRIVERLESS_AI_H2O_PORT is 54321
DRIVERLESS_AI_PROCSY_PORT is 8080
OMP_NUM_THREADS is 16
OPENBLAS_MAIN_FREE is 1
LANG is en_US.UTF-8
MAGIC is /usr/local/dai-1.3.1-linux-ppc64le/share/misc/magic
HOME is /root
uid=0(root) gid=0(root) groups=0(root),2001(powerai)
======================================================================
Scoring server hash:
Scoring individual rows...
[7.788316249847412]
[7.006689071655273]
[21.045005798339844]
[21.044675827026367]
[11.887664794921875]
Scoring multiple rows...
[[7.788316249847412], [7.006689071655273], [21.045005798339844], [21.044675827026367], [11.887664794921875]]
Retrieve column names
['Time', 'Total Occupancy rate (percent)', 'Hotels Occupancy rate (percent)']
Retrieve transformed column names
['0_Time~get_dayofyear', '1_TargetLag:1', '1_TargetLag:7', '1_TargetLag:12', '1_TargetLag:23', '1_TargetLag:24', '1_TargetLag:27', '2_InteractionDiv:Hotels Occupancy rate (percent):Total Occupancy rate (percent)']


AI를 해주는 AI, H2O Driverless AI의 설치와 사용법

H2O Driverless AI의 설치 및 구동, 그리고 모든 사무실에 수북히 쌓여있는 spreadsheet data를 이용한 training은 매우 쉽습니다.

먼저, 다음과 같이 H2O DriverlessAI 설치 파일을 download 받습니다.  저는 여기서 IBM POWER8 CPU와 Pascal P100 GPU를 장착한 Minsky 서버를 사용했습니다.

[root@p57a22 data]# wget https://s3.amazonaws.com/artifacts.h2o.ai/releases/ai/h2o/dai/rel-1.3.1-12/ppc64le-centos7/dai-1.3.1-linux-ppc64le.sh


(rpm을 download 받아서 해도 됩니다만, 이게 TAR SH를 download 받는 것이 여러모로 가장 편리합니다.)


이것을 수행하면 그 directory를 DRIVERLESS_AI_HOME으로 하여 필요한 binary engine이 설치됩니다.  다른 directory에 설치하고 싶으시면 ./dai-1.3.1-linux-ppc64le.sh "설치_디렉토리_이름"과 같이 directory 이름을 직접 적어도 됩니다.

[root@p57a22 data]# chmod a+x dai-1.3.1-linux-ppc64le.sh

[root@p57a22 data]# ./dai-1.3.1-linux-ppc64le.sh
Extracting to dai-1.3.1-linux-ppc64le ...
...
Starting Driverless AI

    run-dai.sh

Stopping Driverless AI

    kill-dai.sh

Debugging Driverless AI

    cat log/dai.out
    cat log/h2o.out
    cat log/procsy.out


설치된 directory로 들어가보면 start와 stop에 필요한 shell script와 함께 각종 jar 및 python 파일들이 들어있습니다.  기본적으로 H2O DriverlessAI는 python과 java로 되어 있으며, 독자적인 python engine (v3.6.1)과 jre (v1.8)을 가지고 있습니다.  물론 이것들은 산업 표준 그대로의 것들입니다.

[root@p57a22 data]# cd dai-1.3.1-linux-ppc64le

[root@p57a22 dai-1.3.1-linux-ppc64le]# ls
bin             cuda-9.2                  h2o.jar      log                 README_TAR_SH.txt  src
BUILD_INFO.txt  dai-env.sh                include      mojo2-runtime.jar   README.txt         start-dai.sh
config.toml     docs                      jre          procsy              README_WSL.txt     start-h2o.sh
cpu-only        h2oai_autoreport          kill-dai.sh  python              run-dai.sh         start-procsy.sh
cuda-8.0        h2oai-dai-connectors.jar  lib          README_DOCKER.txt   sample_data        VERSION.txt
cuda-9.0        h2oai_scorer              LICENSE      README_RPM_DEB.txt  share              vis-data-server.jar


dai-env.sh를 수행하면 필요한 환경 변수들이 자동 설정됩니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ./dai-env.sh
======================================================================
DRIVERLESS_AI_HOME is /home/data/dai-1.3.1-linux-ppc64le
DRIVERLESS_AI_CONFIG_FILE is /home/data/dai-1.3.1-linux-ppc64le/config.toml
DRIVERLESS_AI_JAVA_HOME is /home/data/dai-1.3.1-linux-ppc64le/jre
JAVA_HOME is /home/data/dai-1.3.1-linux-ppc64le/jre
CUDA Version is cuda-9.2
DRIVERLESS_AI_H2O_XMX is 233580m
DRIVERLESS_AI_H2O_PORT is 54321
DRIVERLESS_AI_PROCSY_PORT is 8080
OMP_NUM_THREADS is 16
OPENBLAS_MAIN_FREE is 1
LANG is en_US.UTF-8
MAGIC is /home/data/dai-1.3.1-linux-ppc64le/share/misc/magic
HOME is /root
uid=0(root) gid=0(root) groups=0(root),2001(powerai)
======================================================================

이제 run-dai.sh를 수행하면 H2O DAI가 시작됩니다.

[root@p57a22 dai-1.3.1-linux-ppc64le]# ./run-dai.sh
======================================================================
DRIVERLESS_AI_HOME is /home/data/dai-1.3.1-linux-ppc64le
DRIVERLESS_AI_CONFIG_FILE is /home/data/dai-1.3.1-linux-ppc64le/config.toml
DRIVERLESS_AI_JAVA_HOME is /home/data/dai-1.3.1-linux-ppc64le/jre
JAVA_HOME is /home/data/dai-1.3.1-linux-ppc64le/jre
CUDA Version is cuda-9.2
DRIVERLESS_AI_H2O_XMX is 233580m
DRIVERLESS_AI_H2O_PORT is 54321
DRIVERLESS_AI_PROCSY_PORT is 8080
OMP_NUM_THREADS is 16
OPENBLAS_MAIN_FREE is 1
LANG is en_US.UTF-8
MAGIC is /home/data/dai-1.3.1-linux-ppc64le/share/misc/magic
HOME is /root
uid=0(root) gid=0(root) groups=0(root),2001(powerai)
======================================================================
Started.


이후에는 http://129.40.XX.XX:12345 와 같이 12345 포트로 web browser를 통해 dataset을 import하고 training (H2O에서는 experiment라고 합니다)을 하면 됩니다.

(아래 그림에 나오는 IP address는 VPN으로만 접근 가능한 주소이니 공연히 두들겨 보지 마십시요... 시간낭비입니다 ㅋ)




맨 처음 나오는 나오는 화면은 login 화면인데, 여기서의 user id와 passwd는 임의로 직접 여기서 정하시면 됩니다.  이 user id는 OS의 user id가 아니라, 그냥 DriverlessAI의 user id입니다.  이 user id는 login 했을 때 내가 볼 수 있는 dataset과 train된 model들 등을 구분하기 위한 것이며, 또한 H2O DAI의 license의 단위가 됩니다.  DAI의 license는 CPU core나 server box 수가 아니라 user 단위로 됩니다.

Login 이후에는 dataset부터 import 하게 되어 있습니다.  PC에서 upload하셔도 되고, 미리 서버에 upload해둔 file을 서버의 filesystem에서 가져와도 됩니다.  모든 CSV 포맷 파일을 그대로 사용하실 수 있습니다.  Excel 파일이 있다면 그건 수작업으로 CSV 포맷으로 저장하셔서 사용하셔야 합니다.  여기서는 https://timeseries.weebly.com/data-sets.html 에서 얻은 각 숙박시설의 점유율 data를 가지고 해보겠습니다.   이는 달별로 호텔, 모텔, 야영장, 배낭족 등의 점유율을 정리한 100여줄의 매우 작은 자료입니다.




Dataset이 import되면 즉각 자동으로 각 column들의 Min/Max/Avg/Dev 등을 계산해주는 것은 물론, 다양한 형태로 visualize까지 할 수 있습니다.   가령 아래 그림은 각 column 간의 상관관계를 보여주는 도표입니다.




이제 predict 메뉴를 눌러 이 dataset으로 model을 training하겠습니다.


여기서 지정해줄 것은 사실상 딱 하나, 어떤 column에 대해서 향후 예측을 하고 싶으냐만 정하시면 됩니다.  여기서는 Holiday Park Occupancy Rate라는 칼럼으로 하겠습니다.




나머지는 옵션들입니다.  가령 이 spreadsheet의 칼럼 중 시간 부분이 있다면 그걸 Time 칼럼으로 지정하시는 것이 좋습니다.  Time 칼럼을 Auto로 놓으면 아예 자동으로 어떤 칼럼이 시간 부분인지 탐지하여 설정합니다. 


그리고 조종할 부분은 3개의 라디오 다이얼 같은 것 뿐입니다.  왼쪽부터 Accuracy (정확도), Time (시간), Interpretability (기계학습 해석) 다이얼인데, 1~10까지의 '강약'을 조절하는 방식으로 되어 있습니다.   가령 Accuracy를 높일 경우 사용되는 알고리즘이 GLM과 XGBoost에서 XGBoost로 바뀐다든지, Time을 늘릴 경우 training 반복 회수가 12번에서 523번으로 바뀐다든지 하는 식입니다.  어려운 세부 튜닝을 자동으로 해주므로 우리는 그냥 보고서 제출 때까지 시간 여유가 얼마나 있는지 등만 결정하면 되는 것입니다.




물론 아래와 같이 expert setting을 할 수도 있습니다.  Tensorflow라든가 RuleFit 같은 것들은 현재 alpha 버전으로 제공됩니다.



Training을 시작하면 왼쪽 아래에는 validation, 즉 기본적으로 RMSE (Root Mean Square Error)가 display되면서 error가 점차 줄어드는 것을 보실 수 있습니다.  오른쪽 아래에는 data 내의 실제 값과, training 회수가 반복되면서 prediction하는 값의 상관 관계가 그래프로 보여집니다.  처음에는 저 그래프는 분산도가 크게 보여지다가, training이 잘 되면 점차 직선으로 수렴되는 것을 보실 수 있습니다.   또한 중앙 상단의 모델 완성%를 보여주는 계기판 위에는 "3912개의 feature에 대해 896개 모델 중 118개에 대해 평가를 완료"라는 메시지가 보이는데, 이 숫자들은 training이 진행되면서 최적화를 거쳐 계속 동적으로 변화됩니다.


H2O DAI에서는 필요에 따라 띄엄띄엄 GPU를 사용합니다.   다음과 같이 nvidia-smi로도 그 사용 모습을 모니터링할 수 있고, 또 오른쪽 하단의 'GPU usage' tab을 클릭하면 GPU 사용률을 GPU별로 볼 수 있습니다.


Fri Oct  5 00:51:19 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 396.26                 Driver Version: 396.26                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  On   | 00000002:01:00.0 Off |                    0 |
| N/A   31C    P0    39W / 300W |    600MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  On   | 00000003:01:00.0 Off |                    0 |
| N/A   33C    P0    42W / 300W |    608MiB / 16280MiB |     35%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  On   | 0000000A:01:00.0 Off |                    0 |
| N/A   30C    P0    38W / 300W |    604MiB / 16280MiB |     20%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  On   | 0000000B:01:00.0 Off |                    0 |
| N/A   33C    P0    29W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|    0     18750      C   ...uild_cv_model_subprocess-end(prot=True)   295MiB |
|    0     18969      C   ...uild_cv_model_subprocess-end(prot=True)   295MiB |
|    1     18749      C   ...uild_cv_model_subprocess-end(prot=True)   295MiB |
|    1     18970      C   ...el-running(prot=False)-XGBoostModel-fit   303MiB |
|    2     18748      C   ...uild_cv_model_subprocess-end(prot=True)   295MiB |
|    2     18971      C   ...ng(prot=False)-RuleFitModel-fit_glm-fit   299MiB |
+-----------------------------------------------------------------------------+



Training(DAI에서는 Experiment라고 함)이 끝나면 다음과 같이 당장 prediction을 할 수 있는 "Score on another dataset"이라는 메뉴가 제공됩니다.  여기에 training시킨 dataset과 같은 명칭과 종류의 column과 data를 가진 test dataset을 넣으면 아까 정한 target column에 대해 prediction을 해줍니다.   저는 여기에 미리 따로 잘라서 준비해둔 occupancy test dataset을 입력해보았습니다.   그 결과로 다음과 같이 해당 column에 대한 예측값을 CSV로 download 받을 수 있습니다.





이 값을 실제 수치와 비교를 해보면 대략 다음과 같이 나옵니다.  100여줄 정도의 data로 10여분 training한 것치고는 괜찮은 예측치입니다.



또한, 이런 예측을 이렇게 DAI 서버의 web interface 말고, 여기서 train된 모델을 다른 서버로 옮겨서 python 혹은 java client program을 거쳐서 수행할 수도 있습니다.  이에 대해서는 다른 posting에서 다루겠습니다.


2018년 9월 10일 월요일

ILSVRC2012 dataset 중 강아지 사진만을 이용한 짧은 TF inception v3 테스트 방법



다음과 같이 benchmark/tensorflow 디렉토리에 들어가서, exec_img.sh를 수행하시면 됩니다.  이때 아래와 같이 nohup으로 수행하시면 도중에 연결 세션이 끊어져도 백그라운드로 job은 계속 수행될 뿐만 아니라, 수행 기록이 nohup.out에도 기록되므로 편리하실 것입니다.

[root@ac922 tensorflow]# pwd
/home/files/ilsvrc12/tensorflow

[root@ac922 tensorflow]# ls
benchmark  exec_img.sh  models  nohup.out.final.tf  output_final

[root@ac922 tensorflow]# nohup ./exec_img.sh &

위와 같이 exec_img.sh를 한번 수행하시면 그 속에서 아래와 같이 ./models/run_model.sh 스크립트가 batch_size=128로 순차적으로 GPU 개수 4, 2, 1에 대해서 각각 1번씩 총 3번을 수행합니다.  각 수행이 끝날 때마다 time 명령에 의해 수행 시간에 걸린 시간이 nohup.out에 기록됩니다.   원래 NVIDIA에서 준 script를 수행해보니, 매번 exec을 수행할 때마다 output directory를 새로 만들어야 제대로 수행되는 것 같아 아래와 같이 exec 수행시마다 ouput directory를 다른 이름으로 옮기고 새로 output을 만드는 문장을 추가했습니다.

mkdir output
time  exec  tf inception3  128  4  0
mv output output4gpu
mkdir output
time  exec  tf inception3  128  2  0
mv output output2gpu
mkdir output
time  exec  tf inception3  128  1  0
mv output output1gpu


결과 확인은 ouput directory에 쌓이는 아래의 log를 보셔도 되고, nohup.out을 보셔도 됩니다.  이 script에서는 total images/sec이 python 자체적으로 합산되어 표시되므로 그것을 기록하시면 됩니다.   단, python에서 계산되는 Elapsed Time은 일부 로직이 잘못되어 분:초 단위만 맞고 시간 단위는 9시간으로 나오니 그건 무시하십시요. 

이 테스트를 위해 필요한 python code 및 model file을 아래 google drive에 올려 놓았습니다.

https://drive.google.com/open?id=1DNn-Nv4rlOiv2NLqk6Y0j2ANlJjw9VP6

그리고 이 테스트를 위해 필요한 종류별로 labeling된 강아지 사진을 tfrecord 포맷으로 만든 dataset을 아래 google drive에 올려 놓았습니다.

https://drive.google.com/open?id=1rQcxAWeNbByy0Yooj6IbROyVRsdQPn5-

위 dataset을 추출하고 tfrecord로 포맷하는 과정은 아래에 정리되어 있습니다.

http://hwengineer.blogspot.com/2018/04/ilsvrc2012imgtraint3tar-training-dataset.html


** 별첨 :  tfrecord file들의 이름과 size

[root@ac922 ilsvrc12]# cd tfrecord/

[root@ac922 tfrecord]# ls -l | head
total 1509860
-rw-rw-r--. 1 1001 1001  6920780 Apr 11 19:20 train-00000-of-00120
-rw-rw-r--. 1 1001 1001  6422535 Apr 11 19:20 train-00001-of-00120
-rw-rw-r--. 1 1001 1001  6959007 Apr 11 19:21 train-00002-of-00120
-rw-rw-r--. 1 1001 1001  6885268 Apr 11 19:21 train-00003-of-00120
-rw-rw-r--. 1 1001 1001  5969364 Apr 11 19:21 train-00004-of-00120
-rw-rw-r--. 1 1001 1001  6143260 Apr 11 19:21 train-00005-of-00120
-rw-rw-r--. 1 1001 1001  6123517 Apr 11 19:21 train-00006-of-00120
-rw-rw-r--. 1 1001 1001  8585788 Apr 11 19:21 train-00007-of-00120
-rw-rw-r--. 1 1001 1001  6149957 Apr 11 19:21 train-00008-of-00120

[root@ac922 tfrecord]# ls -l | tail
-rw-rw-r--. 1 1001 1001 24124729 Apr 11 19:20 validation-00022-of-00032
-rw-rw-r--. 1 1001 1001 23741822 Apr 11 19:20 validation-00023-of-00032
-rw-rw-r--. 1 1001 1001 24759230 Apr 11 19:20 validation-00024-of-00032
-rw-rw-r--. 1 1001 1001 25225023 Apr 11 19:20 validation-00025-of-00032
-rw-rw-r--. 1 1001 1001 25273559 Apr 11 19:20 validation-00026-of-00032
-rw-rw-r--. 1 1001 1001 26820464 Apr 11 19:20 validation-00027-of-00032
-rw-rw-r--. 1 1001 1001 24115323 Apr 11 19:20 validation-00028-of-00032
-rw-rw-r--. 1 1001 1001 24459085 Apr 11 19:20 validation-00029-of-00032
-rw-rw-r--. 1 1001 1001 25246485 Apr 11 19:20 validation-00030-of-00032
-rw-rw-r--. 1 1001 1001 23561132 Apr 11 19:20 validation-00031-of-00032

[root@ac922 tfrecord]# du -sm .
1475    .


2018년 9월 6일 목요일

Poughkeepsie 센터에서 LSF cluster 이용하여 tensorflow 수행하는 방법 안내

** 이는 IBM Poughkeepsie benchmark center의 cluster에서 LSF를 이용해 테스트를 수행하시는 분들을 위한 guide입니다.


먼저 별도로 통보받으신 VPN SW와 VPN id/passwd를 이용해 Poughkeepsie benchmark center cluster에 VPN 연결을 하셔야 합니다.

그 다음에, 이미 통보받으신대로 p10login4.pbm.ihost.com 라는 주소로 putty 등을 이용해 ssh 접속을 하십시요.   (아래 그림 참조)



접속할 때의 userid 및 passwd는 VPN id/passwd와는 별도로 통보받으신 userid/passwd (서버 linux OS용) 입니다.

p10login4에 접속하신 뒤, 먼저 anaconda3를 설치하시기 바랍니다.  설치하실 때 default로 제시되는 directory를 그대로 이용하시는 것이 좋습니다.  이유는 /gpfs/gpfs_gl4_16mb/ 밑의 directory가 GPFS(요즘 이름은 Spectrum Scale)라는 공유파일시스템로서 cluster 내의 모든 work node에 mount 되어 있는 것이기 때문입니다.  거기에 설치해야 나중에 어느 work node에서 job을 수행하더라도 이 anaconda를 사용하실 수 있습니다.

[b8p217za@p10login4 ~]$ wget https://repo.continuum.io/archive/Anaconda3-5.2.0-Linux-ppc64le.sh

[b8p217za@p10login4 ~]$ chmod a+x Anaconda3-5.2.0-Linux-ppc64le.sh

[b8p217za@p10login4 ~]$ ./Anaconda3-5.2.0-Linux-ppc64le.sh
...
[/gpfs/gpfs_gl4_16mb/b8p217/b8p217za/anaconda3] >>>
...
Do you wish the installer to prepend the Anaconda3 install location
to PATH in your /gpfs/gpfs_gl4_16mb/b8p217/b8p217za/.bashrc ? [yes|no]
[no] >>> yes

설치가 끝난 뒤에는 .bashrc을 다시 수행하셔서 기본 python이 anaconda3에서 나오는 것인지 확인하십시요.

[b8p217za@p10login4 ~]$ . /gpfs/gpfs_gl4_16mb/b8p217/b8p217za/.bashrc

[b8p217za@p10login4 ~]$ which python
~/anaconda3/bin/python

그 다음으로는 tensorflow 운용에 필요한 dependent package들을 설치하셔야 합니다.  다음의 명령을 내리시면 됩니다.

[b8p217za@p10login4 ~]$ /opt/DL/tensorflow/bin/install_dependencies
...

The following NEW packages will be INSTALLED:

    absl-py:                    0.1.10-py36_0              file://opt/DL/conda-pkgs
    astor:                      0.6.2-py_0                 file://opt/DL/conda-pkgs
    blas:                       1.0-openblas
    gast:                       0.2.0-py36_0               file://opt/DL/conda-pkgs
    grpcio:                     1.10.0-py36hf484d3e_0      file://opt/DL/conda-pkgs
    libprotobuf:                3.5.0-hf484d3e_0           file://opt/DL/conda-pkgs
    powerai-tensorflow-prereqs: 1.8.0_31721.7987738-py36_0 file:///opt/DL/tensorflow/conda-pkgs
    protobuf:                   3.5.0-py36_0               file://opt/DL/conda-pkgs
    termcolor:                  1.1.0-py36_0               file://opt/DL/conda-pkgs
    toposort:                   1.5-py36_0                 file://opt/DL/conda-pkgs
...
Proceed ([y]/n)? y


이제 tensorflow를 사용하시기 위해 환경변수 설정 script를 다음과 같이 수행하십시요.   이 script를 수행하시면 아래와 같이 PATH, PYTHONPATH들이 설정되면서 PowerAI에 포함된 tensorflow를 사용하실 수 있게 됩니다.

[b8p217za@p10login4 ~]$ source /opt/DL/tensorflow/bin/tensorflow-activate

[b8p217za@p10login4 ~]$ env | grep PATH
MANPATH=/vol/ibmplatform/lsf/10.1/man:/usr/share/lmod/lmod/share/man::
MODULEPATH_ROOT=/gpfs/gpfs_gl4_16mb/lmod/P8
LD_LIBRARY_PATH=/vol/ibmplatform/lsf/10.1/linux3.10-glibc2.17-ppc64le/lib:/usr/local/cuda-9.2/lib64:/usr/local/cuda-9.2/extras/CUPTI/lib64:/opt/DL/tensorflow/lib
PATH=/gpfs/gpfs_gl4_16mb/b8p217/b8p217za/anaconda3/bin:/vol/ibmplatform/lsf/10.1/linux3.10-glibc2.17-ppc64le/etc:/vol/ibmplatform/lsf/10.1/linux3.10-glibc2.17-ppc64le/bin:/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/opt/ibutils/bin:/gpfs/gpfs_gl4_16mb/b8p217/b8p217za/.local/bin:/gpfs/gpfs_gl4_16mb/b8p217/b8p217za/bin:/opt/DL/tensorflow/bin
MODULEPATH=/etc/modulefiles:/usr/share/modulefiles:/gpfs/gpfs_gl4_16mb/lmod/P8/Linux:/gpfs/gpfs_gl4_16mb/lmod/P8/Core:/gpfs/gpfs_gl4_16mb/lmod/P8/rhel/7.5/core
PYTHONPATH=/opt/DL/tensorflow/lib/python3.6/site-packages:/opt/DL/tensorflow/lib/python3.6/site-packages/external/protobuf_archive/python:/opt/DL/tensorflow/lib/python3.6/site-packages/external/six_archive

이제 tensorflow를 사용하실 준비가 끝났습니다.   그러나 이 서버에서 직접 tensorflow training을 수행하시면 안 됩니다.  이 서버는 어디까지나 login 서버일 뿐, V100이 장착된 AC922 서버가 아닙니다.  다음과 같이 job scheduler인 LSF에게 job을 submit 하는 방식으로 training을 수행하셔야 합니다.

먼저, 수행하실 tensorflow python code를 확인하십시요.   여기서는 아래의 cnn_mnist_lms.py를 LSF로 수행하는 것을 해보겠습니다.  참고로, 이 cnn_mnist_lms.py는 /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/examples/tutorials/layers/cnn_mnist.py를 LMS로 변환한 example code입니다.

[b8p217za@p10login4 ~]$ ls -l /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py
-rw-r--r-- 1 root root 6203 Jun  5 08:31 /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py

위 code를 LSF로 수행하시려면 다음과 같이 하시면 됩니다.   즉 아래의 파란색 부분만 덧붙이시면 됩니다.

[b8p217za@p10login4 ~]$ bsub -R "rusage[ngpus_excl_p=4]" -q ac922_v100 -o ./1.out -e ./1.err python /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py
Job <243511> is submitted to queue <ac922_v100>.

-q는 queue 이름입니다.  안내받으신 대로 ac922_v100을 쓰시면 됩니다.  -o는 output file을, -e는 error message file을 지정합니다.

결과물은 위에서 지정한 대로라면 login 서버의 현재 directory에 1.out이라는 file에 저장되고, 혹시 error가 생겼다면 그 메시지는 1.err라는 file에 저장됩니다.

그리고 "rusage[ngpus_excl_p=4]" 라는 것은 GPU 4개를 exclusive mode로 쓰려고 하니 가용한 GPU 개수가 4개인 서버에서 수행하라는 뜻입니다.  만약 1개만 쓰실 거라면 그 숫자를 1로 지정하시면 됩니다.  만약 MPI로 작성하신 code를 mpirun 명령을 통해 돌리시는 거라면, AC922 1대에 설치된 GPU 개수가 4장이지만 ngpus_excl_p=8 또는 12 등 4보다 더 큰 숫자로 두셔도 됩니다.  물론 보통의 deep learning training에서는 4개 이하를 쓰시겠지요.

위의 job number에 대해서 bhist 명령을 내리면 job이 어느 work node로 allocation되었는지 또 언제 시작되었고 (만약 끝났다면) 언제 끝났는지 알 수 있습니다.  아래의 경우는 p10a02라는 work node에 할당되었으나, 뭔가 문제가 있어서 시작된지 6초만에 fail 났습니다.

[b8p217za@p10login4 ~]$ bhist -l 243511

Job <243511>, User <b8p217za>, Project <default>, Command <python /opt/DL/tenso
                     rflow/lib/python3.6/site-packages/tensorflow/contrib/lms/e
                     xamples/cnn_mnist_lms.py>
Wed Sep  5 22:45:59: Submitted from host <p10login4>, to Queue <ac922_v100>, CW
                     D <$HOME>, Output File <./1.out>, Error File <./1.err>, Re
                     quested Resources <rusage[ngpus_excl_p=4]>;
Wed Sep  5 22:45:59: Dispatched 1 Task(s) on Host(s) <p10a02>, Allocated 1 Slot
                     (s) on Host(s) <p10a02>, Effective RES_REQ <select[type ==
                      local] order[r15s:pg] rusage[ngpus_excl_p=4.00] >;
Wed Sep  5 22:46:00: Starting (Pid 7426);
Wed Sep  5 22:46:06: External Message "p10a02:gpus=0,1,2,3;" was posted from "b
                     8p217za" to message box 0;
Wed Sep  5 22:46:06: Running with execution home </gpfs/gpfs_gl4_16mb/b8p217/b8
                     p217za>, Execution CWD </gpfs/gpfs_gl4_16mb/b8p217/b8p217z
                     a>, Execution Pid <7426>;
Wed Sep  5 22:46:06: Exited with exit code 2. The CPU time used is 0.4 seconds;
Wed Sep  5 22:46:06: Completed <exit>;

MEMORY USAGE:
MAX MEM: 7 Mbytes;  AVG MEM: 7 Mbytes

Summary of time in seconds spent in various states by  Wed Sep  5 22:46:06
  PEND     PSUSP    RUN      USUSP    SSUSP    UNKWN    TOTAL
  0        0        7        0        0        0        7

Error가 난 이유는 아래와 같이 해당 example code가 work node인 p10a02 서버의 local directory에 설치되어 있지 않기 때문입니다.

[b8p217za@p10login4 ~]$ cat 1.err
python: can't open file '/opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py': [Errno 2] No such file or directory

위 error를 수정하기 위해 POK center에 연락하여 각 node들에서 # yum install power-mldl-py3로 필요 fileset들의 update를 요청했습니다.   (sudo 권한이 필요한 일입니다.)

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

POK center로부터 update 수행했다는 연락을 받았고, 다시 수행해본 수행 결과는 아래와 같습니다.

[b8p217za@p10login4 ~]$ bsub -R "rusage[ngpus_excl_p=4]" -q ac922_v100 -o ./1.out -e ./1.err python /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py
Job <244143> is submitted to queue <ac922_v100>.


[b8p217za@p10login4 ~]$ bhist -l 244143

Job <244143>, User <b8p217za>, Project <default>, Command <python /opt/DL/tenso
                     rflow/lib/python3.6/site-packages/tensorflow/contrib/lms/e
                     xamples/cnn_mnist_lms.py>
Thu Sep  6 21:27:03: Submitted from host <p10login4>, to Queue <ac922_v100>, CW
                     D <$HOME>, Output File <./1.out>, Error File <./1.err>, Re
                     quested Resources <rusage[ngpus_excl_p=4]>;
Thu Sep  6 21:27:04: Dispatched 1 Task(s) on Host(s) <p10a01>, Allocated 1 Slot
                     (s) on Host(s) <p10a01>, Effective RES_REQ <select[type ==
                      local] order[r15s:pg] rusage[ngpus_excl_p=4.00] >;
Thu Sep  6 21:27:05: Starting (Pid 76857);
Thu Sep  6 21:27:12: External Message "p10a01:gpus=0,1,2,3;" was posted from "b
                     8p217za" to message box 0;
Thu Sep  6 21:27:12: Running with execution home </gpfs/gpfs_gl4_16mb/b8p217/b8
                     p217za>, Execution CWD </gpfs/gpfs_gl4_16mb/b8p217/b8p217z
                     a>, Execution Pid <76857>;
Thu Sep  6 21:29:28: Done successfully. The CPU time used is 204.2 seconds;
Thu Sep  6 21:29:35: Post job process done successfully;

MEMORY USAGE:
MAX MEM: 4.2 Gbytes;  AVG MEM: 3 Gbytes

Summary of time in seconds spent in various states by  Thu Sep  6 21:29:35
  PEND     PSUSP    RUN      USUSP    SSUSP    UNKWN    TOTAL
  1        0        144      0        0        0        145


1초 만에 "p10a01" node로 dispatch 되어 2분 16초 만에 성공적으로 training을 완료했습니다.  

결과물이 저장되는 1.out 파일을 열어보면 아래와 같은 내용이 담겨 있습니다.  


[b8p217za@p10login4 ~]$ cat 1.out

Sender: LSF System <p10lsf@p10a01>
Subject: Job 244143: <python /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py> in cluster <pok_tc_cloud> Done

Job <python /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py> was submitted from host <p10login4> by user <b8p217za> in cluster <pok_tc_cloud> at Thu Sep  6 21:27:03 2018.
Job was executed on host(s) <p10a01>, in queue <ac922_v100>, as user <b8p217za> in cluster <pok_tc_cloud> at Thu Sep  6 21:27:04 2018.
</gpfs/gpfs_gl4_16mb/b8p217/b8p217za> was used as the home directory.
</gpfs/gpfs_gl4_16mb/b8p217/b8p217za> was used as the working directory.
Started at Thu Sep  6 21:27:04 2018.
Terminated at Thu Sep  6 21:29:29 2018.
Results reported at Thu Sep  6 21:29:29 2018.

Your job looked like:

------------------------------------------------------------
# LSBATCH: User input
python /opt/DL/tensorflow/lib/python3.6/site-packages/tensorflow/contrib/lms/examples/cnn_mnist_lms.py
------------------------------------------------------------

Successfully completed.

Resource usage summary:

    CPU time :                                   204.17 sec.
    Max Memory :                                 4393 MB
    Average Memory :                             3106.20 MB
    Total Requested Memory :                     -
    Delta Memory :                               -
    Max Swap :                                   -
    Max Processes :                              3
    Max Threads :                                346
    Run time :                                   147 sec.
    Turnaround time :                            146 sec.

The output (if any) follows:

Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Extracting MNIST-data/train-images-idx3-ubyte.gz
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Extracting MNIST-data/train-labels-idx1-ubyte.gz
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Extracting MNIST-data/t10k-images-idx3-ubyte.gz
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting MNIST-data/t10k-labels-idx1-ubyte.gz
Saving graph to: /tmp/tmpeuq76pnh
{'accuracy': 0.96890002, 'loss': 0.10233325, 'global_step': 20000}


PS:

Read file <./1.err> for stderr output of this job.


그리고 training 과정 중의 메시지는 아래와 같이 1.err에 저장됩니다.   여기서는 일부만 copy & paste 했습니다.

[b8p217za@p10login4 ~]$ cat 1.err
...
INFO:tensorflow:Saving checkpoints for 20000 into /tmp/tmpeuq76pnh/model.ckpt.
INFO:tensorflow:Loss for final step: 0.103957.
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-09-07-01:29:27
INFO:tensorflow:Graph was finalized.
2018-09-06 21:29:27.207180: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1435] Adding visible gpu devices: 0, 1, 2, 3
2018-09-06 21:29:27.207305: I tensorflow/core/common_runtime/gpu/gpu_device.cc:923] ...
2018-09-06 21:29:27.208973: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1053] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:3 with 14127 MB memory) -> physical GPU (device: 3, name: Tesla V100-SXM2-16GB, pci bus id: 0035:04:00.0, compute capability: 7.0)
INFO:tensorflow:Restoring parameters from /tmp/tmpeuq76pnh/model.ckpt-20000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Finished evaluation at 2018-09-07-01:29:27
INFO:tensorflow:Saving dict for global step 20000: accuracy = 0.9689, global_step = 20000, loss = 0.102333


2018년 8월 30일 목요일

무료 ppc64le Cloud - Power Development Cloud (PDC)


x86 기반으로 개발한 code를 ppc64le 기반의 Redhat/Ubuntu/SuSE 등으로 포팅 및 컴파일하려면 일단 ppc64le 기반의 개발 장비가 필요합니다.

이런 용도로 사용하실 수 있는 무료 ppc64le linux Cloud가 이미 있습니다.   IBM에서 제공하는 Power Development Cloud (PDC)입니다.

이는 POWER8 1-core짜리의 작은 가상머신을 2주간 무료로 사용할 수 있도록 해주는 platform 입니다.  2주가 끝난 뒤에는 다시 또 신청하면 다시 2주간 더 사용할 수 있습니다.  단, 사용하던 disk의 내용은 일단 지워지는데, 지워지기 전에 "Save Image" 기능을 이용하여 save 해놓았다가 가상머신을 재신청할 때 그 saved image를 이용하여 가상머신을 달라고 요청하면 기존 image를 그대로 또 사용하실 수 있습니다.

신청을 하기 위해서는 먼저 IBM PartnerWorld에 회원으로 가입하셔야 합니다.   신청 및 가상머신 신청은 아래 URL에서 하시면 됩니다.

https://www-356.ibm.com/partnerworld/wps/servlet/ContentHandler/stg_com_sys_power-development-platform

위 URL에서 가운데의 "Go to the Program to get started"를 클릭하시면 됩니다.   그러면 VPN 설치 후에 ssh로 연결될 수 있는 가상머신의 IP와 passwd가 제공됩니다.   신청부터 실제 access까지는 통상 2~3시간 정도가 걸리는 것 같습니다.

아쉬운 점은 disk size가 35GB로 제한되어 있다는 점입니다.  써보면 항상 이 부분이 가장 아쉽던데, 공짜이니 그 정도도 고맙게 쓰고 있습니다.







2018년 8월 28일 화요일

nvidia-docker를 위한 Redhat 7.5 ppc64le docker image의 build


** 이 문서에서 서술하는 방식으로 만든 이미지들의 완성본을 다음의 주소에서 받으실 수 있습니다.   IBM GPU 서버인 AC922이나 Minsky 서버를 위한 Redhat 7.5 ppc64le + CUDA 9.2 + cudnn 7.2.1 + NCCL 2.2 + PowerAI 5.2 + Anaconda 2 (py2) or Anaconda3 (py3) 기반으로 만들어진 이미지들입니다.

https://hub.docker.com/r/bsyu/rhel75_ppc64le_cuda92_all_py2_powerai52/
https://hub.docker.com/r/bsyu/rhel75_ppc64le_cuda92_all_py3_powerai52/

Pull 할 때는 다음과 같이 하시면 됩니다.

# docker pull bsyu/rhel75_ppc64le_cuda92_all_py2_powerai52:v0.4     (python2.7)
# docker pull bsyu/rhel75_ppc64le_cuda92_all_py3_powerai52:v0.3     (python3.6)

아래는 이 docker image들을 만들 때의 과정입니다.

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

먼저, 현재 host 서버의 OS(여기서는 Redhat 7.5 ALT ppc64le)를 기반으로 docker base image를 만듭니다.  아래 github에서 제공되는 mkimage-yum.sh를 사용하면 쉽습니다.

https://github.com/moby/moby/blob/master/contrib/mkimage-yum.sh

[root@ING ~]# cd docker

[root@ING docker]# vi mkimage-yum.sh    #  https://github.com/moby/moby/blob/master/contrib/mkimage-yum.sh의 script를 copy & paste

[root@ING docker]# chmod +x mkimage-yum.sh

[root@ING docker]# ./mkimage-yum.sh baserehel75alt
...
Running transaction
  Installing : libgcc-4.8.5-28.el7_5.1.ppc64le                                                                         1/243
  Installing : redhat-release-server-7.5-7.el7a.ppc64le                                                                2/243
  Installing : setup-2.8.71-9.el7.noarch                                                                               3/243
  Installing : filesystem-3.2-25.el7.ppc64le                                                                           4/243
  Installing : tzdata-2018e-3.el7.noarch                                                                               5/243
  Installing : basesystem-10.0-7.el7.noarch                                                                            6/243
...
  xz-libs.ppc64le 0:5.2.2-1.el7                                       yum-metadata-parser.ppc64le 0:1.1.4-10.el7
  zlib.ppc64le 0:1.2.7-17.el7

Complete!
+ [[ -n '' ]]
+ yum -c /etc/yum.conf --installroot=/tmp/mkimage-yum.sh.Oh71td -y clean all
Loaded plugins: langpacks, product-id, search-disabled-repos, subscription-manager
This system is not registered with an entitlement server. You can use subscription-manager to register.
There are no enabled repos.
 Run "yum repolist all" to see the repos you have.
 To enable Red Hat Subscription Management repositories:
     subscription-manager repos --enable <repo>
 To enable custom repositories:
     yum-config-manager --enable <repo>

Script가 위와 같이 성공적으로 완료된 뒤에 message에 표시된 /tmp 밑의 directory로 가보면 아래와 같이 mini-OS image가 마련되어 있는 것을 보실 수 있습니다. 
이제 이걸 tar로 말아올린 뒤 docker import 명령으로 import 해주면 됩니다.

[root@ING docker]# cd /tmp/mkimage-yum.sh.Oh71td

[root@ING mkimage-yum.sh.Oh71td]# ls -ltr
total 12
dr-xr-xr-x  2 root root    6 Dec 15  2017 sys
drwxr-xr-x  2 root root    6 Dec 15  2017 srv
dr-xr-xr-x  2 root root    6 Dec 15  2017 proc
drwxr-xr-x  2 root root    6 Dec 15  2017 opt
drwxr-xr-x  2 root root    6 Dec 15  2017 mnt
drwxr-xr-x  2 root root    6 Dec 15  2017 media
drwxr-xr-x  2 root root    6 Dec 15  2017 home
drwxr-xr-x  2 root root  180 Dec 15  2017 dev
dr-xr-xr-x  2 root root    6 Dec 15  2017 boot
lrwxrwxrwx  1 root root    7 Aug  9 09:47 bin -> usr/bin
lrwxrwxrwx  1 root root    8 Aug  9 09:47 sbin -> usr/sbin
lrwxrwxrwx  1 root root    9 Aug  9 09:47 lib64 -> usr/lib64
lrwxrwxrwx  1 root root    7 Aug  9 09:47 lib -> usr/lib
drwxr-xr-x 13 root root  207 Aug  9 09:47 usr
drwxrwxrwt  7 root root  117 Aug  9 09:47 tmp
drwxr-xr-x 19 root root  335 Aug  9 09:47 var
drwxr-xr-x 15 root root  261 Aug  9 09:47 run
drwxr-xr-x 68 root root 8192 Aug  9 09:47 etc
dr-xr-x---  2 root root   91 Aug  9 09:47 root

[root@ING mkimage-yum.sh.Oh71td]# tar -zcf /tmp/rhel7_ppc64le.tar.gz .

[root@ING mkimage-yum.sh.Oh71td]# ls -l /tmp/rhel7_ppc64le.tar.gz
-rw-r--r-- 1 root root 224266718 Aug  9 10:15 /tmp/rhel7_ppc64le.tar.gz

[root@ING mkimage-yum.sh.Oh71td]# docker import /tmp/rhel7_ppc64le.tar.gz bsyu/rhel75_ppc64le:base

[root@ING mkimage-yum.sh.Oh71td]# docker images
REPOSITORY                 TAG                         IMAGE ID            CREATED             SIZE
bsyu/rhel75_ppc64le        base                        3bf1baa60960        4 seconds ago       715 MB

이제 이 base image를 기반으로 dockerfile을 편집해서 CUDA 명령을 쓸 수 있는 nvidia-docker image를 만들면 됩니다.

그러기 위해서는 먼저 이 docker base image에서도 yum 명령을 써야 하는데, 기본적으로 Redhat에서 제공되는 /etc/yum.repos.d/redhat.repo 파일은 매번 yum을 기동할 때마다 자동으로 blank로 reset 되어버립니다.   따라서 이 파일 이름말고, 다른 이름, 가령 /etc/yum.repos.d/new.repo라는 이름으로 host OS에 있는 /etc/yum.repos.d/redhat.repo 파일을 그대로 저장해두면 host OS에서처럼 외부 YUM repository를 자유롭게 쓸 수 있습니다.   물론 이때 /etc/pki/entitlement/*-key.pem 등의 필요 ceritificate 파일들도 함께 docker image 속의 /etc/pki/entitlement에 copy 해두어야 합니다.   가령 다음과 같이 하면 됩니다.

[bsyu@p57a22 ~]# docker run -ti --rm -v /etc:/mnt bsyu/rhel75_ppc64le:base bash

----inside docker container------

[root@7e3b00f3fac2 ~]# cp /mnt/pki/entitlement/*.pem /etc/pki/entitlement

[root@7e3b00f3fac2 ~]# cp /mnt/yum.repos.d/redhat.repo /etc/yum.repos.d/new.repo    # 절대 redhat.repo라는 이름으로 copy하면 안 됩니다.

[root@7e3b00f3fac2 ~]# rpm -Uvh /mnt/epel-release-7-11.noarch.rpm   # epel-release-7-11.noarch.rpm 파일의 경우 host의 /etc 밑에 미리 copy해둡니다.

[root@7e3b00f3fac2 ~]# yum install wget curl cmake cmake3 make automake autoconf bzip2 zip unzip git gcc gcc-c++ gfortran yum-utils   # 기본적으로 필요한 package들을 미리 설치해둡니다.

----outside docker container------

[bsyu@p57a22 ~]# docker ps
CONTAINER ID        IMAGE                   COMMAND             CREATED             STATUS              PORTS              NAMES
7e3b00f3fac2        bsyu/rhel75_ppc64le:base bash   "bash"              23 hours ago        Up 23 hours                  angry_bose

[bsyu@p57a22 ~]# docker commit 7e3b00f3fac2 bsyu/rhel75_ppc64le:base_v6

이제 dockerfile을 이용하여 nvidia-docker 이미지를 만듭니다.  먼저 (다른 이름도 상관없습니다만) docker라는 directory를 만들고, 거기에 docker image 속에 설치할 cuda*.rpm 등을 미리 copy 해둡니다.  그리고나서 dockerfile.cuda92 파일을 다음과 같이 만듭니다.

[bsyu@p57a22 ~]# mkdir /home/docker && cd /home/docker   

[root@p57a22 docker]# vi dockerfile.cuda92
FROM bsyu/rhel75_ppc64le:base_v6

# Update image
# 'local' means rhel local repository
# To use these repos below in building process, you must set up the RHEL subscription and enable these repos on your host system first.
RUN yum-config-manager --enable rhel-7-for-power-9-rpms/7Server/ppc64le
RUN yum-config-manager --enable rhel-7-for-power-9-optional-rpms/7Server/ppc64le
RUN yum-config-manager --enable rhel-7-for-power-9-extras-rpms/7Server/ppc64le
RUN yum-config-manager --enable epel/ppc64le

RUN mkdir /tmp/temp
COPY cuda-repo-rhel7-9-2-local* /tmp/temp/
RUN rpm -Uvh /tmp/temp/cuda-repo-rhel7-9-2-local*
RUN yum install -y cuda

# nvidia-docker 1.0
LABEL com.nvidia.volumes.needed="nvidia_driver"
LABEL com.nvidia.cuda.version="${CUDA_VERSION}"

RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf && \
    echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf

ENV PATH /usr/local/nvidia/bin:/usr/local/cuda/bin:${PATH}
ENV LD_LIBRARY_PATH /usr/local/nvidia/lib:/usr/local/nvidia/lib64:/usr/local/cuda/lib64/stubs

# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV NVIDIA_REQUIRE_CUDA "cuda>=9.2"

RUN yum clean all &&  rm -rf /var/cache/yum/* /tmp/temp
RUN rpm -e cuda-repo-rhel7-9-2-local

이제 위의 dockerfile.cuda92 파일을 이용하여 다음과 같이 bsyu/rhel75_ppc64le_cuda92_all:v0.1라는 이름으로 docker image를 build합니다.

[root@p57a22 docker]# docker build -t bsyu/rhel75_ppc64le_cuda92_all:v0.1 -f dockerfile.cuda92 .
Sending build context to Docker daemon 1.705 GB
Step 1/24 : FROM docker.io/bsyu/rhel75_ppc64le:base_v5
 ---> fc88cbad6b18
....
Cleaning up everything
Maybe you want: rm -rf /var/cache/yum, to also free up space taken by orphaned data from disabled or removed repos
 ---> f26c0a2167a0
Removing intermediate container bb911c868f27
Step 26/26 : RUN rpm -e cuda-repo-rhel7-9-2-local
 ---> Running in 6bceb027f2f1

 ---> deaf06286bf4
Removing intermediate container 6bceb027f2f1
Successfully built deaf06286bf4

다음과 같이 지정한 이름의 docker image가 생성된 것을 확인합니다.

[root@p57a22 docker]# docker images | grep bsyu
bsyu/rhel75_ppc64le_cuda92_all                 v0.1                        deaf06286bf4        45 seconds ago      8.11 GB
bsyu/rhel75_ppc64le                       base_v6                     872374a229f2        8 minutes ago       1.35 GB

이제 nvidia-docker로 이 image를 구동하여 nvidia-smi가 제대로 작동하는지 확인합니다.   그리고 PowerAI나 libcudnn* libnccl2* 등 필요 SW를 더 설치한 뒤 commit 하여 필요한 image를 추가로 만듭니다.

[bsyu@p57a22 data]$ nvidia-docker run -ti --rm -v /home/bsyu/files:/mnt bsyu/rhel75_ppc64le_cuda92_all:v0.1 bash

----inside docker container------

[root@e8a6f36fb132 /]# nvidia-smi
Thu Aug 23 01:28:52 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 396.26                 Driver Version: 396.26                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000002:01:00.0 Off |                    0 |
| N/A   28C    P0    29W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  Off  | 00000003:01:00.0 Off |                    0 |
| N/A   30C    P0    32W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  Off  | 0000000A:01:00.0 Off |                    0 |
| N/A   28C    P0    29W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  Off  | 0000000B:01:00.0 Off |                    0 |
| N/A   31C    P0    29W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+