Pensieve Books, Programming

Jetson TX1에 CNTK 2.5 설치하기

NOTICE: The English version of this manual is on the README.md page of my forked repository of CNTK at GitHub.

이 포스트에서는 Jetson TX1에 CNTK 2.5를 설치하는 방법을 설명하겠습니다. 이 포스트는 공식 CNTK 사이트의 Setup CNTK on Linux 문서를 참조하였습니다.

CNTK 프로젝트 팀은 리눅스 환경에서 실행할 수 있는 도커 이미지를 제공하고 있습니다. 그런데 현재 도커 허브에 제공되어 있는 이미지들은 GPU 기능이 활성화된 버전을 이용하고 싶을 경우 nvidia-docker를 이용해야 한다고 안내되어 있습니다. 문제는 이 nvidia-docker가 테그라 플랫폼(Tegra platform)을 지원하지 않는다는 데에 있습니다. 따라서 TX1에서 CNTK를 돌리기 위해서는 어쩔 수 없이 CNTK 소스코드를 받아서 직접 빌드해야 합니다.

사전작업

  1. TX1에 JetPack 3.2 설치: 포스트 작성 시점에서 최신 JetPack 버전인 3.2 버전이 설치되어 있다고 가정하겠습니다.

  2. TX1 Development Kit에 추가 저장 장치 설치: Jetson TX1 Development Kit를 구매하면 기본 저장장치로 eMMC가 설치되어 있는데 용량이 16GB에 불과합니다. JetPack을 설치하면 저장 공간 부족 문제로 CNTK를 빌드할 수 없습니다. 저는 이 가이드를 참고로 해서 256GB SSD를 설치하였고 TX1이 SSD에서 부팅하도록 하였습니다.

  3. 설치한 추가 저장 장치에 Swap 공간 설정하기: Swap 공간을 설정하지 않으면 빌드 과정에서 메모리 부족 현상이 발생할 수 있습니다. Swap 공간을 설정하는 방법은 여기를 참고하세요.

TX1에서 개발을 진행할 때는 jetson_clocks.sh 스크립트를 실행하는 것이 좋습니다. 이 스크립트는 TX1의 CPU, GPU 및 EMC(메모리 컨트롤러) 클럭을 최대로 설정해줍니다. 이 스크립트는 JetPack을 설치하면 홈 디렉토리에 복사되어 있습니다.

$ sudo ~/jetson_clocks.sh

빌드

CNTK 설치를 위한 사전작업으로 다음의 라이브러리들을 설치하겠습니다.

  • OpenBLAS 0.2.20
  • libzip 1.1.2
  • Boost 1.60.0
  • CUB 1.7.4
  • Protobuf 3.1.0
  • OpenCV 3.1.0

위 라이브러리들을 설치한 후에 CNTK의 configure 스크립트가 위 라이브러리를 잘 찾을 수 있도록 symbolic link를 만드는 과정을 거치도록 하겠습니다.

여기까지 끝나면 CNTK를 빌드할 수 있습니다. GPU 기능이 활성화된 2.5 버전을 빌드하도록 하겠습니다.

OpenBLAS 0.2.20

CNTK에 사용되는 기본 수학 라이브러리는 Intel Math Kernel Library (Intel MKL) 입니다. 그러나 이 라이브러리는 Intel 계열 프로세서만 지원합니다. TX1은 aarch64 기반이므로 우리는 다른 수학 라이브러리를 이용해야 합니다. CNTK는 현재 Intel MKL 말고도 OpenBLAS를 지원하고 있는 것으로 보이므로 (참고1, 참고2) 우리는 OpenBLAS를 사용하도록 하겠습니다. 포스트 작성 시점에서 최신 버전인 0.2.20 버전을 사용하도록 하겠습니다.

OpenBLAS를 빌드하기 전에 gfortran 라이브러리를 설치해야 합니다. 그래야 OpenBLAS에 LAPACKE 라이브러리가 포함되서 빌드가 되는데, 이렇게 하지 않으면 나중에 CNTK 빌드시에 링킹 에러가 발생합니다.

$ git clone https://github.com/xianyi/OpenBLAS.git
$ cd OpenBLAS
$ git checkout v0.2.20
$ sudo apt install gfortran
$ make -j4

