2018년 10월 15일 월요일

Python Image Library(PIL, Pillow)의 성능 테스트

Python Image Library (PIL, python3에서는 pillow)을 이용하여 python에서 image 생성/변경 등이 가능합니다.  그리고, 이 성능 평가를 위해서는 pillow-perf라는 code를 이용할 수 있습니다.   먼저 pillow-perf를 git으로부터 clone 합니다.

[root@python1 ~]# git clone https://github.com/python-pillow/pillow-perf.git

아래와 같이 pip로 필요 package들을 설치합니다.

[root@python1 ~]# cd pillow-perf/testsuite/

[root@python1 testsuite]# pip install -r ./requirements.txt

이제 다음과 같이 몇가지 테스트를 수행해봅니다.   아래의 결과는 Naver nCloud에서 제공되는 E5-2660 v4@2.00GHz에서 수행된 것입니다.  이 테스트는 single-thread로 되어 있고, IBM POWER8/POWER9에서도 동일한 방법으로 수행할 수 있습니다.

[root@python1 testsuite]#  ./run.py scale --progress

Scale 2560×1600 RGB image
    to 26x16 bil        0.01323 s   309.62 Mpx/s
    to 26x16 bic        0.02488 s   164.62 Mpx/s
    to 26x16 lzs        0.03783 s   108.28 Mpx/s
    to 320x200 bil      0.02107 s   194.43 Mpx/s
    to 320x200 bic      0.03579 s   114.45 Mpx/s
    to 320x200 lzs      0.05393 s    75.95 Mpx/s
    to 2048x1280 bil    0.05956 s    68.77 Mpx/s
    to 2048x1280 bic    0.08711 s    47.02 Mpx/s
    to 2048x1280 lzs    0.12037 s    34.03 Mpx/s
    to 5478x3424 bil    0.28072 s    14.59 Mpx/s
    to 5478x3424 bic    0.38422 s    10.66 Mpx/s
    to 5478x3424 lzs    0.49239 s     8.32 Mpx/s

[root@python1 testsuite]# ./run.py scale --mode RGBA

Scale 2560×1600 RGBA image
    to 26x16 bil        0.02508 s   163.33 Mpx/s
    to 26x16 bic        0.04012 s   102.09 Mpx/s
    to 26x16 lzs        0.05564 s    73.62 Mpx/s
    to 320x200 bil      0.03434 s   119.29 Mpx/s
    to 320x200 bic      0.04993 s    82.04 Mpx/s
    to 320x200 lzs      0.07300 s    56.11 Mpx/s
    to 2048x1280 bil    0.10238 s    40.01 Mpx/s
    to 2048x1280 bic    0.13699 s    29.90 Mpx/s
    to 2048x1280 lzs    0.18249 s    22.44 Mpx/s
    to 5478x3424 bil    0.51842 s     7.90 Mpx/s
    to 5478x3424 bic    0.63934 s     6.41 Mpx/s
    to 5478x3424 lzs    0.78471 s     5.22 Mpx/s

[root@python1 testsuite]# ./run.py scale --runs 50

Scale 2560×1600 RGB image
    to 26x16 bil        0.01308 s   313.08 Mpx/s
    to 26x16 bic        0.02493 s   164.28 Mpx/s
    to 26x16 lzs        0.03770 s   108.64 Mpx/s
    to 320x200 bil      0.02115 s   193.62 Mpx/s
    to 320x200 bic      0.03549 s   115.42 Mpx/s
    to 320x200 lzs      0.05399 s    75.87 Mpx/s
    to 2048x1280 bil    0.05944 s    68.91 Mpx/s
    to 2048x1280 bic    0.08735 s    46.89 Mpx/s
    to 2048x1280 lzs    0.12058 s    33.97 Mpx/s
    to 5478x3424 bil    0.28272 s    14.49 Mpx/s
    to 5478x3424 bic    0.38564 s    10.62 Mpx/s
    to 5478x3424 lzs    0.49298 s     8.31 Mpx/s

[root@python1 testsuite]# ./run.py blur

Blur 2560×1600 RGB image
    1px                 0.22742 s    18.01 Mpx/s
    10px                0.22500 s    18.20 Mpx/s
    30px                0.22543 s    18.17 Mpx/s

[root@python1 testsuite]# ./run.py convert

