2017년 10월 30일 월요일

ppc64le에서의 nvidia-docker의 설치 (2017.10)

전에 nvidia-docker를 ppc64le에서 build하는 방법을 올린 적(http://hwengineer.blogspot.kr/2017/02/minsky-ubuntu-1604-xenial-ppc64le.html)이 있습니다.   그 사이에 설치 방법이 업데이트가 된 것이 있어서, 새로 올립니다.

이 URL(https://developer.ibm.com/linuxonpower/docker-on-power)에 나온 가이드대로, 먼저 docker를 설치합니다.

u0017649@sys-89698:~$ sudo vi /etc/apt/sources.list.d/xenial-docker.list
deb http://ftp.unicamp.br/pub/ppc64el/ubuntu/16_04/docker-17.06.0-ce-ppc64el/ xenial main

u0017649@sys-89698:~$ sudo apt-get update

u0017649@sys-89698:~$ sudo apt-get install docker-ce

그 뒤에 아래와 같이 하시면 됩니다.

u0017649@sys-89698:~$ git clone https://github.com/NVIDIA/nvidia-docker.git

u0017649@sys-89698:~$ cd nvidia-docker/

u0017649@sys-89698:~/nvidia-docker$ sudo make
...
Step 21/22 : ENV VERSION $PKG_VERS
 ---> Using cache
 ---> 39d92843179c
Step 22/22 : CMD go install -v -ldflags="-s -X main.Version=$VERSION" ./...
 ---> Using cache
 ---> a66fd805e845
Successfully built a66fd805e845
Successfully tagged nvidia-docker:build
github.com/NVIDIA/nvidia-docker/src/nvidia-docker-plugin
github.com/NVIDIA/nvidia-docker/src/nvidia-docker


u0017649@sys-89698:~/nvidia-docker$ sudo make install
...
Step 21/22 : ENV VERSION $PKG_VERS
 ---> Using cache
 ---> 39d92843179c
Step 22/22 : CMD go install -v -ldflags="-s -X main.Version=$VERSION" ./...
 ---> Using cache
 ---> a66fd805e845
Successfully built a66fd805e845
Successfully tagged nvidia-docker:build
github.com/NVIDIA/nvidia-docker/src/nvidia-docker
github.com/NVIDIA/nvidia-docker/src/nvidia-docker-plugin
install -D -m 755 -t /usr/local/bin /home/u0017649/nvidia-docker/bin/nvidia-docker
install -D -m 755 -t /usr/local/bin /home/u0017649/nvidia-docker/bin/nvidia-docker-plugin

u0017649@sys-89698:~$ which nvidia-docker
/usr/local/bin/nvidia-docker

그리고 이렇게 설치된 nvidia-docker에서는 nvidia-docker-plugin을 수동으로 살려줘야 합니다.  매번 그러기는 귀찮으니, 아예 /etc/rc.local에 아래와 같이 1줄 넣어주는 것을 권고합니다.  그러면 부팅 때마다 nvidia-docker-plugin이 백그라운드로 떠있게 됩니다.

/usr/local/bin/nvidia-docker-plugin &

그러난 뒤에, 아래와 같이 제가 미리 build 해둔 tensorflow 1.3과 python3용 Anaconda가 설치된 ppc64le용 docker image를 pull 하시면 됩니다.

root@firestone:/home# docker pull bsyu/tf1.3-ppc64le:v0.1
v0.3: Pulling from bsyu/tf1.3-ppc64le
0ad9ca03f1b2: Already exists
7d2491df9494: Already exists
9a961cbb08c0: Already exists
9f38c9e24bdd: Already exists
36070ab6f935: Already exists
dd84cc8c7847: Already exists
4317eeb0f4b7: Already exists
13f482d825bc: Already exists
d221c8d6a86c: Already exists
994d0d1ac151: Already exists
c736e0aba22f: Already exists
e7b4f7096c8f: Already exists
a0aaaa391ef4: Downloading  3.165MB/38.83MB
3c8d454a2390: Download complete
9bdf7a145ee5: Downloading  2.671MB/120.4MB

이왕 하실 때 기타 아래 것들도 받아두시면 해로울 건 없겠습니다.

# docker pull bsyu/cudnn6-conda2-ppc64le:v0.1  (python 2.7의 anaconda image)
# docker pull bsyu/cudnn6-conda3-ppc64le:v0.1  (python 3.6의 anaconda image)


-------- 이하는 그냥 실습 옵션입니다.

이제 여기서 ppc64le/ubuntu:latest를 이용하여 libcudnn 6.0와 anaconda2/3 등이 설치된 docker image를 빌드해보겠습니다.

u0017649@sys-89830:~/docker$ ls
Anaconda2-4.4.0.1-Linux-ppc64le.sh
Anaconda3-4.4.0.1-Linux-ppc64le.sh
cuda-repo-ubuntu1604-8-0-local-cublas-performance-update_8.0.61-1_ppc64el-deb
cuda-repo-ubuntu1604-8-0-local-ga2v2_8.0.61-1_ppc64el-deb
dockerfile.cudnn6
libcudnn6_6.0.21-1+cuda8.0_ppc64el.deb
libcudnn6-dev_6.0.21-1+cuda8.0_ppc64el.deb
mldl-repo-local_4.0.0_ppc64el.deb

관련 file들을 위와 같이 ~/docker 디렉토리 속에 모아놓은 뒤, 아래와 같이 dockerfile을 구성합니다.

u0017649@sys-89830:~/docker$ vi dockerfile.cudnn6
FROM ppc64le/ubuntu:latest

ENV CUDNN_VERSION 6.0.21
LABEL com.nvidia.cudnn.version="${CUDNN_VERSION}"

RUN mkdir /tmp/temp
COPY *deb /tmp/temp/
COPY *.sh /tmp/temp/
RUN dpkg -i /tmp/temp/cuda-repo-ubuntu1604-8-0-local-ga2v2_8.0.61-1_ppc64el-deb && \
   dpkg -i /tmp/temp/cuda-repo-ubuntu1604-8-0-local-cublas-performance-update_8.0.61-1_ppc64el-deb && \
   apt-get update && apt-get install -y --no-install-recommends initramfs-tools && \
   apt-get install -y cuda && \
   dpkg -i /tmp/temp/libcudnn* && \
   dpkg -i /tmp/temp/mldl-repo-local_4.0.0_ppc64el.deb && \
   /tmp/temp/Anaconda3-4.4.0.1-Linux-ppc64le.sh -b -p /opt/anaconda3 && \
   /tmp/temp/Anaconda2-4.4.0.1-Linux-ppc64le.sh -b -p /opt/anaconda2 && \
   apt-get install -y libnccl-dev libnccl1 python-ncclient bazel libopenblas-dev libopenblas libopenblas-base && \
   apt-get remove -y mldl-repo-local && \
   apt-get remove -y cuda-repo-ubuntu1604-8-0-local-ga2v2 cuda-repo-ubuntu1604-8-0-local-cublas-performance-update && \
   ldconfig && \
   rm -rf /tmp/temp && \
   rm -rf /var/lib/apt/lists/*
ENV LD_LIBRARY_PATH="/opt/DL/nccl/lib:/opt/DL/openblas/lib:/usr/local/cuda-8.0/lib6:/usr/lib:/usr/local/lib:/opt/caffe2/lib:/usr/lib/powerpc64le-linux-gnu"
ENV PATH="/opt/anaconda2/bin:/opt/caffe2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

이제 이걸 아래와 같이 build 하면 됩니다.

u0017649@sys-89830:~/docker$ sudo docker build -t bsyu/cudnn6_v0.1:ppc64le-xenial -f dockerfile.cudnn6 .

저는 한창 진행 중에 아래와 같이 disk 공간 부족으로 error가 나네요.  PDP(Power Development Platform) cloud는 disk 공간이 너무 작은 것이 탈입니다...

Preparing to unpack .../libcudnn6_6.0.21-1+cuda8.0_ppc64el.deb ...
Unpacking libcudnn6 (6.0.21-1+cuda8.0) ...
dpkg: error processing archive /tmp/temp/libcudnn6_6.0.21-1+cuda8.0_ppc64el.deb (--install):
 cannot copy extracted data for './usr/lib/powerpc64le-linux-gnu/libcudnn.so.6.0.21' to '/usr/lib/powerpc64le-linux-gnu/libcudnn.so.6.0.21.dpkg-new': failed to write (No space left on device)
dpkg-deb: error: subprocess paste was killed by signal (Broken pipe)

2017년 10월 27일 금요일

caffe-ibm의 LMS 기능에 대한 설명

전에 올린 DDL 관련 포스팅(https://hwengineer.blogspot.kr/2017/10/caffe-ddl-alexnet-training.html)에서, LMS(large model support) 기능을 믿고 batch_size를 화끈하게 2048이나 4096으로 올리면 어떤가라는 질문이 있을 수 있습니다.  결론부터 말씀드리면 LMS를 쓴다고 해도 batch_size를 무한정 키울 수는 없습니다.

먼저 저 포스팅에 나와 있듯이, LMS 기능은 '기존 GPU memory 한계 때문에 돌릴 수 없었던 큰 모델도 돌릴 수 있게 해주는 기능'이지, 이 때문에 반드시 더 빠른 성능을 낼 수 있는 것은 아닙니다.  아무리 NVLink를 통해 가져온다고 해도, host server memory가 GPU memory보다는 느리니까요.

그와는 별도로, LMS도 무한정 host memory를 쓸 수는 없습니다.  Lab에서 들은 이야기입니다만, LMS를 쓴다고 해도 아래 정보들은 반드시 GPU memory 상에 올라가야 한다고 합니다.

- input tensor
- output tensor
- weight
- gradient (training인 경우)

그리고 이 정보들이 차지하는 memory의 양은 batch_size가 늘어날 수록 함께 늘어나는데, 그로 인해 결국 한계가 있습니다.  LMS의 핵심은, deep learning에서 layer별로 training을 할 때, 당장 처리하고 있는 layer는 GPU memory 위에 두더라도, 이미 처리했거나 나중에 처리할 layer들은 host memory에 저장할 수 있다는 것입니다.  따라서, LMS로 처리가능한 최대 neural network 크기는 그 neural network에서 가장 큰 layer의 크기에 달려 있다고 할 수 있습니다.



가령 전에 테스트했던, Alexnet의 deploy.prototxt 이용해서 'caffe time'을 수행할 때 보면 아래와 같이 data, conv1, relu1 등 총 24개의 layer가 만들어집니다.

$ grep "Creating Layer" caffe_time.log

I1025 16:37:01.848961 29514 net.cpp:90] Creating Layer data
I1025 16:37:01.867213 29514 net.cpp:90] Creating Layer conv1

I1025 16:37:03.477823 29514 net.cpp:90] Creating Layer fc8
I1025 16:37:03.481210 29514 net.cpp:90] Creating Layer prob

그리고 각 layer마다 다음과 같이 Top shape가 정해지면서 "Memory required for data"가 연산됩니다.  그리고 그 값은 처음 layer에서는 작아도 나중에는 매우 커지지요.


I1025 16:37:01.867137 29514 net.cpp:135] Top shape: 10 3 1600 1200 (57600000)
I1025 16:37:01.867183 29514 net.cpp:143] Memory required for data: 230400000

I1025 16:37:02.231456 29514 net.cpp:135] Top shape: 10 96 398 298 (113859840)
I1025 16:37:02.231468 29514 net.cpp:143] Memory required for data: 685839360

I1025 16:37:02.246103 29514 net.cpp:135] Top shape: 10 256 49 37 (4641280)
I1025 16:37:02.246112 29514 net.cpp:143] Memory required for data: 3315185920


이런 특성들로 인해, wide한 (layer별 메모리 필요량이 많은) neural network보다는 deep한 (layer 개수가 많은) neural network이 LMS의 잇점을 훨씬 더 잘 살릴 수 있습니다.



LMS의 진정한 장점을 정리하면 아래와 같습니다.

1) width로는 10-30배 정도 더 큰 모델 사용 가능
2) depth로는 무한대의 큰 모델을 사용 가능 

특성상 layer들이 많은 RNN에서 LMS가 특히 유용하게 쓰일 수 있다고 합니다.   그리고 요즘 신경망 발전 방향이 wide해지는 방향이 아니라 점점 deep해지는 방향이라고 합니다.  가령 몇년 전에 나온 Alexnet 같은 경우 이론상 7개 layer라고 하는데, 그로부터 4년 뒤에 나온 ResNet 같은 경우 1000개 layer라고 하지요.  LMS의 적용 범위는 점점 넓어지고 있다고 할 수 있습니다. 

caffe DDL을 이용한 Alexnet training

지난 9월 포스팅(http://hwengineer.blogspot.kr/2017/09/ibm-powerai-40-caffe-distributed-deep.html)에서 PowerAI에 포함된 DDL(Distributed Deep Learning), 즉 MPI를 이용한 분산처리 기능에 대해 간단히 설명드린 바 있습니다.  이번에는 그것으로 ILSVRC2012의 128만장 image dataset을 caffe alexnet으로 training 해보겠습니다.

제가 잠깐 빌릴 수 있는 Minsky 서버가 딱 1대 뿐이라, 원래 여러대의 Minsky 서버를 묶어서 하나의 model을 train시킬 수 있지만 여기서는 1대의 서버에서 caffe DDL을 수행해보겠습니다.  잠깐, 1대라고요 ?  1대에서 MPI 분산처리가 의미가 있나요 ?

예, 없지는 않습니다.  Multi-GPU를 이용한 training을 할 때 일반 caffe와 caffe DDL의 차이는 multi-thread냐, multi-process냐의 차이입니다.  좀더 쉽게 말해, 일반 caffe에서는 하나의 caffe process가 P2P를 통해 여러개의 GPU를 사용합니다.  그에 비해, caffe DDL에서는 GPU당 1개씩 별도의 caffe process가 떠서, 서로간에 MPI를 이용한 통신을 하며 여러개의 GPU를 사용합니다.

이를 그림으로 표현하면 아래와 같습니다.



실제로, 일반 caffe를 사용할 경우 nvidia-smi로 관찰해보면 다음과 같이 caffe의 PID가 모두 같지만, caffe DDL에서는 각 GPU를 사용하는 caffe PID가 서로 다릅니다.

일반 caffe :

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0     30681    C   caffe                                        15497MiB |
|    1     30681    C   caffe                                        14589MiB |
|    2     30681    C   caffe                                        14589MiB |
|    3     30681    C   caffe                                        14589MiB |
+-----------------------------------------------------------------------------+

caffe DDL :

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0     31227    C   caffe                                        15741MiB |
|    1     31228    C   caffe                                        14837MiB |
|    2     31229    C   caffe                                        14837MiB |
|    3     31230    C   caffe                                        14837MiB |
+-----------------------------------------------------------------------------+

자, 대략 차이를 이해하셨으면, alexnet training을 한번은 일반 caffe로, 또 한번은 caffe DDL로 training해보시지요.  물론 모두 같은 Minsky 서버, 즉 4-GPU 시스템 1대를 써서 테스트한 것입니다.  각각의 성능 측정은 128만장을 2-epochs, 즉 2회 반복 training할 때 걸린 시간으로 측정하겠습니다.

일반 caffe :

test@ubuntu:/nvme$ caffe train --solver=models/bvlc_alexnet/solver.prototxt -gpu all

caffe DDL :

test@ubuntu:/nvme$ mpirun -x PATH -x LD_LIBRARY_PATH -n 4 -rf 4x1x1.rf caffe train --solver=models/bvlc_alexnet/solver.prototxt -gpu 0 -ddl "-mode n:4x1x1 -dev_sync 1"

지난번에 잠깐 설명드린 것을 반복하자면 이렇습니다.

- mpirun은 여러대의 서버 노드에 동일한 명령을 동일한 환경변수 (-x 옵션)을 써서 수행해주는 병렬환경 명령어입니다.
- 4x1x1.rf라는 이름의 파일은 rank file입니다.  이 속에 병렬 서버 환경의 toplogy가 들어있습니다.
- -n 4라는 것은 MPI client의 총 숫자이며, 쉽게 말해 training에 이용하려는 GPU의 갯수입니다.
- -gpu 0에서, 왜 4개가 아니라 gpu 0이라고 1개로 지정했는지 의아하실 수 있는데, MPI 환경에서는 각각의 GPU가 하나의 learner가 됩니다.  따라서 실제 물리적 서버 1대에 GPU가 몇 장 장착되어있든 상관없이 모두 -gpu 0, 즉 GPU는 1개로 지정한 것입니다.
- "-mode b:4x1x1"에서 b라는 것은 가능하면 enhanced NCCL을 이용하라는 뜻입니다.  4x1x1은 4장의 GPU를 가진 서버 1대가 하나의 rack에 들어있다는 뜻입니다.
- dev_sync에서 0은 GPU간 sync를 하지 말라는 것이고, 1은 통신 시작할 때 sync하라는 뜻, 2는 시작할 때와 끝낼 때 각각 sync하라는 뜻입니다.

여기서 사용된 rank file 4x1x1.rf 속의 내용은 아래와 같습니다.

rank 0=minksy           slot=0:0-3
rank 1=minksy           slot=0:4-7
rank 2=minksy           slot=1:0-3
rank 3=minksy           slot=1:4-7

128만장 x 2-epochs를 처리하기 위해서는, solver.prototxt와 train_val.prototxt 속에 표시된 batch_size와 max_iter의 곱이 128만장 x 2 = 256만장이면 됩니다.  batch_size를 조절함에 따라 training 속도가 꽤 달라지는데, 여기서는 256부터 512, 768 순으로 늘려가며 테스트해보겠습니다.



위 표에서 보시다시피, batch_size가 작을 때는 일반 caffe의 성능이 더 빨랐는데, batch_size가 점점 커지면서 caffe DDL의 성능이 점점 더 빨라져서 결국 역전하게 됩니다.  batch_size와 MPI를 이용한 DDL의 성능과의 상관 관계가 있을 것 같기는 한데, 아직 그 이유는 파악을 못 했습니다.  Lab에 문의해봤는데, batch_size와는 무관할 것이라는 답변을 받긴 했습니다.


여기서 batch_size를 1024보다 더 키우면 어떻게 될까요 ?

...
F1025 17:48:43.059572 30265 syncedmem.cpp:651] Check failed: error == cudaSuccess (2 vs. 0)  out of memoryF1025 17:48:43.071281 30285 syncedmem.cpp:651] Check failed: error == cudaSuccess (2 vs. 0)  out of memory
*** Check failure stack trace: ***
    @     0x3fffb645ce0c  google::LogMessage::Fail()
    @     0x3fffb69649cc  caffe::Solver<>::Step()
    @     0x3fffb645f284  google::LogMessage::SendToLog()
...

일반 caffe든 caffe DDL이든 batch_size가 1100만 되어도 이렇게 out-of-memory (OOM) error를 내며 죽어버립니다.  그러니 아쉽게도 더 큰 batch_size에서는 테스트가 안되는 것이지요.

batch_size가 너무 커서 OOM error가 난다면 그걸 또 피해가는 방법이 있습니다.  역시 caffe-ibm에 포함된 LMS(large model support)입니다.   아래와 같이 -lms 옵션을 주면 caffe나 caffe DDL이나 모두 batch_size=1200 정도까지는 무난히 돌릴 수 있습니다.  -lms 800000이라는 것은 800000KB 이상의 memory chunk는 GPU 말고 CPU에 남겨두라는 뜻입니다.   (http://hwengineer.blogspot.kr/2017/09/inference-gpu-sizing-ibm-caffe-large.html 참조)


일반 caffe with LMS :

test@ubuntu:/nvme$ caffe train -lms 800000 --solver=models/bvlc_alexnet/solver.prototxt -gpu all

caffe DDL with LMS :

test@ubuntu:/nvme$ mpirun -x PATH -x LD_LIBRARY_PATH -n 4 -rf 4x1x1.rf caffe train -lms 800000 --solver=models/bvlc_alexnet/solver.prototxt -gpu 0 -ddl "-mode n:4x1x1 -dev_sync 1"


그 결과는 아래와 같습니다.   확실히 batch_size가 커질 수록 일반 caffe보다 caffe DDL의 성능이 더 잘 나옵니다.




궁금해하실 분들을 위해서, caffe DDL을 수행할 경우 나오는 메시지의 앞부분과 뒷부분 일부를 아래에 붙여놓습니다.

--------------------------------------------------------------------------
[[31653,1],2]: A high-performance Open MPI point-to-point messaging module
was unable to find any relevant network interfaces:

Module: OpenFabrics (openib)
  Host: minsky

Another transport will be used instead, although this may result in
lower performance.
--------------------------------------------------------------------------
ubuntu: n0(0) n1(0) n2(0) n3(0) 
I1025 18:59:45.681555 31227 caffe.cpp:151] [MPI:0   ] spreading GPUs per MPI rank
I1025 18:59:45.681725 31227 caffe.cpp:153] [MPI:0   ]    use gpu[0]
I1025 18:59:45.681541 31228 caffe.cpp:151] [MPI:1   ] spreading GPUs per MPI rank
I1025 18:59:45.681725 31228 caffe.cpp:153] [MPI:1   ]    use gpu[1]
I1025 18:59:45.681541 31229 caffe.cpp:151] [MPI:2   ] spreading GPUs per MPI rank
I1025 18:59:45.681726 31229 caffe.cpp:153] [MPI:2   ]    use gpu[2]
I1025 18:59:45.681735 31229 caffe.cpp:283] Using GPUs 2
I1025 18:59:45.681541 31230 caffe.cpp:151] [MPI:3   ] spreading GPUs per MPI rank
I1025 18:59:45.681726 31230 caffe.cpp:153] [MPI:3   ]    use gpu[3]
I1025 18:59:45.681735 31230 caffe.cpp:283] Using GPUs 3
I1025 18:59:45.681735 31227 caffe.cpp:283] Using GPUs 0
I1025 18:59:45.681733 31228 caffe.cpp:283] Using GPUs 1
I1025 18:59:45.683846 31228 caffe.cpp:288] GPU 1: Tesla P100-SXM2-16GB
I1025 18:59:45.683897 31227 caffe.cpp:288] GPU 0: Tesla P100-SXM2-16GB
I1025 18:59:45.683955 31230 caffe.cpp:288] GPU 3: Tesla P100-SXM2-16GB
I1025 18:59:45.684010 31229 caffe.cpp:288] GPU 2: Tesla P100-SXM2-16GB
I1025 18:59:46.056959 31227 caffe.cpp:302] [MPI:0   ]  name = minsky root = 1
I1025 18:59:46.067212 31228 caffe.cpp:302] [MPI:1   ]  name = minsky root = 1
I1025 18:59:46.070734 31230 caffe.cpp:302] [MPI:3   ]  name = minsky root = 1
I1025 18:59:46.071211 31229 caffe.cpp:302] [MPI:2   ]  name = minsky root = 1
I1025 18:59:46.073958 31227 solver.cpp:44] Initializing solver from parameters: 
test_iter: 1000
test_interval: 1000
base_lr: 0.01
display: 500
max_iter: 2500
lr_policy: "step"
gamma: 0.1

...중략...

I1025 19:24:53.536928 31227 solver.cpp:414]     Test net output #0: accuracy = 0.20032
I1025 19:24:53.536965 31227 solver.cpp:414]     Test net output #1: loss = 4.09802 (* 1 = 4.09802 loss)
I1025 19:24:54.180562 31227 solver.cpp:223] Iteration 2000 (1.27922 iter/s, 390.864s/500 iters), loss = 4.18248
I1025 19:24:54.180598 31227 solver.cpp:242]     Train net output #0: loss = 4.18248 (* 1 = 4.18248 loss)
I1025 19:24:54.180613 31227 sgd_solver.cpp:121] Iteration 2000, lr = 0.01
I1025 19:26:57.349701 31256 data_layer.cpp:86] Restarting data prefetching from start.
I1025 19:30:28.547333 31256 data_layer.cpp:86] Restarting data prefetching from start.
I1025 19:30:29.081480 31227 solver.cpp:466] Snapshotting to binary proto file models/bvlc_alexnet/caffe_alexnet_train_iter_2500.caffemodel
I1025 19:30:29.283386 31228 solver.cpp:315] Iteration 2500, loss = 3.91634
I1025 19:30:29.283444 31228 solver.cpp:320] Optimization Done.
I1025 19:30:29.283535 31230 solver.cpp:315] Iteration 2500, loss = 3.9612
I1025 19:30:29.283582 31230 solver.cpp:320] Optimization Done.
I1025 19:30:29.285512 31228 caffe.cpp:357] Optimization Done.
I1025 19:30:29.285521 31228 caffe.cpp:359] [MPI:1   ] MPI_Finalize
I1025 19:30:29.285697 31230 caffe.cpp:357] Optimization Done.
I1025 19:30:29.285706 31230 caffe.cpp:359] [MPI:3   ] MPI_Finalize
I1025 19:30:29.286912 31229 solver.cpp:315] Iteration 2500, loss = 3.90313
I1025 19:30:29.286952 31229 solver.cpp:320] Optimization Done.
I1025 19:30:29.290489 31229 caffe.cpp:357] Optimization Done.
I1025 19:30:29.290498 31229 caffe.cpp:359] [MPI:2   ] MPI_Finalize
I1025 19:30:29.973234 31227 sgd_solver.cpp:356] Snapshotting solver state to binary proto file models/bvlc_alexnet/caffe_alexnet_train_iter_2500.solverstate
I1025 19:30:30.727695 31227 solver.cpp:315] Iteration 2500, loss = 3.89638
I1025 19:30:30.727744 31227 solver.cpp:320] Optimization Done.
I1025 19:30:30.729465 31227 caffe.cpp:357] Optimization Done.
I1025 19:30:30.729475 31227 caffe.cpp:359] [MPI:0   ] MPI_Finalize



2017년 10월 25일 수요일

Minsky에서의 Caffe2 설치 및 jupyter notebook에서 MNIST 돌려보기


PyTorch와 함께 Caffe2를 찾으시는 고객분들도 점점 늘고 계십니다.  PyTorch처럼 Caffe2도 아직 PowerAI 속에 포함되어 있지는 않지만, 그래도 ppc64le 아키텍처에서도 소스에서 빌드하면 잘 됩니다.  현재의 최신 Caffe2 소스코드에서는 딱 한군데, benchmark 관련 모듈에서 error가 나는 부분이 있는데, 거기에 대해서 IBM이 patch를 제공합니다.  아래를 보시고 따라 하시면 됩니다.

먼저, 기본적인 caffe2의 build는 caffe2 홈페이지에 나온 안내(아래 링크)를 그대로 따르시면 됩니다.

https://caffe2.ai/docs/getting-started.html?platform=ubuntu&configuration=compile

저는 아래와 같은 환경에서 빌드했습니다.  CUDA 8.0과 libcuDNN이 설치된 Ubuntu 16.04 ppc64le 환경입니다.   특기할 부분으로는, caffe2는 Anaconda와는 뭔가 맞지 않습니다.  Anaconda가 혹시 설치되어 있다면 관련 PATH를 모두 unset하시고 빌드하시기 바랍니다.

u0017649@sys-89697:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:        16.04
Codename:       xenial

u0017649@sys-89697:~$ dpkg -l | grep cuda | head -n 4
ii  cuda                                                     8.0.61-1                                   ppc64el      CUDA meta-package
ii  cuda-8-0                                                 8.0.61-1                                   ppc64el      CUDA 8.0 meta-package
ii  cuda-command-line-tools-8-0                              8.0.61-1                                   ppc64el      CUDA command-line tools
ii  cuda-core-8-0                                            8.0.61-1                                   ppc64el      CUDA core tools

u0017649@sys-89697:~$ dpkg -l | grep libcudnn
ii  libcudnn6                                                6.0.21-1+cuda8.0                           ppc64el      cuDNN runtime libraries
ii  libcudnn6-dev                                            6.0.21-1+cuda8.0                           ppc64el      cuDNN development libraries and headers

위에서 언급한 대로, python이든 pip든 모두 Anaconda가 아닌, OS에서 제공하는 것을 사용하십시요.  여기서는 python 2.7을 썼습니다.

u0017649@sys-89697:~$ which python
/usr/bin/python


먼저, 기본적으로 아래의 Ubuntu OS package들을 설치하십시요.

u0017649@sys-89697:~$ sudo apt-get install -y --no-install-recommends build-essential cmake git libgoogle-glog-dev libprotobuf-dev protobuf-compiler

u0017649@sys-89697:~$ sudo apt-get install -y --no-install-recommends libgtest-dev libiomp-dev libleveldb-dev liblmdb-dev libopencv-dev libopenmpi-dev libsnappy-dev openmpi-bin openmpi-doc  python-pydot libgflags-dev

그리고 PowerAI에서 제공하는 openblas와 nccl도 설치하십시요.

u0017649@sys-89697:~$ sudo dpkg -i mldl-repo-local_4.0.0_ppc64el.deb

u0017649@sys-89697:~$ sudo apt-get update

u0017649@sys-89697:~$ sudo apt-get install libnccl-dev
u0017649@sys-89697:~$ sudo apt-get install libopenblas-dev libopenblas

그리고 아래의 pip package들을 설치하십시요.

u0017649@sys-89697:~$ pip install flask future graphviz hypothesis jupyter matplotlib pydot python-nvd3 pyyaml requests scikit-image scipy setuptools six tornado protobuf

이제 caffe2의 source를 download 받습니다.

u0017649@sys-89697:~$ git clone --recursive https://github.com/caffe2/caffe2.git
Cloning into 'caffe2'...
remote: Counting objects: 36833, done.
remote: Compressing objects: 100% (64/64), done.
remote: Total 36833 (delta 37), reused 34 (delta 12), pack-reused 36757
Receiving objects: 100% (36833/36833), 149.17 MiB | 11.42 MiB/s, done.
Resolving deltas: 100% (26960/26960), done.
Checking connectivity... done.
Submodule 'third_party/NNPACK' (https://github.com/Maratyszcza/NNPACK.git) registered for path 'third_party/NNPACK'
Submodule 'third_party/NNPACK_deps/FP16' (https://github.com/Maratyszcza/FP16.git) registered for path 'third_party/NNPACK_deps/FP16'
...
remote: Counting objects: 353, done.
remote: Total 353 (delta 0), reused 0 (delta 0), pack-reused 353
Receiving objects: 100% (353/353), 119.74 KiB | 0 bytes/s, done.
Resolving deltas: 100% (149/149), done.
Checking connectivity... done.
Submodule path 'third_party/pybind11/tools/clang': checked out '254c7a91e3c6aa254e113197604dafb443f4d429'

이제 ppc64le를 위한 source 수정을 하나 하겠습니다.  Patch가 필요한 부분은 주요 부분은 아니고, 벤치마크를 위한 third party 모듈 중 하나입니다.

u0017649@sys-89697:~$ cd caffe2/third_party/benchmark/src

u0017649@sys-89697:~/caffe2/third_party/benchmark/src$ vi cycleclock.h
...
#elif defined(__powerpc__) || defined(__ppc__)
  // This returns a time-base, which is not always precisely a cycle-count.
  int64_t tbl, tbu0, tbu1;
  asm("mftbu %0" : "=r"(tbu0));
  asm("mftb  %0" : "=r"(tbl));
  asm("mftbu %0" : "=r"(tbu1));
  tbl &= -static_cast<long long>(tbu0 == tbu1);
//  tbl &= -static_cast<int64_t>(tbu0 == tbu1);

수정의 핵심은 저 int64 대신 long long을 넣는 것입니다.

** 그 사이에 하나 더 늘었네요.  아래와 같이 third_party/NNPACK/CMakeLists.txt의 30번째 줄에 ppc64le를 넣어줍니다.

u0017649@sys-89697:~/caffe2/build# vi ../third_party/NNPACK/CMakeLists.txt
...
ELSEIF(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64|armv5te|armv7-a|armv7l|aarch64|ppc64le)$")
  MESSAGE(FATAL_ERROR "Unrecognized CMAKE_SYSTEM_PROCESSOR = ${CMAKE_SYSTEM_PROCESSOR}")
...

그 다음으로는 나중에 cblas 관련 error를 없애기 위해, 아래와 같이 Dependencies.cmake 파일에서 cblas 관련 1줄을 comment-out 시킵니다.

u0017649@sys-89697:~/caffe2/cmake$ vi Dependencies.cmake
...
elseif(BLAS STREQUAL "OpenBLAS")
  find_package(OpenBLAS REQUIRED)
  caffe2_include_directories(${OpenBLAS_INCLUDE_DIR})
  list(APPEND Caffe2_DEPENDENCY_LIBS ${OpenBLAS_LIB})
#  list(APPEND Caffe2_DEPENDENCY_LIBS cblas)
...

그리고 OpenBLAS_HOME을 아래와 같이 PowerAI에서 제공하는 openblas로 설정합니다.

u0017649@sys-89697:~/caffe2/cmake$ export OpenBLAS_HOME=/opt/DL/openblas/

또 하나 고칩니다.  FindNCCL.cmake에서 아래 부분을 PowerAI의 NCCL directory로 명기하면 됩니다.

root@26aa285b6c46:/data/imsi/caffe2/cmake# vi Modules/FindNCCL.cmake
...
#set(NCCL_ROOT_DIR "" CACHE PATH "Folder contains NVIDIA NCCL")
set(NCCL_ROOT_DIR "/opt/DL/nccl" CACHE PATH "Folder contains NVIDIA NCCL")
...

이제 cmake 이후 make를 돌리면 됩니다.  단, default인 /usr/local이 아닌, /opt/caffe2에 caffe2 binary가 설치되도록 CMAKE_INSTALL_PREFIX 옵션을 줍니다.

u0017649@sys-89697:~$ cd caffe2
u0017649@sys-89697:~/caffe2$ mkdir build
u0017649@sys-89697:~/caffe2$ cd build

u0017649@sys-89697:~/caffe2/build$ cmake -DCMAKE_INSTALL_PREFIX=/opt/caffe2 ..

u0017649@sys-89697:~/caffe2/build$ make

약 1시간 넘게 꽤 긴 시간이 걸린 뒤에 make가 완료됩니다.  이제 make install을 하면 /opt/caffe2 밑으로 binary들이 설치됩니다.

u0017649@sys-89697:~/caffe2/build$ sudo make install

u0017649@sys-89697:~/caffe2/build$ ls -l /opt/caffe2
total 28
drwxr-xr-x  2 root root 4096 Oct 25 03:16 bin
drwxr-xr-x  3 root root 4096 Oct 25 03:16 caffe
drwxr-xr-x 24 root root 4096 Oct 25 03:16 caffe2
drwxr-xr-x  4 root root 4096 Oct 25 03:16 include
drwxr-xr-x  2 root root 4096 Oct 25 03:16 lib
drwxr-xr-x  3 root root 4096 Oct 25 03:16 share
drwxr-xr-x  2 root root 4096 Oct 25 03:16 test

다른 일반 user들도 사용할 수 있도록 필요에 따라 /opt/caffe2의 ownership을 바꿔줍니다.  (optional)

u0017649@sys-89697:~/caffe2/build$ sudo chown -R u0017649:u0017649 /opt/caffe2

이제 테스트를 해봅니다.  먼저, PYTHONPATH를 설정해줍니다.

u0017649@sys-89697:~/caffe2/build$ export PYTHONPATH=/opt/caffe2

다음과 같이 기본 테스트를 2가지 해봅니다.  먼저 import core를 해봅니다. 

u0017649@sys-89697:~/caffe2/build$ python -c 'from caffe2.python import core' 2>/dev/null && echo "Success" || echo "Failure"
Success

다음으로는 operator_test.relu_op_test를 수행해봅니다.   제가 가진 환경은 GPU가 안 달린 환경이라서 아래 붉은색의 warning이 있습니다만, 여기서는 무시하십시요.

u0017649@sys-89697:~/caffe2/build$ pip install hypothesis

u0017649@sys-89697:~$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/caffe2/lib

u0017649@sys-89697:~$ python -m caffe2.python.operator_test.relu_op_test
NVIDIA: no NVIDIA devices found
WARNING: Logging before InitGoogleLogging() is written to STDERR
E1025 05:09:33.528787 12222 common_gpu.cc:70] Found an unknown error - this may be due to an incorrectly set up environment, e.g. changing env variable CUDA_VISIBLE_DEVICES after program start. I will set the available devices to be zero.
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.], dtype=float32), gc=, dc=[], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([[[-0.03770517, -0.03770517, -0.03770517, -0.03770517],
        [-0.03770517, -0.03770517, -0.03770517, -0.03770517],
        [-0.03770517, -0.03770517, -0.03770517, -0.03770517]],
...
        [ 0.96481699,  0.96481699,  0.96481699,  0.96481699],
        [ 0.96481699,  0.96481699,  0.96481699, -0.74859387]]], dtype=float32), gc=, dc=[], engine=u'')
Trying example: test_relu(self=<__main__.TestRelu testMethod=test_relu>, X=array([ 0.61015409], dtype=float32), gc=, dc=[], engine=u'CUDNN')
.
----------------------------------------------------------------------
Ran 1 test in 0.957s

OK

테스트도 정상적으로 완료되었습니다.   이제 jupyter notebook에서 MNIST를 수행해보시지요.

먼저 jupyter notebook을 외부 browser에서 접속할 수 있도록 config를 수정합니다.

u0017649@sys-89697:~$  jupyter notebook --generate-config
Writing default config to: /home/u0017649/.jupyter/jupyter_notebook_config.py

u0017649@sys-89697:~$ vi /home/u0017649/.jupyter/jupyter_notebook_config.py
...
#c.NotebookApp.ip = 'localhost'
c.NotebookApp.ip = '*'

jupyter notebook을 kill 했다가 다시 띄웁니다.   이제 아래 붉은색처럼 token이 display 됩니다.

u0017649@sys-89697:~$ jupyter notebook &

[I 05:13:29.492 NotebookApp] Writing notebook server cookie secret to /home/u0017649/.local/share/jupyter/runtime/notebook_cookie_secret
[W 05:13:29.578 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
[I 05:13:29.665 NotebookApp] Serving notebooks from local directory: /home/u0017649
[I 05:13:29.666 NotebookApp] 0 active kernels
[I 05:13:29.666 NotebookApp] The Jupyter Notebook is running at: http://[all ip addresses on your system]:8888/?token=ca44acc48f0f2daa6dc9d935904f1de9a1496546efc95768
[I 05:13:29.666 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[W 05:13:29.667 NotebookApp] No web browser found: could not locate runnable browser.
[C 05:13:29.667 NotebookApp]

    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://localhost:8888/?token=ca44acc48f0f2daa6dc9d935904f1de9a1496546efc95768

이 token을 복사해서 외부의 browser에서 입력하면 됩니다.  여기서 사용된 서버의 ip가 172.29.160.94이므로, 먼저 browser에서 http://172.29.160.94:8888의 주소를 찾아들어갑니다.



접속이 완료되면 다시 명령어 창에서 아래의 MNIST python notebook을 download 받습니다.

u0017649@sys-89697:~$ wget https://raw.githubusercontent.com/caffe2/caffe2/master/caffe2/python/tutorials/MNIST.ipynb


이 MNIST.ipynb이 jupyter 화면에 뜨면, 그걸 클릭합니다.




이제 문단 하나하나씩 play button을 누르면서 진행해보실 수 있습니다.







2017년 10월 16일 월요일

Minsky 서버에서 Tensorflow r1.3을 source로부터 build하기


2017년 10월 현재 최신 PowerAI 버전은 4.0으로서, 이 속에 포함된 tensorflow는 버전 r1.1입니다.

root@ubuntu:/tmp/kkk# dpkg -l | grep mldl
ii  mldl-repo-local                        4.0.0                                      ppc64el      IBM repository for Deep Learning tools for POWER linux
ii  power-mldl                             4.0.0                                      ppc64el      Meta-package for Deep Learning frameworks for POWER


root@ubuntu:/tmp/kkk# dpkg -l | grep tensor
ii  ddl-tensorflow                         0.9.0-4ibm1                                ppc64el      TensorFlow operator for IBM PowerAI Distributed Deep Learning
ii  tensorflow                             1.1.0-4ibm1                                ppc64el      Open source software library for numerical computation

현재 github에 올라온 tensorflow 최신 버전은 r1.4이며, 몇몇 최신 버전을 사용하시는 고객께서는 r1.3을 테스트하시고자 합니다.  PowerAI는 대략 3개월 단위로 최신 ML/DL framework 버전을 갱신하니까, 다음 버전의 PowerAI는 아마도 11월 경에 나올 가능성이 많습니다.  그렇다면 tensorflow나 기타 framework의 최신 버전을 쓰려면 그때까지 참고 기다려야 할까요 ?

일단 기다려주십사 하는 것이 IBM의 공식 입장입니다만, 사실 꼭 그러실 필요는 없습니다.  오픈 소스니까요.  그냥 tensorflow r1.3을 직접 소스로부터 빌드하셔서 사용하실 수도 있습니다.  여기서는 그 방법을 살펴보시고, r1.3이 포함된 site-packages.tar도 올려놓겠습니다.

먼저, 여기서 제가 빌드를 위해 사용한 환경은 Ubuntu 16.04.2 LTS ppc64le입니다.  CUDA는 8.0.61, libcudnn은 6.0.21, 그리고 gcc는 5.4 입니다.

u0017649@sys-89490:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.2 LTS
Release:        16.04
Codename:       xenial


u0017649@sys-89490:~$ dpkg -l | grep cuda
ii  cuda                                                     8.0.61-1                                   ppc64el      CUDA meta-package
ii  cuda-8-0                                                 8.0.61-1                                   ppc64el      CUDA 8.0 meta-package
...
ii  libcudnn6                                                6.0.21-1+cuda8.0                           ppc64el      cuDNN runtime libraries
ii  libcudnn6-dev                                            6.0.21-1+cuda8.0                           ppc64el      cuDNN development libraries and headers

u0017649@sys-89490:~$ /usr/bin/gcc --version
gcc (Ubuntu/IBM 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

여기서는 아래의 tensorflow 공식 홈페이지에 나온 source로부터의 빌드 방법을 거의 그대로 따라가겠습니다. 

https://www.tensorflow.org/install/install_sources#ConfigureInstallation

Tensorflow 홈페이지에서는 아래의 libcupti-dev 외에 python 관련 패키지를 잔뜩 설치해야 하라고 나오는데, 실제로는 그냥 anaconda만 설치하고 진행해도 괜찮은 것 같습니다.

u0017649@sys-89490:~$ sudo apt-get install libcupti-dev

아래는 ananconda3 설치 절차입니다.

u0017649@sys-89490:~$ wget wget https://repo.continuum.io/archive/Anaconda3-4.4.0.1-Linux-ppc64le.sh

u0017649@sys-89490:~$ chmod u+x Anaconda*

u0017649@sys-89490:~$ sudo ./Anaconda3-4.4.0.1-Linux-ppc64le.sh
...
[/home/u0017649/anaconda3] >>> /usr/local/anaconda3

u0017649@sys-89490:~$ export PATH="/usr/local/anaconda3/bin:$PATH"

여기서는 주로 u0017649 userid를 사용하므로, 그 userid로 anaconda root directory(/usr/local/anaconda3)를 자유롭게 쓸 수 있도록 그 directory의 ownership을 바꿔줍니다.

u0017649@sys-89490:~$ sudo chown -R u0017649:u0017649 /usr/local/anaconda3

이제 conda 명령을 이용해서 bazel과 numpy를 설치합니다.

u0017649@sys-89490:~$ conda install bazel numpy
Fetching package metadata .........
Solving package specifications: .

Package plan for installation in environment /usr/local/anaconda3:

The following NEW packages will be INSTALLED:

    bazel:    0.4.5-0

The following packages will be UPDATED:

    anaconda: 4.4.0-np112py36_0 --> 4.4.0-np112py36_1
    conda:    4.3.21-py36_0     --> 4.3.27-py36_0

Proceed ([y]/n)? y

bazel-0.4.5-0. 100% |####################################################| Time: 0:00:09  14.58 MB/s
conda-4.3.27-p 100% |####################################################| Time: 0:00:00  10.31 MB/s
anaconda-4.4.0 100% |####################################################| Time: 0:00:00   6.57 MB/s

u0017649@sys-89490:~$ which bazel
/usr/local/anaconda3/bin/bazel

이제 tensorflow의 source를 git clone 명령으로 download 받습니다.

u0017649@sys-89490:~$ git clone --recursive https://github.com/tensorflow/tensorflow.git
Cloning into 'tensorflow'...
remote: Counting objects: 246390, done.
remote: Total 246390 (delta 0), reused 0 (delta 0), pack-reused 246390
Receiving objects: 100% (246390/246390), 125.14 MiB | 6.34 MiB/s, done.
Resolving deltas: 100% (192026/192026), done.
Checking connectivity... done.

우리가 빌드하려는 것은 r1.3으로 그 branch로 switch합니다.

u0017649@sys-89490:~$ cd tensorflow

u0017649@sys-89490:~/tensorflow$ git checkout r1.3
Checking out files: 100% (3934/3934), done.
Branch r1.3 set up to track remote branch r1.3 from origin.
Switched to a new branch 'r1.3'

이제 build 준비가 끝났습니다.  Build 절차는 기본적으로, configure --> bazel로 pip package build --> wheel file build  --> pip 명령으로 wheel file 설치입니다.

Configure하실 때 대부분은 default를 선택하시되, 몇몇 부분에서는 별도로 지정하셔야 합니다.  ppc64le 특성에 맞춰야 하는 부분은 딱 한군데, cuDNN 6 library가 위치한 directory를 지정하는 부분 뿐입니다.

u0017649@sys-89490:~/tensorflow$ ./configure
Extracting Bazel installation...
..................
You have bazel 0.4.5- installed.
Please specify the location of python. [Default is /usr/local/anaconda3/bin/python]:
Found possible Python library paths:
  /usr/local/anaconda3/lib/python3.6/site-packages
Please input the desired Python library path to use.  Default is [/usr/local/anaconda3/lib/python3.6/site-packages]
Do you wish to build TensorFlow with MKL support? [y/N] n
...
Do you wish to build TensorFlow with CUDA support? [y/N] y
...
Please specify which gcc should be used by nvcc as the host compiler. [Default is /opt/at10.0/bin/gcc]: /usr/bin/gcc
...
Please specify the location where cuDNN 6 library is installed. Refer to README.md for more details. [Default is /usr/local/cuda]: /usr/lib/powerpc64le-linux-gnu
...
You can find the compute capability of your device at: https://developer.nvidia.com/cuda-gpus.
Please note that each additional compute capability significantly increases your build time and binary size.
[Default is: "3.5,5.2"]: "3.7,6.0"       # 3.7은 K80, 6.0은 P100을 위한 compute capability입니다.
...

Configure가 끝나면 bazel로 TensorFlow with GPU support를 위한 pip package를 build합니다.  이 과정 중에, 아래 예시한 것과 같이 인터넷으로부터 일부 tar.gz 파일들을 download 받는 부분이 관측됩니다.  즉, 이 과정을 위해서는 인터넷 연결이 필요합니다.

u0017649@sys-89490:~/tensorflow$ bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
...
INFO: Downloading http://mirror.bazel.build/github.com/google/boringssl/archive/bbcaa15b0647816b9a\
1a9b9e0d209cd6712f0105.tar.gz: 3,244,032 bytes
...
INFO: Downloading http://mirror.bazel.build/github.com/google/boringssl/archive/bbcaa15b0647816b9a\
1a9b9e0d209cd6712f0105.tar.gz: 4,032,059 bytes
...
INFO: From Compiling tensorflow/python/pywrap_tensorflow_internal.cc:
bazel-out/local_linux-py3-opt/bin/tensorflow/python/pywrap_tensorflow_internal.cc: In function 'PyObject* _wrap_PyRecordReader_New(PyObject*, PyObject*)':
bazel-out/local_linux-py3-opt/bin/tensorflow/python/pywrap_tensorflow_internal.cc:5173:138: warning: 'arg2' may be used uninitialized in this function [-Wmaybe-uninitialized]
     result = (tensorflow::io::PyRecordReader *)tensorflow::io::PyRecordReader::New((string const &)*arg1,arg2,(string const &)*arg3,arg4);
                                                                                                                                          ^
At global scope:
cc1plus: warning: unrecognized command line option '-Wno-self-assign'
Target //tensorflow/tools/pip_package:build_pip_package up-to-date:
  bazel-bin/tensorflow/tools/pip_package/build_pip_package
INFO: Elapsed time: 7106.091s, Critical Path: 4427.34s

이런저런 warning message만 나올 뿐, 잘 끝났습니다.  저는 이 과정을 1-core짜리 cloud 환경에서 돌렸는데, 이렇게 거의 2시간 가까이 걸렸습니다.

이제 여기서 build된 binary를 이용하여 .whl file을 build합니다.  생성될 .whl 파일은 /tmp/tensorflow_pkg directory에 들어가도록 지정합니다.

u0017649@sys-89490:~/tensorflow$ bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
Fri Oct 13 03:40:03 EDT 2017 : === Using tmpdir: /tmp/tmp.UreS6KLhqt
~/tensorflow/bazel-bin/tensorflow/tools/pip_package/build_pip_package.runfiles ~/tensorflow
~/tensorflow
/tmp/tmp.UreS6KLhqt ~/tensorflow
Fri Oct 13 03:40:23 EDT 2017 : === Building wheel
warning: no files found matching '*.dll' under directory '*'
warning: no files found matching '*.lib' under directory '*'
warning: no files found matching '*.h' under directory 'tensorflow/include/tensorflow'
warning: no files found matching '*' under directory 'tensorflow/include/Eigen'
warning: no files found matching '*' under directory 'tensorflow/include/external'
warning: no files found matching '*.h' under directory 'tensorflow/include/google'
warning: no files found matching '*' under directory 'tensorflow/include/third_party'
warning: no files found matching '*' under directory 'tensorflow/include/unsupported'
~/tensorflow
Fri Oct 13 03:44:36 EDT 2017 : === Output wheel file is in: /tmp/tensorflow_pkg


u0017649@sys-89490:~$ ls /tmp/tensorflow_pkg
tensorflow-1.3.1-cp36-cp36m-linux_ppc64le.whl

잘 끝났습니다.  이제 이 wheel 파일을 pip 명령으로 설치합니다.  단, 그 전에 PYTHONPATH 환경변수를 확실히 지정할 것을 권고합니다.  여기서도 tensorflow 설치에 필요한 tensorboard나 protobuf 등을 인터넷으로부터 자동으로 download 받는 것 같습니다.

u0017649@sys-89490:~$ export PYTHONPATH=/usr/local/anaconda3/lib/python3.6/site-packages

u0017649@sys-89490:~$ pip install /tmp/tensorflow_pkg/tensorflow-1.3.1-cp36-cp36m-linux_ppc64le.whl
Processing /tmp/tensorflow_pkg/tensorflow-1.3.1-cp36-cp36m-linux_ppc64le.whl
Requirement already satisfied: six>=1.10.0 in /usr/local/anaconda3/lib/python3.6/site-packages (from tensorflow==1.3.1)
Collecting tensorflow-tensorboard<0.2.0,>=0.1.0 (from tensorflow==1.3.1)
  Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connection broken by 'ReadTimeoutError("HTTPSConnectionPool(host='pypi.python.org', port=443): Read timed out. (read timeout=15)",)': /simple/tensorflow-tensorboard/
  Downloading tensorflow_tensorboard-0.1.8-py3-none-any.whl (1.6MB)
    100% |????????????????????????????????| 1.6MB 772kB/s
Requirement already satisfied: wheel>=0.26 in /usr/local/anaconda3/lib/python3.6/site-packages (from tensorflow==1.3.1)
Requirement already satisfied: numpy>=1.11.0 in /usr/local/anaconda3/lib/python3.6/site-packages (from tensorflow==1.3.1)
Collecting protobuf>=3.3.0 (from tensorflow==1.3.1)
  Downloading protobuf-3.4.0-py2.py3-none-any.whl (375kB)
    100% |????????????????????????????????| 378kB 2.5MB/s
Requirement already satisfied: werkzeug>=0.11.10 in /usr/local/anaconda3/lib/python3.6/site-packages (from tensorflow-tensorboard<0.2.0,>=0.1.0->tensorflow==1.3.1)
...
Successfully installed html5lib-0.9999999 markdown-2.6.9 protobuf-3.4.0 tensorflow-1.3.1 tensorflow-tensorboard-0.1.8

자, 이제 설치가 끝났습니다.  conda list 명령으로 tensorflow의 설치를 확인합니다.

u0017649@sys-89490:~$ conda list | grep tensor
tensorflow                1.3.1                     <pip>
tensorflow-tensorboard    0.1.8                     <pip>

이제 tensorflow가 설치된 PYTHONPATH, 즉 /usr/local/anaconda3/lib/python3.6/site-packages를 통째로 tar로 말아서 K80 GPU가 설치된 제2의 서버에 가져가겠습니다.  물론 그 제2의 서버에는 미리 anaconda3가 설치되어 있어야 합니다.

u0017649@sys-89498:/usr/local/anaconda3/lib/python3.6 $ tar -zcf site-packages.tgz site-packages

u0017649@sys-89498:~$ scp /usr/local/anaconda3/lib/python3.6/site-packages.tgz firestone:~/
site-packages.tgz                             100%  313MB  19.6MB/s   00:16

이제 위에서 firestone이라고 되어 있는 그 서버로 이동해서 작업합니다.  참고로, 이 firestone이라는 서버는 Ubuntu 16.04.3으로서 빌드 서버의 16.04.2보다 약간 버전이 높습니다만, 별 문제 없이 잘 수행되더군요.

먼저 anaconda3가 설치되어 있는지 확인합니다.

root@ubuntu:~# which conda
/root/anaconda3/bin/conda

여기서는 root user로 /root/anaconda3 위치에 anaconda를 설치해놓았네요.  뭐 별로 좋은 위치는 아닙니다만, 여기서는 이걸 그대로 써보겠습니다.  여기서의 PYTHONPATH, 즉, /root/anaconda3/lib/python3.6/site-packages에 저 위의 서버에서 가져온 site-packages.tgz를 그대로 풀어놓겠습니다.  기존의 site-packages 속에 들어있는 package들은 overwrite 됩니다만, 만약 새로 풀리는 site-packages 밑에 없는 패키지들이 있었다면 그것들은 그대로 보존되니까, 그냥 풀어놓으셔도 됩니다.

root@ubuntu:~# cd /root/anaconda3/lib/python3.6

root@ubuntu:~/anaconda3/lib/python3.6# tar -zxf ~/site-packages.tgz

이제 준비 완료입니다.  먼저 conda list로 tensorflow가 설치되어 있는 것으로 나오는지 확인해봅니다.

root@ubuntu:~/anaconda3/lib/python3.6# conda list | grep tensorflow
tensorflow                1.3.1                     <pip>
tensorflow-tensorboard    0.1.8                     <pip>

예, 잘 보이네요.  이제 PYTHONPATH를 다시 한번 확실히 선언하고, 시험 삼아 cifar10을 수행해보겠습니다.

root@ubuntu:~# export PYTHONPATH=/root/anaconda3/lib/python3.6/site-packages

root@ubuntu:~# git clone https://github.com/tensorflow/models.git
Cloning into 'models'...
remote: Counting objects: 7644, done.
remote: Total 7644 (delta 0), reused 0 (delta 0), pack-reused 7644
Receiving objects: 100% (7644/7644), 157.90 MiB | 19.09 MiB/s, done.
Resolving deltas: 100% (4139/4139), done.
Checking connectivity... done.

root@ubuntu:~# cd models/tutorials/image/cifar10

root@ubuntu:~/models/tutorials/image/cifar10# ls
BUILD             cifar10_input_test.py       cifar10_train.py
cifar10_eval.py   cifar10_multi_gpu_train.py  __init__.py
cifar10_input.py  cifar10.py                  README.md

root@ubuntu:~/models/tutorials/image/cifar10# which python
/root/anaconda3/bin/python

Download 받은 example script 중 cifar10_train.py을 수행하면 training dataset의 download부터 training까지 일사천리로 수행됩니다.

root@ubuntu:~/models/tutorials/image/cifar10# python cifar10_train.py
>> Downloading cifar-10-binary.tar.gz 100.0%
Successfully downloaded cifar-10-binary.tar.gz 170052171 bytes.
/root/anaconda3/lib/python3.6/site-packages/numpy/core/machar.py:127: RuntimeWarning: overflow encountered in add
  a = a + a
/root/anaconda3/lib/python3.6/site-packages/numpy/core/machar.py:129: RuntimeWarning: invalid value encountered in subtract
  temp1 = temp - a
/root/anaconda3/lib/python3.6/site-packages/numpy/core/machar.py:138: RuntimeWarning: invalid value encountered in subtract
  itemp = int_conv(temp-a)
/root/anaconda3/lib/python3.6/site-packages/numpy/core/machar.py:162: RuntimeWarning: overflow encountered in add
  a = a + a
/root/anaconda3/lib/python3.6/site-packages/numpy/core/machar.py:164: RuntimeWarning: invalid value encountered in subtract
  temp1 = temp - a
/root/anaconda3/lib/python3.6/site-packages/numpy/core/machar.py:171: RuntimeWarning: invalid value encountered in subtract
  if any(temp-a != zero):
Filling queue with 20000 CIFAR images before starting to train. This will take a few minutes.
...
2017-10-13 22:18:12.974909: I tensorflow/core/common_runtime/gpu/gpu_device.cc:986] 2:   N N Y Y
2017-10-13 22:18:12.974915: I tensorflow/core/common_runtime/gpu/gpu_device.cc:986] 3:   N N Y Y
2017-10-13 22:18:12.974933: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:0) -> (device: 0, name: Tesla K80, pci bus id: 0000:03:00.0)
2017-10-13 22:18:12.974942: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:1) -> (device: 1, name: Tesla K80, pci bus id: 0000:04:00.0)
2017-10-13 22:18:12.974952: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:2) -> (device: 2, name: Tesla K80, pci bus id: 0020:03:00.0)
2017-10-13 22:18:12.974960: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1045] Creating TensorFlow device (/gpu:3) -> (device: 3, name: Tesla K80, pci bus id: 0020:04:00.0)
2017-10-13 22:18:22.502001: step 0, loss = 4.67 (52.2 examples/sec; 2.451 sec/batch)
2017-10-13 22:18:22.917980: step 10, loss = 4.62 (3076.9 examples/sec; 0.042 sec/batch)
2017-10-13 22:18:23.240470: step 20, loss = 4.43 (3969.1 examples/sec; 0.032 sec/batch)
2017-10-13 22:18:23.538250: step 30, loss = 4.41 (4298.5 examples/sec; 0.030 sec/batch)
2017-10-13 22:18:23.837076: step 40, loss = 4.29 (4283.4 examples/sec; 0.030 sec/batch)
2017-10-13 22:18:24.134108: step 50, loss = 4.33 (4309.3 examples/sec; 0.030 sec/batch)
2017-10-13 22:18:24.426799: step 60, loss = 4.30 (4373.2 examples/sec; 0.029 sec/batch)
...
2017-10-14 07:09:50.128824: step 999920, loss = 0.10 (4352.2 examples/sec; 0.029 sec/batch)
2017-10-14 07:09:50.428406: step 999930, loss = 0.11 (4272.7 examples/sec; 0.030 sec/batch)
2017-10-14 07:09:50.722993: step 999940, loss = 0.14 (4345.0 examples/sec; 0.029 sec/batch)
2017-10-14 07:09:51.019963: step 999950, loss = 0.11 (4310.2 examples/sec; 0.030 sec/batch)
2017-10-14 07:09:51.317448: step 999960, loss = 0.13 (4302.7 examples/sec; 0.030 sec/batch)
2017-10-14 07:09:51.617180: step 999970, loss = 0.11 (4270.7 examples/sec; 0.030 sec/batch)
2017-10-14 07:09:51.914633: step 999980, loss = 0.14 (4303.0 examples/sec; 0.030 sec/batch)
2017-10-14 07:09:52.213837: step 999990, loss = 0.13 (4278.1 examples/sec; 0.030 sec/batch)


완벽하게 잘 수행되었습니다.

아래의 제 구글 드라이브에 site-packages.tgz를 올려두었습니다.  사이즈는 330MB 정도인 이 파일은 ppc64le 아키텍처의 Ubuntu 16.04, CUDA 8.0, libcuDNN 6.0 환경의 K80 또는 P100을 활용하실 수 있도록 빌드된 것입니다.  필요하시면 마음대로 가져가 쓰셔도 됩니다.   제가 책임은 질 수 없는 패키지라는 것은 양해 바랍니다.

https://drive.google.com/open?id=0B-F0jEb44gqUZGdYb3A2QUNaenM 

2017년 10월 10일 화요일

Minsky 위에서의 PyTorch 설치, 그리고 MNIST 수행


IBM에서 제공되는 주요 오픈소스 기반 Deep Learning framework toolkit인 PowerAI에는 아직 PyTorch가 포함되어 있지 않습니다.  그러나 요즘 python의 인기를 타고 PyTorch를 사용하는 사례가 점점 늘고 있습니다.

ppc64le 아키텍처 기반의 IBM Minsky 서버에서는 그렇다면 아직 PyTorch를 사용 못하는 것인가 ?  아닙니다.  오픈소스 좋은 것이 무엇이겠습니까 ?  그냥 source에서 빌드하셔서 사용하시면 됩니다.   여기서는 그 과정을 한번 보겠습니다.   제가 가난하여 Minsky가 없는 관계로, Kolon Benit에서 잠깐 빌려주신 Firestone 서버 (POWER8 + K80)에서 빌드하고 테스트했습니다.   여기서는 Ubuntu 16.04.03에 CUDA 8.0.61을 썼습니다.

root@ubuntu:/data/examples/mnist# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.3 LTS
Release:        16.04
Codename:       xenial

root@ubuntu:/data/examples/mnist# dpkg -l | grep cuda
ii  cuda                                    8.0.61-1                                   ppc64el      CUDA meta-package
ii  cuda-8-0                                8.0.61-1                                   ppc64el      CUDA 8.0 meta-package


먼저 아래 URL에 따라 anaconda를 설치합니다.

http://hwengineer.blogspot.kr/2017/09/minsky-anaconda-installer-full-package.html

다음으로 github에서 source download 합니다.

root@ubuntu:/data# git clone https://github.com/pytorch/pytorch.git
Cloning into 'pytorch'...
remote: Counting objects: 40225, done.
remote: Compressing objects: 100% (39/39), done.
remote: Total 40225 (delta 33), reused 30 (delta 24), pack-reused 40162
Receiving objects: 100% (40225/40225), 15.52 MiB | 6.41 MiB/s, done.
Resolving deltas: 100% (30571/30571), done.
Checking connectivity... done.

root@ubuntu:/data# cd pytorch

Anaconda로부터 conda가 제대로 설치되었는지 확인하고, 그에 따라 CMAKE_PREFIX_PATH를 설정합니다.

root@ubuntu:/data/pytorch# which conda
/opt/anaconda2/bin/conda

root@ubuntu:/data/pytorch# export CMAKE_PREFIX_PATH=/opt/anaconda2

이어서 numpy와 pyyaml 등 PyTorch에 필요한 python package들을 conda 명령으로 설치합니다.  이때 원래의 build instruction (https://github.com/pytorch/pytorch#from-source)에서는 intel에만 있는 mkl도 conda로 설치하라고 나옵니다만, ppc64le에서는 그 대신 openblas를 설치하시면 됩니다.

root@ubuntu:/data/pytorch# conda install numpy pyyaml setuptools cmake cffi openblas
...
Package plan for installation in environment /opt/anaconda2:

The following NEW packages will be INSTALLED:

    bzip2:        1.0.6-3
    certifi:      2016.2.28-py27_0
    cmake:        3.6.3-0

The following packages will be UPDATED:

    anaconda:     4.4.0-np112py27_0  --> custom-py27_0
    astropy:      1.3.2-np112py27_0  --> 2.0.1-np113py27_1
    bottleneck:   1.2.1-np112py27_0  --> 1.2.1-np113py27_1
    conda:        4.3.21-py27_0      --> 4.3.27-py27_0
    h5py:         2.7.0-np112py27_0  --> 2.7.0-np113py27_1
    matplotlib:   2.0.2-np112py27_0  --> 2.0.2-np113py27_0
    numexpr:      2.6.2-np112py27_0  --> 2.6.2-np113py27_1
    numpy:        1.12.1-py27_0      --> 1.13.1-py27_1
    pandas:       0.20.1-np112py27_0 --> 0.20.3-py27_1
    pytables:     3.2.2-np112py27_4  --> 3.4.2-np113py27_0
    pywavelets:   0.5.2-np112py27_0  --> 0.5.2-np113py27_1
    scikit-image: 0.13.0-np112py27_0 --> 0.13.0-np113py27_0
    scikit-learn: 0.18.1-np112py27_1 --> 0.19.0-np113py27_1
    scipy:        0.19.0-np112py27_0 --> 0.19.1-np113py27_1
    setuptools:   27.2.0-py27_0      --> 36.4.0-py27_1
    statsmodels:  0.8.0-np112py27_0  --> 0.8.0-np113py27_1

Proceed ([y]/n)? y

bzip2-1.0.6-3. 100% |################################| Time: 0:00:00  10.23 MB/s
anaconda-custo 100% |################################| Time: 0:00:00  15.66 MB/s
certifi-2016.2 100% |################################| Time: 0:00:01 147.40 kB/s
cmake-3.6.3-0. 100% |################################| Time: 0:00:36 225.32 kB/s
numpy-1.13.1-p 100% |################################| Time: 0:00:04   1.68 MB/s
bottleneck-1.2 100% |################################| Time: 0:00:01 224.70 kB/s
h5py-2.7.0-np1 100% |################################| Time: 0:00:02   1.09 MB/s
numexpr-2.6.2- 100% |################################| Time: 0:00:01 288.12 kB/s
pywavelets-0.5 100% |################################| Time: 0:00:05   1.08 MB/s
scipy-0.19.1-n 100% |################################| Time: 0:01:25 459.82 kB/s
setuptools-36. 100% |################################| Time: 0:00:01 347.78 kB/s
pandas-0.20.3- 100% |################################| Time: 0:00:56 407.34 kB/s
pytables-3.4.2 100% |################################| Time: 0:00:41 168.51 kB/s
scikit-learn-0 100% |################################| Time: 0:01:19 158.86 kB/s
astropy-2.0.1- 100% |################################| Time: 0:00:15 644.67 kB/s
statsmodels-0. 100% |################################| Time: 0:00:44 178.04 kB/s
conda-4.3.27-p 100% |################################| Time: 0:00:00  44.12 MB/s
matplotlib-2.0 100% |################################| Time: 0:00:04   2.51 MB/s
scikit-image-0 100% |################################| Time: 0:02:18 245.94 kB/s


  - https://repo.continuum.io/pkgs/free/noarch
  - https://repo.continuum.io/pkgs/r/linux-ppc64le
  - https://repo.continuum.io/pkgs/r/noarch
  - https://repo.continuum.io/pkgs/pro/linux-ppc64le
  - https://repo.continuum.io/pkgs/pro/noarch


이제 pytorch를 설치할 차례입니다.

root@ubuntu:/data/pytorch# python setup.py install
Could not find /data/pytorch/torch/lib/gloo/CMakeLists.txt
Did you run 'git submodule update --init'?

억, git clone할 때 --recursive를 안 붙여줬기 때문에 이런 error를 겪나 봅니다.  시키는 대로 git submodule 명령을 수행하시면 이 error는 안 생깁니다.

root@ubuntu:/data/pytorch# git submodule update --init
Submodule 'torch/lib/gloo' (https://github.com/facebookincubator/gloo) registered for path 'torch/lib/gloo'
Submodule 'torch/lib/nanopb' (https://github.com/nanopb/nanopb.git) registered for path 'torch/lib/nanopb'
Submodule 'torch/lib/pybind11' (https://github.com/pybind/pybind11) registered for path 'torch/lib/pybind11'
Cloning into 'torch/lib/gloo'...
remote: Counting objects: 1922, done.
remote: Compressing objects: 100% (61/61), done.
remote: Total 1922 (delta 28), reused 64 (delta 24), pack-reused 1837
Receiving objects: 100% (1922/1922), 567.77 KiB | 0 bytes/s, done.
Resolving deltas: 100% (1422/1422), done.
Checking connectivity... done.
Submodule path 'torch/lib/gloo': checked out '7fd607e2852c910f0f1320d2aaa92f1da2291109'
Cloning into 'torch/lib/nanopb'...
remote: Counting objects: 4384, done.
...
Resolving deltas: 100% (6335/6335), done.
Checking connectivity... done.
Submodule path 'torch/lib/pybind11': checked out '9f6a636e547fc70a02fa48436449aad67080698f'


이제 다시 pytorch를 설치합니다.   보시다시피 설치 메시지에서 x86 아키텍처에만 있는 SSE2 extension이 없다든가, mkl_intel이 없다는 등의 경고 메시지가 많이 나옵니다만 대범하게 무시하십시요.

root@ubuntu:/data/pytorch# python setup.py install
running install
running build_deps
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Checking if C linker supports --verbose
-- Checking if C linker supports --verbose - yes
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Checking if CXX linker supports --verbose
-- Checking if CXX linker supports --verbose - yes
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Try OpenMP C flag = [-fopenmp]
-- Performing Test OpenMP_FLAG_DETECTED
-- Performing Test OpenMP_FLAG_DETECTED - Success
-- Try OpenMP CXX flag = [-fopenmp]
-- Performing Test OpenMP_FLAG_DETECTED
-- Performing Test OpenMP_FLAG_DETECTED - Success
-- Found OpenMP: -fopenmp
-- Compiling with OpenMP support
-- Could not find hardware support for NEON on this machine.
-- No OMAP3 processor on this machine.
-- No OMAP4 processor on this machine.
-- Looking for cpuid.h
...
-- Performing Test C_HAS_SSE1_1
-- Performing Test C_HAS_SSE1_1 - Failed
-- Performing Test C_HAS_SSE1_2
-- Performing Test C_HAS_SSE1_2 - Failed
-- Performing Test C_HAS_SSE1_3
...
-- Checking for [mkl_gf_lp64 - mkl_gnu_thread - mkl_core - gomp - pthread - m - dl]
--   Library mkl_gf_lp64: not found
-- Checking for [mkl_gf_lp64 - mkl_intel_thread - mkl_core - gomp - pthread - m - dl]
--   Library mkl_gf_lp64: not found
...
-- MKL library not found
-- Checking for [openblas]
--   Library openblas: /opt/anaconda2/lib/libopenblas.so
-- Looking for sgemm_
-- Looking for sgemm_ - found
-- Performing Test BLAS_F2C_DOUBLE_WORKS
-- Performing Test BLAS_F2C_DOUBLE_WORKS - Success
-- Performing Test BLAS_F2C_FLOAT_WORKS
-- Performing Test BLAS_F2C_FLOAT_WORKS - Success
-- Performing Test BLAS_USE_CBLAS_DOT
-- Performing Test BLAS_USE_CBLAS_DOT - Success
-- Found a library with BLAS API (open).
-- Looking for cheev_
-- Looking for cheev_ - found
-- Found a library with LAPACK API. (open)
-- Looking for clock_gettime in rt
-- Looking for clock_gettime in rt - found
...
Scanning dependencies of target TH
[ 12%] Building C object CMakeFiles/TH.dir/THSize.c.o
[ 12%] Building C object CMakeFiles/TH.dir/THHalf.c.o
[ 18%] Building C object CMakeFiles/TH.dir/THGeneral.c.o
[ 25%] Building C object CMakeFiles/TH.dir/THAllocator.c.o
[ 31%] Building C object CMakeFiles/TH.dir/THStorage.c.o
[ 37%] Building C object CMakeFiles/TH.dir/THRandom.c.o
[ 43%] Building C object CMakeFiles/TH.dir/THFile.c.o
[ 50%] Building C object CMakeFiles/TH.dir/THTensor.c.o
[ 56%] Building C object CMakeFiles/TH.dir/THDiskFile.c.o
[ 62%] Building C object CMakeFiles/TH.dir/THMemoryFile.c.o
[ 75%] Building C object CMakeFiles/TH.dir/THLogAdd.c.o
[ 75%] Building C object CMakeFiles/TH.dir/THLapack.c.o
[ 81%] Building C object CMakeFiles/TH.dir/THBlas.c.o
[ 87%] Building C object CMakeFiles/TH.dir/THVector.c.o
[ 93%] Building C object CMakeFiles/TH.dir/THAtomic.c.o
...
/data/pytorch/torch/lib/tmp_install/include/THC/THCNumerics.cuh(38): warning: integer conversion resulted in a change of sign
...
Compiling src/reduce_scatter.cu               > /data/pytorch/torch/lib/build/nccl/obj/reduce_scatter.o
ptxas warning : Too big maxrregcount value specified 96, will be ignored
ptxas warning : Too big maxrregcount value specified 96, will be ignored
...
byte-compiling /opt/anaconda2/lib/python2.7/site-packages/torch/utils/data/__init__.py to __init__.pyc
byte-compiling /opt/anaconda2/lib/python2.7/site-packages/torch/utils/data/dataset.py to dataset.pyc
byte-compiling /opt/anaconda2/lib/python2.7/site-packages/torch/utils/data/distributed.py to distributed.pyc
byte-compiling /opt/anaconda2/lib/python2.7/site-packages/torch/_utils.py to _utils.pyc
running install_egg_info
running egg_info
creating torch.egg-info
writing requirements to torch.egg-info/requires.txt
writing torch.egg-info/PKG-INFO
writing top-level names to torch.egg-info/top_level.txt
writing dependency_links to torch.egg-info/dependency_links.txt
writing manifest file 'torch.egg-info/SOURCES.txt'
reading manifest file 'torch.egg-info/SOURCES.txt'
writing manifest file 'torch.egg-info/SOURCES.txt'
Copying torch.egg-info to /opt/anaconda2/lib/python2.7/site-packages/torch-0.2.0+efe91fb-py2.7.egg-info
running install_scripts

보시다시피 warning message들이 나왔을 뿐 결국 잘 compile 됩니다.   이제 python에서 torch를 import하여 간단한 test를 몇가지 해보겠습니다.   저는 프로그래밍에 젬병인지라 그냥 pytorch 홈페이지의 튜토리얼 (http://pytorch.org/tutorials/beginner/blitz/tensor_tutorial.html#sphx-glr-beginner-blitz-tensor-tutorial-py) 일부를 그대로 수행해보았습니다.

root@ubuntu:/data/pytorch# python
Python 2.7.13 |Anaconda custom (64-bit)| (default, Mar 16 2017, 18:34:18)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> from __future__ import print_function
>>> import torch
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "torch/__init__.py", line 53, in <module>
    from torch._C import *
ImportError: No module named _C
>>>

시작하자마자 이게 웬 error인가요 ?  이건 다소 우스운 error입니다.  (https://github.com/pytorch/pytorch/issues/7)  pytorch의 설치 directory (여기서는 /data/pytorch)에는 torch라는 이름의 directory가 있는데, 이 directory에서 import torch를 하면 이 directory name과 중복되어 error가 나는 것입니다.  그냥 다른 directory로 옮기셔서 python을 수행하시면 이 error는 나지 않습니다. 

root@ubuntu:/data/pytorch# ls
build            DLConvertor.h  LICENSE           test            tox.ini
cmake            dlpack.h       README.md         tools
CONTRIBUTING.md  Dockerfile     requirements.txt  torch
DLConvertor.cpp  docs           setup.py          torch.egg-info

이제 다른 아무 directory로 옮겨가서 거기서 python을 수행하겠습니다.

root@ubuntu:/data/pytorch# cd

root@ubuntu:~# python
Python 2.7.13 |Anaconda custom (64-bit)| (default, Mar 16 2017, 18:34:18)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> from __future__ import print_function
>>> import torch

예, 이번에는 이상없이 import됩니다.  Torch에서 사용하는 Tensor 및 rand 함수를 써보겠습니다.

>>> x = torch.Tensor(5, 3)
>>> print(x)

 0.0000e+00  0.0000e+00  0.0000e+00
 0.0000e+00  9.1957e+35  2.2955e-41
 9.2701e+35  2.2955e-41  1.1673e+36
 2.2955e-41  9.2913e+35  2.2955e-41
 0.0000e+00  0.0000e+00  0.0000e+00
[torch.FloatTensor of size 5x3]

>>> x = torch.rand(5, 3)
>>> print(x)

 0.7949  0.8651  0.0330
 0.5913  0.2181  0.9074
 0.7759  0.0349  0.9361
 0.3618  0.9953  0.8532
 0.2193  0.1514  0.6486
[torch.FloatTensor of size 5x3]

>>> print(x.size())
(5L, 3L)

>>> y = torch.rand(5, 3)
>>> print(x + y)

 0.8520  1.0601  0.7188
 0.7161  0.3146  1.0981
 1.4604  1.0081  0.9696
 1.1450  1.7239  1.2189
 0.2487  0.9476  1.6199
[torch.FloatTensor of size 5x3]

>>> print(torch.add(x, y))

 0.8520  1.0601  0.7188
 0.7161  0.3146  1.0981
 1.4604  1.0081  0.9696
 1.1450  1.7239  1.2189
 0.2487  0.9476  1.6199
[torch.FloatTensor of size 5x3]

>>> result = torch.Tensor(5, 3)
>>> torch.add(x, y, out=result)

 0.8520  1.0601  0.7188
 0.7161  0.3146  1.0981
 1.4604  1.0081  0.9696
 1.1450  1.7239  1.2189
 0.2487  0.9476  1.6199
[torch.FloatTensor of size 5x3]

>>> y.add_(x)

 0.8520  1.0601  0.7188
 0.7161  0.3146  1.0981
 1.4604  1.0081  0.9696
 1.1450  1.7239  1.2189
 0.2487  0.9476  1.6199
[torch.FloatTensor of size 5x3]

다 잘 됩니다.  Torch Tensor를 numpy Array로 전환하는 것도 해보겠습니다.

>>> a = torch.ones(5)
>>> print(a)

 1
 1
 1
 1
 1
[torch.FloatTensor of size 5]

>>> b = a.numpy()
>>> print(b)
[ 1.  1.  1.  1.  1.]

>>> a.add_(1)

 2
 2
 2
 2
 2
[torch.FloatTensor of size 5]

>>> print(b)
[ 2.  2.  2.  2.  2.]

다 잘 됩니다.   이제 GPU를 써서 pytorch를 구동해보겠습니다.

>>> if torch.cuda.is_available():
...     x = x.cuda()
...     y = y.cuda()
...     x + y
...

 1.6470  1.9252  0.7518
 1.3074  0.5327  2.0054
 2.2363  1.0430  1.9057
 1.5068  2.7193  2.0721
 0.4680  1.0990  2.2685
[torch.cuda.FloatTensor of size 5x3 (GPU 0)]

역시 잘 됩니다.  저 위의 .cuda()가 구동되는 순간 아래와 같이 GPU를 이미 python이 점거하는 것을 보실 수 있습니다.

Tue Oct 10 00:13:54 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 361.119                Driver Version: 361.119                   |
|-------------------------------+----------------------+----------------------+
| 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 K80           Off  | 0000:03:00.0     Off |                    0 |
| N/A   44C    P0    58W / 149W |    200MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla K80           Off  | 0000:04:00.0     Off |                    0 |
| N/A   30C    P8    31W / 149W |      2MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla K80           Off  | 0020:03:00.0     Off |                    0 |
| N/A   35C    P8    26W / 149W |      2MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla K80           Off  | 0020:04:00.0     Off |                    0 |
| N/A   30C    P8    29W / 149W |      2MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0     40655    C   python                                         198MiB |
+-----------------------------------------------------------------------------+


이제 가장 간단한 deep learning 예제인 MNIST를 pytorch로 수행해보겠습니다.   먼저, 아래와 같이 pytorch에서 제공하는 example source code를 download 받습니다.

root@ubuntu:/data# git clone --recursive https://github.com/pytorch/examples.git
Cloning into 'examples'...
remote: Counting objects: 1461, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 1461 (delta 1), reused 2 (delta 0), pack-reused 1455
Receiving objects: 100% (1461/1461), 29.95 MiB | 6.56 MiB/s, done.
Resolving deltas: 100% (767/767), done.
Checking connectivity... done.

root@ubuntu:/data# cd examples/mnist

다운받은 requirements.txt 속에는 아래와 같이 torch와 torchvision의 2줄이 들어있습니다.

root@ubuntu:/data/examples/mnist# vi requirements.txt
torch
torchvision

여기에 대해 pip로 install하면 다음과 같이 torchvision이 새로 설치됩니다.

root@ubuntu:/data/examples/mnist# pip install -r requirements.txt
Requirement already satisfied: torch in /opt/anaconda2/lib/python2.7/site-packages (from -r requirements.txt (line 1))
Collecting torchvision (from -r requirements.txt (line 2))
  Downloading torchvision-0.1.9-py2.py3-none-any.whl (43kB)
    100% |████████████████████████████████| 51kB 423kB/s
Requirement already satisfied: pyyaml in /opt/anaconda2/lib/python2.7/site-packages (from torch->-r requirements.txt (line 1))
Requirement already satisfied: numpy in /opt/anaconda2/lib/python2.7/site-packages (from torch->-r requirements.txt (line 1))
Requirement already satisfied: pillow in /opt/anaconda2/lib/python2.7/site-packages (from torchvision->-r requirements.txt (line 2))
Requirement already satisfied: six in /opt/anaconda2/lib/python2.7/site-packages (from torchvision->-r requirements.txt (line 2))
Requirement already satisfied: olefile in /opt/anaconda2/lib/python2.7/site-packages (from pillow->torchvision->-r requirements.txt (line 2))
Installing collected packages: torchvision
Successfully installed torchvision-0.1.9

이제 남은 것은 mnist directory에 들어있는 main.py를 수행하기만 하면 됩니다.

root@ubuntu:/data/examples/mnist# python main.py
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz
Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz
Processing...
...
Train Epoch: 10 [55040/60000 (92%)]     Loss: 0.148484
Train Epoch: 10 [55680/60000 (93%)]     Loss: 0.215679
Train Epoch: 10 [56320/60000 (94%)]     Loss: 0.122693
Train Epoch: 10 [56960/60000 (95%)]     Loss: 0.120907
Train Epoch: 10 [57600/60000 (96%)]     Loss: 0.153347
Train Epoch: 10 [58240/60000 (97%)]     Loss: 0.100982
Train Epoch: 10 [58880/60000 (98%)]     Loss: 0.272780
Train Epoch: 10 [59520/60000 (99%)]     Loss: 0.079338

Test set: Average loss: 0.0541, Accuracy: 9815/10000 (98%)

10번의 epoch(전체 training dataset을 총 10회 반복 training했다는 뜻) 만에 98.15%의 accuracy를 결과로 냅니다.   이 과정에서는 물론 GPU는 1장만 쓰는데, 대략 30~35%의 사용률을 보입니다.  (이거 P100이 아니라 K80입니다.  착오 없으시기 바랍니다.)


Tue Oct 10 00:23:02 2017
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 361.119                Driver Version: 361.119                   |
|-------------------------------+----------------------+----------------------+
| 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 K80           Off  | 0000:03:00.0     Off |                    0 |
| N/A   44C    P0    62W / 149W |    380MiB / 11441MiB |     30%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla K80           Off  | 0000:04:00.0     Off |                    0 |
| N/A   30C    P8    31W / 149W |      2MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla K80           Off  | 0020:03:00.0     Off |                    0 |
| N/A   36C    P8    26W / 149W |      2MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla K80           Off  | 0020:04:00.0     Off |                    0 |
| N/A   30C    P8    29W / 149W |      2MiB / 11441MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID  Type  Process name                               Usage      |
|=============================================================================|
|    0     40735    C   python                                         378MiB |
+-----------------------------------------------------------------------------+