빌드가 완료되면 다음과 같이 LAPACK 및 LAPACKE 라이브러리까지 빌드되었다고 나와야 합니다.

 OpenBLAS build complete. (BLAS CBLAS LAPACK LAPACKE)

  OS               ... Linux             
  Architecture     ... arm64               
  BINARY           ... 64bit                 
  C compiler       ... GCC  (command line : gcc)
  Fortran compiler ... GFORTRAN  (command line : gfortran)
  Library Name     ... libopenblas_cortexa57p-r0.2.20.a (Multi threaded; Max num-threads is 4)

이제 빌드된 라이브러리를 다음과 같이 설치하도록 하겠습니다.

$ sudo make install PREFIX=/usr/local/OpenBLAS

libzip 1.1.2

JetPack 3.2는 Ubuntu 16.04를 포함하고 있습니다. Ubuntu 16.04에서 제공하는 libzip 버전은 1.0.1입니다(참고). 그러나 CNTK 문서에서 보다 최신 버전을 설치할 것을 강하게 권고하고 있기 때문에 우리도 문서를 따라 1.1.2 버전을 설치하도록 하겠습니다.

$ wget http://nih.at/libzip/libzip-1.1.2.tar.gz
$ tar xzf ./libzip-1.1.2.tar.gz
$ cd libzip-1.1.2
$ ./configure
$ make -j4
$ sudo make install

Boost 1.60.0

Ubuntu 16.04에서 기본으로 제공하는 버전은 1.58.0입니다(참고). CNTK 문서에서 예시로 든 버전은 1.60.0 버전이어서 1.60.0 버전 소스를 받아 빌드하도록 하겠습니다.

$ wget -q -O - https://sourceforge.net/projects/boost/files/boost/1.60.0/boost_1_60_0.tar.gz/download | tar -xzf -
$ cd boost_1_60_0
$ ./bootstrap.sh --prefix=/usr/local/boost-1.60.0
$ sudo apt install libbz2-dev python-dev
$ sudo ./b2 -d0 -j4 install

(2018-08-01) 참고로 빌드할 때 -fPIC 옵션을 주고 싶으면 다음과 같이 하면 됩니다.

$ sudo ./b2 -d0 -j4 cxxflags="-fPIC" install

CUB 1.7.4

$ wget https://github.com/NVlabs/cub/archive/1.7.4.zip
$ unzip ./1.7.4.zip
$ sudo cp -r cub-1.7.4 /usr/local

Protobuf 3.1.0

Ubuntu 16.04에서 기본으로 제공하는 버전은 2.6.1입니다(참고). 이 버전을 이용해서 CNTK를 빌드하려고 했으나 proto2가 아닌 proto3를 요구하면서 빌드에 실패하였습니다. 따라서 CNTK 문서에 따라 3.1.0 버전을 받아 설치하겠습니다.

$ wget https://github.com/google/protobuf/archive/v3.1.0.tar.gz
$ tar xzf v3.1.0.tar.gz
$ cd protobuf-3.1.0
$ sudo apt install curl
$ ./autogen.sh
$ ./configure CFLAGS=-fPIC CXXFLAGS=-fPIC --disable-shared --prefix=/usr/local/protobuf-3.1.0
$ make -j4
$ sudo make install

OpenCV 3.1.0

$ sudo apt install cmake libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
$ wget https://github.com/opencv/opencv/archive/3.1.0.zip
$ unzip 3.1.0.zip
$ cd opencv-3.1.0
$ mkdir release
$ cd release
$ cmake -D WITH_CUDA=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local/opencv-3.1.0 -D BUILD_PERF_TESTS=OFF -D BUILD_TESTS=OFF ..
$ make all
$ sudo make install

추가 설정

CNTK configure 스크립트가 우리가 설치한 라이브러리들을 알아볼 수 있도록 심볼릭 링크(symbolic link)를 생성하도록 하겠습니다.

# create symbolic links for CUDNN
$ sudo mkdir /usr/local/cudnn-7.0/cuda/include -p
$ sudo ln -s /usr/lib/aarch64-linux-gnu /usr/local/cudnn-7.0/lib
$ sudo ln -s /usr/include/aarch64-linux-gnu/cudnn_v7.h /usr/local/cudnn-7.0/cuda/include/cudnn.h

# create symbolic link for NVML
$ sudo ln -s /usr/local/cuda-9.0/targets/aarch64-linux/include/nvml.h /usr/local/include

# create symbolic link for Open MPI C++ wrapper compiler
$ sudo mkdir /usr/lib/openmpi/bin
$ sudo ln -s /usr/bin/mpic++ /usr/lib/openmpi/bin/mpic++