Convert 2560×1600 RGB image
    RGB to L            0.00539 s   760.07 Mpx/s
    RGBA to LA          0.00652 s   627.90 Mpx/s
    RGBa to RGBA        0.03590 s   114.08 Mpx/s
    RGBA to RGBa        0.00851 s   481.57 Mpx/s


그 외에, 실제 jpg 파일들을 이용하여 몇가지 PIL 처리를 하는 sample code를 수행해보는 것도 괜찮습니다.

[root@python1 ~]# cat piljpg.py
from PIL import Image, ImageFilter
list = [ "1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg", "7.jpg", "8.jpg", "9.jpg", "10.jpg" ]
for x in list:
    im = Image.open(x)
    print(im.size)
    im.save('pasta.jpg')
    im = Image.open(x)
    size = (64, 64)
    im.thumbnail(size)
    im.save('python-thumb.jpg')
    im = Image.open(x)
    cropImage = im.crop((100, 100, 150, 150))
    cropImage.save('python-crop.png')
    im = Image.open(x)
    img2 = im.resize((600, 600))
    img2.save('python-600.jpg')
    img3 = im.rotate(90)
    img3.save('rotate.jpg')
    im = Image.open(x)
    blurImage = im.filter(ImageFilter.BLUR)
    blurImage.save('python-blur.jpg')


[root@python1 ~]# time python piljpg.py
(2281, 3072)
(972, 1422)
(972, 1422)
(972, 1422)
(972, 1422)
(972, 1422)
(5040, 4912)
(1600, 1280)
(2281, 3072)
(972, 1422)

real    0m15.047s
user    0m14.759s
sys     0m0.285s


piljpg.py의 코드와 거기에 쓰인 *.jpg 파일은 아래 구글 드라이브에 올려놓았습니다.

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

2018년 10월 11일 목요일

Python을 위한 local private repository 만들기 (bandersnatch + nginx)

Python은 그 특성상 필요에 따라 자주 새로운 package를 설치해서 써야 하는데, 이를 위해서는 해당 서버가 443번 포트를 통해 인터넷에 연결되어 있는 환경이어야 합니다.  그러나 실제로는 대부분의 기업용 data center들에서는 인터넷과의 연결이 완전히 단절되어 있으므로 python을 쓰기에 매우 불편합니다.   이는 x86이든 ppc64le이든 arm이든 모든 CPU 아키텍처에서 공통적으로 골치아파하는 문제이며, 국내 대기업들은 물론 해외 유명 인터넷 업체에서도 다 공통적으로 겪는 문제입니다.  가령 Pillow라는 package를 import해서 쓰려면 먼저 그 package를 설치해야 하는데, pip 명령으로 설치하면 아래처럼 그때그때 인터넷에서 source를 download 받아서 즉석에서 build해서 설치합니다.


[bsyu@p57a22 ~]$ pip install Pillow
Collecting Pillow
  Downloading https://files.pythonhosted.org/packages/1b/e1/1118d60e9946e4e77872b69c58bc2f28448ec02c99a2ce456cd1a272c5fd/Pillow-5.3.0.tar.gz (15.6MB)
    100% |████████████████████████████████| 15.6MB 11.6MB/s
Building wheels for collected packages: Pillow
  Running setup.py bdist_wheel for Pillow ... done
  Stored in directory: /home/bsyu/.cache/pip/wheels/df/81/28/47e761b5e307472ba7c2c5ced6e52037bbefe33c9c4b2a627e
Successfully built Pillow
Installing collected packages: Pillow
Successfully installed Pillow-5.3.0


이런 문제를 해결하는 왕도는 따로 없으나, 가장 근본적인 해결책은 외부망과 분리된 data center 내에 python을 위한 private local repository를 구성하는 것입니다.   다만 여기에는 2가지 문제가 있습니다.

1) Public python repository는 pypi.org (실제로는 files.pythonhosted.org) 인데, 전체 repository 크기가 800GB가 넘고, 날마다 계속 커지고 있습니다.

2) 기존 python package들의 새버전과, 또 아예 새로 만들어지는 python package들이 날마다 쏟아져 나오므로 주기적으로 자주 update를 해줘야 합니다.

보통 1번 문제는 (돈 있는 기업들 입장에서는) 큰 문제가 아닙니다.  Local repository server에 넉넉한 크기의 disk를 쓰면 되기 때문입니다.   문제는 2번 문제인데, 이것도 뾰족한 방법은 없고 외부에서 (1달에 1번 정도) 주기적으로 pypi.org의 내용을 backup 받아서 USB 외장 disk에 담아 data center로 들여온 뒤 local repository server에 부어주는 수 밖에 없습니다.

