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을 누르면서 진행해보실 수 있습니다.







댓글 없음:

댓글 쓰기