CNTK 2.5

이제 본격적으로 CNTK를 빌드하겠습니다.

$ git clone https://github.com/nglee/CNTK.git
$ cd CNTK
$ git checkout v2.5_tx1
$ mkdir build/release -p
$ cd build/release
$ ../../configure --asgd=no \
                  --cuda=yes \
                  --with-openblas=/usr/local/OpenBLAS \
                  --with-boost=/usr/local/boost-1.60.0 \
                  --with-cudnn=/usr/local/cudnn-7.0 \
                  --with-protobuf=/usr/local/protobuf-3.1.0 \
                  --with-mpi=/usr/lib/openmpi \
                  --with-gdk-include=/usr/local/include \
                  --with-gdk-nvml-lib=/usr/local/cuda-9.0/targets/aarch64-linux/lib/stubs
$ make -C ../../ \
       BUILD_TOP=$PWD \
       SSE_FLAGS='' \
       GENCODE_FLAGS='-gencode arch=compute_53,code=\"sm_53,compute_53\"' \
       all \
       -j 4

빌드가 완료되면 libbin 디렉토리가 생성되고 그 밑에 CNTK 2.5 라이브러리와 바이너리가 위치하게 됩니다.

테스트

CNTK가 제대로 빌드되었는지 확인하기 위해 여기에 나온 테스트 스텝을 따라할 수 있습니다. 그러나 TX1은 NVML(NVIDIA Management Library) 관련해서 조심해야 할 부분이 있습니다. 여기에 나와있듯이 NVML은 TX1을 지원하지 않고, stub 라이브러리만 제공합니다. 테스트에 사용할 cntk라는 바이너리는 NVML을 필요로하기 때문에 stub 라이브러리를 사용해서 동작하도록 설정하겠습니다.

$ export LD_LIBRARY_PATH=/usr/local/cuda-9.0/targets/aarch64-linux/lib/stubs:$LD_LIBRARY_PATH
$ sudo ln -s /usr/local/cuda-9.0/targets/aarch64-linux/lib/stubs/libnvidia-ml.so /usr/local/cuda-9.0/targets/aarch64-linux/lib/stubs/libnvidia-ml.so.1

Stub 라이브러리를 설정한 후에 다음과 같이 CPU로 CNTK를 돌려보겠습니다.

$ export PATH=$HOME/Repos/cntk/build/release/bin:$PATH
$ cd [CNTK_SOURCE_BASE]/Tutorials/HelloWorld-LogisticRegression
$ cntk configFile=lr_bs.cntk makeMode=false

GPU로 CNTK를 돌리기 위해서는 다음과 같이 합니다.

$ cntk configFile=lr_bs.cntk makeMode=false deviceId=auto

(2018-08-01) x86_64 기반 컴퓨터에서 빌드하기

OpenBLAS 대신 mklml을 사용한다는 것 빼고는 기본적으로 동일합니다. 아래 명령어에 나오는 “compute_XX”, “sm_XX”와 같은 부분들은 자신의 컴퓨터의 그래픽카드 사양에 맞게 설정하면 됩니다. 그래픽카드의 cc 값을 확인해서 “XX” 부분에 넣으면 됩니다.

release build

$ ../../configure --asgd=no \
                  --cuda=yes \
                  --with-mkl=/usr/local/mklml/mklml_lnx_2018.0.3.20180406 \
                  --with-cudnn=/usr/local \
                  --with-protobuf=/usr/local/protobuf-3.1.0 \
                  --with-mpi=/usr/local/mpi
$ make -C ../../ \
       BUILD_TOP=$PWD \
       GENCODE_FLAGS='-gencode arch=compute_50,code=\"sm_50,compute_50\"' \
       -j4 \
       all

debug build

$ ../../configure --asgd=no \
                  --cuda=yes \
                  --with-mkl=/usr/local/mklml/mklml_lnx_2018.0.3.20180406 \
                  --with-cudnn=/usr/local \
                  --with-protobuf=/usr/local/protobuf-3.1.0 \
                  --with-mpi=/usr/local/mpi \
                  --with-buildtype=debug
$ make -C ../../ \
       BUILD_TOP=$PWD \
       GENCODE_FLAGS='-gencode arch=compute_50,code=\"sm_50,compute_50\"' \
       -j4 \
       all

Show ChangeLog