이런 정책만 정해지면 local repository server를 구성하는 것은 그다지 어렵지 않습니다.    다음과 같이 bandersnatch라는 package를 이용하면 쉽습니다.

아래의 모든 테스트는 ppc64le 아키텍처인 IBM POWER8 processor와 Redhat 7.5를 이용해서 수행되었습니다.  혹자는 x86_64를 위한 python repository는 어디 있는지 알겠는데 ppc64le를 위한 것은 어디 있냐고 여쭈시는 분도 있습니다만,  x86이나 ppc64le나 aarch64나 모두 같은 repository를 사용합니다. 


먼저, 다음과 같이 Anaconda3가 설치된 환경에서 pip로 bandersnatch를 설치합니다. 

[bsyu@p57a22 ~]$ which pip
~/anaconda3/bin/pip

[bsyu@p57a22 ~]$ pip install -r https://bitbucket.org/pypa/bandersnatch/raw/stable/requirements.txt
...
Successfully installed apipkg-1.4 bandersnatch-2.0.0 coverage-4.3.1 execnet-1.4.1 mock-2.0.0 packaging-16.8 pbr-1.10.0 pep8-1.7.0 py-1.4.32 pyflakes-1.3.0 pyparsing-2.1.10 pytest-3.0.5 pytest-cache-1.0 pytest-catchlog-1.2.2 pytest-codecheckers-0.2 pytest-cov-2.4.0 pytest-timeout-1.2.0 python-dateutil-2.6.0 requests-2.12.4 setuptools-33.1.1 six-1.10.0 xmlrpc2-0.3.1

[bsyu@p57a22 ~]$ which bandersnatch
~/anaconda3/bin/bandersnatch

그리고 'bandersnatch mirror' 명령을 수행합니다.   그러면 기본 /etc/bandersnatch.conf을 만들어줍니다.  이 때문에 이 명령은 일단 sudo 권한이 필요합니다.

[bsyu@p57a22 ~]$ sudo /home/bsyu/anaconda3/bin/bandersnatch mirror
2018-10-10 03:31:32,069 WARNING: Config file '/etc/bandersnatch.conf' missing, creating default config.
2018-10-10 03:31:32,069 WARNING: Please review the config file, then run 'bandersnatch' again.

이 /etc/bandersnatch.conf를 필요에 따라 수정합니다.  여기서는 어느 directory에 python repository를 내려받을 것인지만 수정했습니다.

[bsyu@p57a22 ~]$ sudo vi /etc/bandersnatch.conf
...
; directory = /srv/pypi
directory = /home/bsyu/files/pypi
...

다시 'bandersnatch mirror' 명령을 수행하면 정규 public repository (files.pythonhosted.org)를 통째로 download 받습니다.   800GB가 넘는다는 점에 유의하시기 바랍니다.  저도 끝까지 download 받아본 적은 없고, disk가 부족하여 도중에 끊어야 했습니다.

[bsyu@p57a22 ~]$ bandersnatch mirror
2018-10-10 03:33:35,064 INFO: bandersnatch/2.0.0 (cpython 3.7.0-final0, Linux ppc64le)
2018-10-10 03:33:35,064 INFO: Setting up mirror directory: /home/bsyu/files/pypi/
2018-10-10 03:33:35,064 INFO: Setting up mirror directory: /home/bsyu/files/pypi/web/simple
2018-10-10 03:33:35,064 INFO: Setting up mirror directory: /home/bsyu/files/pypi/web/packages
2018-10-10 03:33:35,064 INFO: Setting up mirror directory: /home/bsyu/files/pypi/web/local-stats/days
2018-10-10 03:33:35,064 INFO: Generation file missing. Reinitialising status files.
2018-10-10 03:33:35,065 INFO: Status file missing. Starting over.
2018-10-10 03:33:35,065 INFO: Syncing with https://pypi.python.org.
2018-10-10 03:33:35,065 INFO: Current mirror serial: 0
2018-10-10 03:33:35,065 INFO: Syncing all packages.
2018-10-10 03:33:37,934 INFO: Trying to reach serial: 4358961
2018-10-10 03:33:37,934 INFO: 154638 packages to sync.
...
2018-10-10 03:53:50,360 INFO: Downloading: https://files.pythonhosted.org/packages/8a/5c/625ac1a93da3a672f52d947023770331b958a1100cd9889b727cde5f7ba5/CommonMark-0.7.5-py2.py3-none-any.whl
2018-10-10 03:53:50,360 DEBUG: Getting https://files.pythonhosted.org/packages/8a/5c/625ac1a93da3a672f52d947023770331b958a1100cd9889b727cde5f7ba5/CommonMark-0.7.5-py2.py3-none-any.whl (serial None)
2018-10-10 03:53:50,363 INFO: Syncing package: CompCamps-Cash-Api (serial 4042164)
2018-10-10 03:53:50,363 DEBUG: Getting /pypi/CompCamps-Cash-Api/json (serial 4042164)
2018-10-10 03:53:50,370 INFO: Downloading: https://files.pythonhosted.org/packages/77/16/44a297228a439484d049cdad818c7f6691c162b4cd741c619caeb208bb1e/CommonMark-0.7.5.tar.gz
2018-10-10 03:53:50,371 DEBUG: Getting https://files.pythonhosted.org/packages/77/16/44a297228a439484d049cdad818c7f6691c162b4cd741c619caeb208bb1e/CommonMark-0.7.5.tar.gz (serial None)
...

이제 해당 directory에 가보면 다음과 같이 web/packages 밑에 실제 python package 파일들이 download 되어진 것을 보실 수 있습니다.   web/simple은 그 파일들에 대한 index directory입니다.

[bsyu@p57a22 ~]$ cd files/pypi

[bsyu@p57a22 pypi]$ ls
generation  todo  web

[bsyu@p57a22 pypi]$ cd web

[bsyu@p57a22 web]$ ls
local-stats  packages  simple

[bsyu@p57a22 web]$ cd packages/

[bsyu@p57a22 packages]$ ls
00  0b  16  21  2c  37  42  4e  59  64  6f  7a  85  90  9b  a6  b1  bc  c7  d2  dd  e8  f3  fe
01  0c  17  22  2d  38  43  4f  5a  65  70  7b  86  91  9c  a7  b2  bd  c8  d3  de  e9  f4  ff
02  0d  18  23  2e  39  44  50  5b  66  71  7c  87  92  9d  a8  b3  be  c9  d4  df  ea  f5
03  0e  19  24  2f  3a  45  51  5c  67  72  7d  88  93  9e  a9  b4  bf  ca  d5  e0  eb  f6
04  0f  1a  25  30  3b  46  52  5d  68  73  7e  89  94  9f  aa  b5  c0  cb  d6  e1  ec  f7
05  10  1b  26  31  3c  47  53  5e  69  74  7f  8a  95  a0  ab  b6  c1  cc  d7  e2  ed  f8
06  11  1c  27  32  3d  49  54  5f  6a  75  80  8b  96  a1  ac  b7  c2  cd  d8  e3  ee  f9
07  12  1d  28  33  3e  4a  55  60  6b  76  81  8c  97  a2  ad  b8  c3  ce  d9  e4  ef  fa
08  13  1e  29  34  3f  4b  56  61  6c  77  82  8d  98  a3  ae  b9  c4  cf  da  e5  f0  fb
09  14  1f  2a  35  40  4c  57  62  6d  78  83  8e  99  a4  af  ba  c5  d0  db  e6  f1  fc
0a  15  20  2b  36  41  4d  58  63  6e  79  84  8f  9a  a5  b0  bb  c6  d1  dc  e7  f2  fd


이렇게 download된 generation todo web의 3개 directory를 포함하는 python repository directory 전체 (여기서는 /home/bsyu/files/pypi)를 USB 외장 disk 등에 복사하여 local repository로 사용할 서버에 옮깁니다.   여기서는 편의상 그냥 download 받은 서버에서 직접 local repository 서버를 구성하겠습니다.

https을 통해서 다른 서버들에게 python repository 서비스를 하기 위해서는 당연히 web 서버를 구성해야 합니다.  여기서는 간단하게 nginx를 사용하겠습니다.  먼저 nginx를 YUM 명령으로 설치한 뒤, /etc/nginx/nginx.conf를 수정합니다.  단, 여기서 http(80번 포트)가 아닌 https(443번 포트)를 구성해야 합니다.  그리고 root를 복사한 directory 중 'web' directory로 정해야 하고, SSL certificate과 그 key도 등록해야 합니다.   server_name은 FQDN(Fully Qualified Domain Name)으로 합니다.  여기서는 IP address로 했습니다.

[bsyu@p57a22 ~]$ sudo yum install nginx

[bsyu@p57a22 ~]$ sudo vi /etc/nginx/nginx.conf
...
    server {
        listen       443 ssl http2 default_server;
        listen       [::]:443 ssl http2 default_server;
#        root         /usr/share/nginx/html;
        root         /home/bsyu/files/pypi/web;
        autoindex on;
        charset utf-8;

#        server_name  _;
        server_name  129.40.xx.xx;
        ssl_certificate "/etc/pki/nginx/private/domain.crt";
        ssl_certificate_key "/etc/pki/nginx/private/domain.key";
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
...

이제 SSL 구성을 위해 crt와 key를 생성합니다.  여기서는 1년간 유효한 Self-Signed Certificate (x509)를 만들었습니다.

[bsyu@p57a22 ~]$ cd /etc/pki/nginx/private

[root@p57a22 private]# openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
Generating a 2048 bit RSA private key
.......................................................................................+++++
..............................+++++
writing new private key to 'domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:.
State or Province Name (full name) [Some-State]:.
Locality Name (eg, city) []:.
Organization Name (eg, company) [Internet Widgits Pty Ltd]:.
Organizational Unit Name (eg, section) []:.
Common Name (e.g. server FQDN or YOUR name) []:129.40.xx.xx
Email Address []:.

[root@p57a22 private]# ls -ltr
total 8
-rw-r--r-- 1 root root 1704 Oct 11 00:13 domain.key
-rw-r--r-- 1 root root 1107 Oct 11 00:13 domain.crt

생성된 certificate과 key의 검사는 아래와 같이 할 수 있습니다. 

[root@p57a22 private]# openssl x509 -text -noout -in domain.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            a7:03:d9:7b:33:2d:53:7c
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=129.40.xx.xx
        Validity
            Not Before: Oct 11 04:13:00 2018 GMT
            Not After : Oct 11 04:13:00 2019 GMT
        Subject: CN=129.40.116.82
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:ca:73:3c:7f:e6:29:1e:5e:7b:ff:b5:98:30:ce:
                    fb:48:0e:bc:96:fd:5b:7f:1e:23:e5:62:8f:74:8e:
 ...

[root@p57a22 private]# openssl rsa -check -in domain.key
RSA key ok
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAynM8f+YpHl57/7WYMM77SA68lv1bfx4j5WKPdI6ftW2lRdrw
fUikVx0C+2ni3QB6y/xuT8yT0eiCPT5Ak4yGpDSsfcfzDOFgVSB02irWmX/KUNIS
/zS+E7SkAfariUEFa8iRjt2kmDpi65YGKH9NY7p136NcZOSZQx2wsAU0UM5Pjtci
....

이제 생성된 certificate과 key를 합해 PEM을 만듭니다. 

[root@p57a22 private]# cat domain.crt domain.key >> domain.pem

이제 nginx를 start 합니다.

[root@p57a22 private]# systemctl status nginx

그리고 pip에서 이 129.40.xx.xx를 trusted-host로 사용하도록 ~/.pip/pip.conf를 생성하여 다음과 같은 내용을 넣어줍니다.

[bsyu@p57a22 ~]$ vi .pip/pip.conf
[global]
trusted-host = 129.40.xx.xx
index = https://129.40.xx.xx:443/packages
index-url = https://129.40.xx.xx:443/simple
cert = /etc/pki/nginx/private/domain.pem

이제 CommonMark라는 package를 설치해봅니다.   기존처럼 files.pythonhosted.org가 아니라 129.40.xx.xx에서 package source를 가져오는 것을 보실 수 있습니다.

[bsyu@p57a22 ~]$ pip install CommonMark
Looking in indexes: https://129.40.xx.xx:443/simple
Collecting CommonMark
  Downloading https://129.40.xx.xx:443/packages/ab/ca/439c88039583a29564a0043186875258e9a4f041fb5c422cd387b8e10175/commonmark-0.8.1-py2.py3-none-any.whl (47kB)
    100% |████████████████████████████████| 51kB 37.8MB/s
Requirement already satisfied: future in ./anaconda3/lib/python3.7/site-packages (from CommonMark) (0.16.0)
Installing collected packages: CommonMark
Successfully installed CommonMark-0.8.1

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