2018년 7월 13일 금요일

Redhat 7.5 ppc64le에서 CRAN-R을 source로부터 설치하기


전에 Ubuntu 16.04 ppc64le에서 CRAN-R을 설치하는 과정을 올린 바 있습니다만, 이번에는 Redhat의 경우입니다.   대부분의 과정은 비슷합니다.

먼저, Redhat EPEL에 포함된 R은 3.5 버전입니다.  이걸 쓰셔도 된다면 그냥 이걸 설치하시는 것이 편합니다. 

[root@ING ~]# yum list | grep R-core
R-core.ppc64le                      3.5.0-1.el7         epel
R-core-devel.ppc64le                3.5.0-1.el7         epel


그러나 특정 버전, 가령 3.4.1을 설치하시려면 다음과 같이 CRAN에서 source를 받아다 설치하시면 됩니다.   먼저 기존에 설치된 R 3.5 버전을 다음과 같이 삭제합니다.

[root@ING ~]# yum erase R R-core R-core-devel R-devel R-java R-java-devel

이어서 기본적으로 필요한 OS package들을 설치합니다.

[root@ING test]# yum install readline-devel readline-static libX11-devel libX11-common libXt-devel libXt bzip2 bzip2-libs bzip2-devel lzma-sdk-devel lzma-sdk457-devel pcre2-devel pcre3-devel gcc-gfortran libgfortran libcurl-devel curl texlive-latex texlive-latex-fonts texlive-txfonts texlive-pxfonts texlive-fontaxes java-1.8.0-openjdk java-1.8.0-openjdk-devel java-1.8.0-openjdk-headless

이제 source를 download 받습니다.

[root@ING test]# wget https://cran.r-project.org/src/base/R-3/R-3.4.1.tar.gz

[root@ING test]# tar -zxf R-3.4.1.tar.gz

[root@ING test]# cd R-3.4.1

Build 순서는 똑같습니다.  configure - make - make install 순입니다.

[root@ING R-3.4.1]# ./configure --enable-R-shlib

[root@ING R-3.4.1]# make -j 16

[root@ING R-3.4.1]# make install

이렇게 설치하면 기본적으로 /usr/local/lib64/R 밑에 설치됩니다.

[root@ING R]# pwd
/usr/local/lib64/R

[root@ING R]# ls
bin  COPYING  doc  etc  include  lib  library  modules  share  SVN-REVISION

그러나 별도로 PATH를 잡아주지 않아도 이미 /usr/local/bin에 R이 copy되어 있으므로 그냥 그대로 쓰시면 됩니다.

[root@ING ~]# which R
/usr/local/bin/R

[root@ING ~]# R

R version 3.4.1 (2017-06-30) -- "Single Candle"
Copyright (C) 2017 The R Foundation for Statistical Computing
Platform: powerpc64le-unknown-linux-gnu (64-bit)
...
Type 'q()' to quit R.

> install.packages("knitr")

> install.packages("anim.plots")



*  저같은 경우 ./configure --enable-R-shlib 수행시 처음에는 아래와 같은 error가 발생했습니다.

configure: error: libcurl >= 7.22.0 library and headers are required with support for https

그러나 실제로 보면 아래처럼 libcurl은 이미 7.29 버전이 설치되어 있습니다. 

[root@ING R-3.4.1]# yum list | grep libcurl
libcurl.ppc64le                     7.29.0-46.el7       @anaconda/7.5
libcurl-devel.ppc64le               7.29.0-46.el7       @rhel-7-for-power-9-rpms

이 error의 원인은 다음과 같이 config.log를 뒤져보면 알 수 있습니다.  즉, 환경 설정에서 PATH 변수 맨 앞에 anaconda2가 오도록 되어 있었는데, anaconda2 속에 설치된 libcurl의 버전이 낮은 것이 원인이었습니다.


[root@ING R-3.4.1]# env | grep PATH
PATH=/opt/anaconda2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/opt/DL/tensorflow/bin:/opt/DL/protobuf/bin:/opt/DL/caffe-bvlc/bin

[root@ING R-3.4.1]# grep libcurl config.log
configure:40993: checking if libcurl is version 7 and >= 7.22.0
/usr/bin/ld: warning: libssl.so.1.0.0, needed by /opt/anaconda2/lib/libcurl.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libcrypto.so.1.0.0, needed by /opt/anaconda2/lib/libcurl.so, not found (try using -rpath or -rpath-link)
/opt/anaconda2/lib/libcurl.so: undefined reference to `SSL_CTX_set_srp_username'
/opt/anaconda2/lib/libcurl.so: undefined reference to `libssh2_scp_recv2'
/opt/anaconda2/lib/libcurl.so: undefined reference to `SSL_CTX_set_srp_password'
configure:41089: error: libcurl >= 7.22.0 library and headers are required with support for https

이는 간단히 PATH 환경 변수에서 anaconda2를 제거한 뒤 configure를 수행하면 간단히 핵결됩니다.



2018년 7월 3일 화요일

PowerAI R5.2가 docker image로도 나왔습니다


PowerAI는 v1.4까지는 internet에서 자유롭게 download 받아서 쓸 수 있도록 되어 있었으나, v1.5부터는 별도로 주문을 해야 download 받을 수 있도록 바뀌었습니다.  다만 이때도 machine serial #만 넣으면 무료로 주문이 되니까 비용 부담은 없었습니다.   그래도 불편한 것은 사실이었지요.

그 점은 여전합니다만, v1.5.2, 즉 R5.2부터는 PowerAI를 포함한 docker image로도 배포가 됩니다. 

Redhat 7.5와 docker 13.1, nvidia-docker 1.0을 설치한 AC922 위에서 쓸 수 있는 이 docker image는 Ubuntu 16.04에 CUDA 9.2 기반으로 만들어져 있습니다.  그리고 그 속에 포함된 PowerAI R5.2 속에는 다음과 같은 component 들이 들어있습니다.

특히 IBM이 별도로 만들어 contribute한 Snap ML도 들어있는 것이 눈에 띕니다.


ComponentVersion
Distributed Deep Learning (DDL)1.0.0
TensorFlow1.8.0
TensorBoard1.8.0
IBM Caffe1.0.0
BVLC Caffe1.0.0
PyTorch0.4.0
Snap ML1.0.0
Spectrum MPI10.2
Bazel0.10.0
OpenBLAS0.2.20
Protobuf3.4.0

사용법은 일반 docker와 동일하며 간단합니다.  아래와 같이 pull 해서...

# docker pull ibmcom/powerai

다음과 같이 사용하시면 됩니다. 

# nvidia-docker run -ti --env LICENSE=yes ibmcom/powerai bash

현재 사용가능한 tag은 1.5.2-all-ubuntu16.04와 1.5.2-all-ubuntu16.04-py3이 있습니다.   가령 python3에서 tensorflow를 사용하시고자 한다면 아래와 같이 py3 tag를 붙여서 pull/run 하시면 됩니다.

# docker pull ibmcom/powerai:1.5.2-all-ubuntu16.04-py3

# nvidia-docker run -ti --env LICENSE=yes ibmcom/powerai:1.5.2-all-ubuntu16.04-py3 bash


더 자세한 내용은 아래 site를 참조하세요.

https://developer.ibm.com/linuxonpower/deep-learning-powerai/releases/

https://hub.docker.com/r/ibmcom/powerai/


Redhat ppc64le에서의 OS disk mirroring (SW RAID1)

기존 posting http://hwengineer.blogspot.com/2017/03/ppc64le-power8-ubuntu-sw-raid.html 에서는 Ubuntu ppc64le 환경에서 mdadm device (SW RAID1) 구성을 통해 2장의 내장 disk에 OS mirror를 구성하는 방법을 소개시켜 드렸습니다.  아시다시피 x86 아키텍처와는 달리 ppc64le에는 boot loader를 보관하는 PReP이라는 파티션이 디스크 맨 앞 부분에 존재해야 하는데, 이것은 mdadm으로는 mirror가 되지 않습니다.  다만 이 boot loader는 한번 설치되면 거기에 추가로 write될 일이 없으므로, dd 명령어를 통해 source에서 target으로 copy만 떠 놓으면 OS mirror를 사용하는데 지장이 없습니다.   그를 위해서 사용한 작은 trick은, OS 설치시 먼저 양쪽 disk에 PReP을 포함한 모든 파티션을 만들어놓되, mdadm device는 PReP을 뺸 나머지 device에 대해서만 걸어두는 것이었습니다. 

이제 POWER9과 V100을 장착한 AC922 서버는 현재까지는 주로 Redhat을 이용하는데, Redhat에서도 이런 OS mirror가 가능할까요 ?  불행히도 Redhat installer는 Ubuntu installer와는 약간 달라서, OS 설치시 각각의 disk에 먼저 파티션을 만든 뒤 어느 파티션을 무엇으로 사용할지 정하는 것이 아니라, 먼저 파티션 용도를 지정하면 자동으로 mirror device가 생성됩니다.  그래서 SW RAID1으로 그냥 설치하면 PReP과 /boot는 1번 disk에만 만들어지고, 2번 디스크 앞 부분에는 PReP 파티션을 만들 공간을 따로 확보할 수 없게 됩니다.






이 문제에 대한 workaround가 있습니다.  이 방법은 Kolon의 정유영 대리께서 고안해냈고, 테스트에서 1번 disk를 뽑아낸 뒤 리부팅을 해봐도 정상적으로 리부팅이 되었습니다.  수고해주신 정유영 대리께 감사드립니다.   

이 workaround의 절차를 요약하면 아래와 같습니다.

1) 먼저 Redhat installer가 시키는 대로, PReP과 /boot를 제외한 OS mirror를 mdadm device를 구성하여 완료합니다.
2) OS 설치 완료 뒤 mdadm 명령으로 2번 디스크의 mirror copy를 제거하여 blank disk로 만듭니다.
3) 그렇게 비워진 2번 disk에 1번 disk와 동일한 크기로 PReP과 /boot를 포함한 파티션들을 새로 만듭니다.
4) 그 중 PReP과 /boot에는 dd 명령을 통해 1번 disk의 원본을 copy합니다.
5) 나머지 OS용 파티션에는 mdadm 명령으로 mirror copy를 새로 add 합니다.

간단하지요 ?  다만 이렇게 할 경우, 나중에 혹시 /boot에 뭔가 write를 할 일이 있다면 그 내용을 2번째 disk에 다시 dd 명령으로 write를 해줘야 하긴 합니다.  물론 /boot에는 write가 일어날 일은 거의 없습니다.  이제 위의 내용을 좀 더 자세히 정리해놓겠습니다.



1. 2개의 디스크중 "/"와 "swap" 부분을 mdadm device (즉 SW RAID1)으로 구성 해서 설치합니다.   이때 PReP과 /boot는 제외됩니다.
 - PReP은 그렇다치고, 왜 /boot도 mdadm device로 구성이 안되는지는 의아하긴 합니다.

2. OS 설치 완료 후 OS 명령어 mdadm를 통해 MD device로 구성된  /와 swap에서 2번 디스크를 제거

# mdadm --manage /dev/md126 --remove /dev/sdb1    (swap 영역)
# mdadm --manage /dev/md127 --remove /dev/sdb2    (/ 영역)

3. 이제 텅 비게 된 2번 디스크를 1번 디스크와 동일하게 fdisk 명령을 이용해서 파티셔닝

# fdisk -l /dev/sda    (1번 disk의 파티션 상황 파악)
# fdisk /dev/sdb   (위의 정보에서 얻은 1번 disk 파티션과 동일하게 2번 disk에 파티션을 구성)
 - 특히 맨 앞에 만드는 /dev/sdb1의 disk type은 41 (PPC PReP Boot)으로 구성해줘야 합니다.

# fdisk /dev/sda
...
Command (m for help): t
Hex code (type L to list all codes): 41
Changed type of partition 'Linux' to 'PPC PReP Boot'
...

그래서 다음과 같이 두 disk가 동일한 파티션 정보를 가지도록 만듭니다.

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048       18431        8192   41  PPC PReP Boot
/dev/sda2           18432     1067007      524288   83  Linux
/dev/sda3         1067008     9455615     4194304   82  Linux swap / Solaris
/dev/sda4         9455616  1875384319   932964352    5  Extended
/dev/sda5         9457664  1875384319   932963328   8e  Linux LVM

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048       18431        8192   41  PPC PReP Boot
/dev/sdb2           18432     1067007      524288   83  Linux
/dev/sdb3         1067008     9455615     4194304   82  Linux swap / Solaris
/dev/sdb4         9455616  1875384319   932964352    5  Extended
/dev/sdb5         9457664  1875384319   932963328   8e  Linux LVM

4. 이제 mdadm 명령으로 /와 swap 파티션의 mirror 구성을 실시합니다.

# mdadm --manage /dev/md126 --add /dev/sdb3    (swap 영역)
# mdadm --manage /dev/md127 --add /dev/sdb5    (/ 영역)

5. PReP 파티션을 dd 명령으로 복사합니다.

# dd if=/dev/sda1 of=/dev/sdb1 bs=1024k

6. /boot 파티션을 dd 명령으로 복사합니다.   단, 이 경우는 먼저 신규 /boot에 filesystem을 만들고, 또 기존 /boot를 umount하고 진행해야 합니다.

먼저 기존 /boot가 어떤 type의 filesystem으로 만들어졌는지 확인합니다.  여기서는 xfs로 되어 있습니다. 

# mount | grep boot
/dev/sda2 on /boot type xfs (rw,relatime,attr2,inode64,noquota)

거기에 대응해서 동일 size로 만들어 두었던 /dev/sdb2를 xfs로 format 합니다.  (이 format superblock은 dd로 copy가 안되더라고요)

# mkfs -t xfs -f /dev/sdb2

그 다음에 반드시 먼저 기존의 /boot를 umount 하고 dd를 뜹니다.  (mount된 상태에서 dd를 뜨면 superblock이 copy 되지 않습니다.)

# umount /boot
# dd if=/dev/sda2 of=/dev/sdb2 bs=1024k

이제 보면 xfs_admin 명령으로 확인해보면 /dev/sdb2에도 /dev/sda2와 동일한 UUID가 들어가 있습니다.  이렇게 동일한 UUID를 사용하므로, /boot/grub2/grub.cfg를 굳이 수정할 필요가 없습니다.  다만 이로 인해 서버 부팅 시에 /boot로 /dev/sda2가 아니라 /dev/sdb2가 mount될 가능성도 있는데, 어차피 같은 copy이고 거기에 write가 일어날 일도 거의 없으므로 문제될 것은 없습니다.

#  xfs_admin -u /dev/sda2
UUID = 20a94402-8589-48db-b8cf-e82c16f415ee

#  xfs_admin -u /dev/sdb2
UUID = 20a94402-8589-48db-b8cf-e82c16f415ee

그리고 mount 해서 보면 원래의 /boot와 동일한 file들이 동일하게 보입니다.

# mount /dev/sda2 /boot
# mount /dev/sdb2 /mnt

# ls -l /boot
total 183444
-rw-r--r--. 1 root root   138001 Oct 17  2017 config-4.11.0-44.el7a.ppc64le
drwxr-xr-x. 3 root root       17 May 30 14:58 efi
drwx------. 5 root root      118 May 30 17:11 grub2
-rw-------. 1 root root 64932747 May 30 15:07 initramfs-0-rescue-168b61eb0f2d43cb8783c83d162b35f9.img
-rw-------. 1 root root 44154461 May 30 17:11 initramfs-4.11.0-44.el7a.ppc64le.img
-rw-------. 1 root root 22527454 May 30 15:27 initramfs-4.11.0-44.el7a.ppc64lekdump.img
-rw-r--r--. 1 root root 10382937 May 30 15:06 initrd-plymouth.img
-rw-r--r--. 1 root root   250055 Oct 17  2017 symvers-4.11.0-44.el7a.ppc64le.gz
-rw-------. 1 root root  2754018 Oct 17  2017 System.map-4.11.0-44.el7a.ppc64le
-rwxr-xr-x. 1 root root 21346760 May 30 15:07 vmlinuz-0-rescue-168b61eb0f2d43cb8783c83d162b35f9
-rwxr-xr-x. 1 root root 21346760 Oct 17  2017 vmlinuz-4.11.0-44.el7a.ppc64le

# ls -l /mnt
total 183444
-rw-r--r--. 1 root root   138001 Oct 17  2017 config-4.11.0-44.el7a.ppc64le
drwxr-xr-x. 3 root root       17 May 30 14:58 efi
drwx------. 5 root root      118 May 30 17:11 grub2
-rw-------. 1 root root 64932747 May 30 15:07 initramfs-0-rescue-168b61eb0f2d43cb8783c83d162b35f9.img
-rw-------. 1 root root 44154461 May 30 17:11 initramfs-4.11.0-44.el7a.ppc64le.img
-rw-------. 1 root root 22527454 May 30 15:27 initramfs-4.11.0-44.el7a.ppc64lekdump.img
-rw-r--r--. 1 root root 10382937 May 30 15:06 initrd-plymouth.img
-rw-r--r--. 1 root root   250055 Oct 17  2017 symvers-4.11.0-44.el7a.ppc64le.gz
-rw-------. 1 root root  2754018 Oct 17  2017 System.map-4.11.0-44.el7a.ppc64le
-rwxr-xr-x. 1 root root 21346760 May 30 15:07 vmlinuz-0-rescue-168b61eb0f2d43cb8783c83d162b35f9
-rwxr-xr-x. 1 root root 21346760 Oct 17  2017 vmlinuz-4.11.0-44.el7a.ppc64le

확인이 끝났으면 /mnt는 umount하고 사용을 시작하시면 됩니다. 
# umount /mnt

이로써 OS mirroring이 다 끝난 것입니다. 

2018년 6월 20일 수요일

세계 최대의 수퍼컴 Summit에 대한 가벼운 이야기들

2018년 6월 9일, 드디어 세계 최대의 수퍼컴 Summit이 발표되었습니다.   요구되었던 '최소 150 PetaFLOPS 이상'을 훌쩍 뛰어넘은 200 PetaFLOPS을 구축했고, 이로서 중국의 TaihuLight에게 넘겨주었던 기존의 세계 최대 수퍼컴이라는 타이틀을 5년만에 미국이 되찾아 왔습니다.

수퍼컴이 사용되는 HPC (High Performance Computing)라는 분야는 과학기술 쪽의 박사님들 외에는 잘 모르시고 또 알 필요도 없는 분야입니다만, 이번 글에서는 IT가 아닌 분들도 쉽고 흥미있게 읽으실 수 있도록 이 세계 최대의 수퍼컴에 대해 써봤습니다.



(Summit에 관련된 인포그래픽입니다.   원본은 https://www.olcf.ornl.gov/wp-content/uploads/2018/06/Summit_bythenumbers_FIN.png 입니다.)


1.  CORAL project란 무엇인가 ?

전세계 수퍼컴의 연산능력은 1등부터 500등까지 순위대로 top500.org에 등재됩니다. 여기에 얼마나 많은 수퍼컴이 등재되었는지, 또 얼마나 큰 수퍼컴이 등재되는지가 월드컵 순위나 GDP 순위처럼 일종의 국력의 척도로서 자존심 싸움이 되기도 합니다.  그런데 2013년, 중국이 자체 개발한 TaihuLight라는 수퍼컴이 미국을 따돌리고 세계 최대의 수퍼컴이 되었습니다.  그 성능은 100 PetaFLOPS(Peta = 10의 15승, FLOPS = FLoating Point Operations Per Second = 초당 부동소수점 연산)였습니다.

꼭 이것 때문이라고 하기는 어렵겠으나, 미국의 수퍼컴 프로젝트를 주관하는 미국 에너지성(Department of Energy)에서는 바로 다음해인 2014년 CORAL (Collaboration of Oak Ridge, Argonne, and Livermore)이라는 이름의 프로젝트 하에 오크 릿지, 아르곤, 로렌스 리버모어의 세 국립 연구소의 수퍼컴을 업그레이드/대체하는 사업을 발표합니다.  그 중 오크 릿지와 로렌스 리버모어는 IBM와 NVIDIA, 그리고 인피니밴드 업체인 Mellanox의 OpenPOWER 컨소시엄이 수주한 것입니다.   아르곤에서는 인텔이 주사업자로서 Intel Xeon CPU와 Xeon Phi 가속기를 이용한 수퍼컴을 구축하게 되었습니다.   이 세 연구소의 수퍼컴 중 가장 큰 것은 Summit 입니다.


2.  오크 릿지 Summit 성능이 발표 되었으니, 이제 구축이 끝난 것인가 ?

아닙니다.  아직 Summit은 구축 중이며, 내년 초에나 정식 오픈하는 것으로 되어 있습니다.  물론 최근인 6월 8일, 오크 릿지는 Summit의 성능이 200 PetaFLOPS라고 발표했습니다.  원래 2014년에 나왔던 제안요청서(RFP)에는 150 PetaFLOPS 이상의 성능을 가질 것이 요구되었는데, 그 기준을 여유있게 통과한 것입니다.   다만 6월 20일 현재, 아직 top500.org에는 등재되지 않았습니다.  Top500 list는 매년 6월과 11월, 2차례에 걸쳐 등재되는데, 6월 말에나 업데이트가 될 예정입니다.


3.  최근 볼턴 미 백악관 안보 보좌관이 북한의 핵탄두를 오크 릿지로 반출해야 한다고 주장했는데, 그 오크 릿지가 이 오크 릿지인가 ?

맞습니다.  테네시 주의 오크 릿지에 위치한 오크 릿지 국립 연구소는 제2차 세계대전 당시 미국의 핵무기 개발을 위한 극비 프로젝트였던 맨하탄 계획이 수행된 곳입니다.  다만 볼턴 보좌관이 언급한 곳이 이 국립 연구소를 뜻하는 것인지 아니면 바로 옆에 있는 핵연료 처리 시설인 Y-12 National Security Complex를 가리키는 것인지는 불분명하다고 합니다.


(오크 릿지 연구소 바로 옆에 위치한 Y-12 핵시설입니다.  여기서 제2차 세계대전 때 히로시마와 나가사키에 투하된 원폭을 만들었습니다.)


4.  왜 같은 CORAL 프로젝트 중에서 오크 릿지 연구소의 Summit에 대해서만 이야기가 많고, 로렌스 리버모어 연구소의 Sierra에 대해서는 발표되는 것이 거의 없는가 ?

두가지 이유가 있습니다.  첫째, 오크 릿지의 Summit이 더 크고 더 먼저 시작했습니다.  둘째, 로렌스 리버모어의 보안이 훨씬 엄중합니다.

오크 릿지에서도 고에너지 물리학, 즉 핵물리학 연구를 계속 합니다만, 일반 민간 연구용으로도 컴퓨팅 파워를 빌려줍니다만, 로렌스 리버모어 연구소는 정말 순수하게 핵무기 등 국가 안보 관련된 연구를 하는 곳이라서 외부인들이 Sierra에 접속하여 민간용 연구를 할 일은 없을 것 같습니다.   가령 조지 클루니와 니콜 키드먼 주연의 1997년 영화 The Peacemaker에서, 니콜 키드먼이 백악관 소속 핵무기 전문가로 나오는데, 백악관에서 일하기 전에는 로렌스 리버모어에서 핵무기 개발을 했던 것으로 설정되어 있습니다.


5.  그렇다면 오크 릿지의 Summit은 일반인들도 사용이 가능한가 ?

가능은 합니다.  이 링크 https://www.olcf.ornl.gov/for-users/getting-started/#applying-for-a-user-account 를 보면 여러 가지 형태의 user account 신청이 가능합니다.  다만 이 곳은 아마존이나 MS Azure 같은 클라우드 장사하는 곳이 아니므로 '돈을 낼테니 쓰게 해달라'는 식의 요청은 안 되는 모양이고 연구 과제 등에 대해 까다로운 심사를 받아야 하는 모양입니다. 

최근 top500.org에 나온 기사 https://www.top500.org/news/openpower-gathers-momentum-with-major-deployments/ 를 보면 다음과 같이 우버도 자사의 tensorflow 기반의 신경망을 이 Summit에서 training하고자 오크 릿지와 협업 중에 있다고 합니다.

"우버는 텐서플로우에 기반한 자사의 분산 training 프레임웍인 Horovod를 Summit에서 수행하기를 원하고 있습니다.  이 딥러닝 업무에는 여러가지 우버의 앱들, 가령 자율주행 네비게이션, 여정 예측, 사기 방지 등이 포함됩니다.  우버는 특히 GPU 사용과 관련되어 Horovod의 확장성을 한단계 더 넓히는데 관심이 있습니다."


6.  Summit이라는 수퍼컴이라는 것은 어떻게 생긴 컴퓨터인가 ?

겉에서 보면 일반 데이터 센터에 있는 서버 랙들의 모양새와 별로 다를 것이 없습니다.




7.  Summit 같은 수퍼컴에도 모니터와 키보드가 달려 있는가 ?

극단적으로 한줄 요약하면 없습니다.  Summit은 4,608대의 AC922이라는 IBM GPU 서버를 모아서 만든 것이므로, 이런 수천대의 서버에 일일이 모니터와 키보드 마우스를 연결하여 제어하는 것은 무리입니다.  이런 서버에는 BMC라고 하는 이더넷 포트(RJ-45)처럼 생긴 BMC(Baseboard Management Controller)용 포트가 있는데, 이를 통해 IPMI (Intelligent Platform Management Interface)라는 것을 통해 서버를 제어합니다.





8. Summit에 사용되는 CPU는 어떤 것인가 ?

과거에는 vector processor라는, 수학 계산에 특화된 아키텍처의 프로세서가 수퍼컴의 주류를 이루었습니다만, 지금은 대부분 사라졌습니다.  수퍼컴에도 보통의 회사에서 사용하는 웹서버에 장착된 일반적인 프로세서가 주로 사용됩니다.  Summit에는 IBM의 POWER9이 사용되었습니다.  이 POWER9 프로세서도 엄청난 고가의 특수 프로세서는 아닙니다.  인터넷 쇼핑몰의 웹서버보다 훨씬 더 중요한 업무라고 할 수 있는 은행이나 증권사의 계정계 서버에는 RISC 프로세서인 IBM POWER 프로세서가 사용되는 경우가 많으며, 그런 곳에서 사용되는 것과 똑같은 프로세서입니다.


9. Summit에서는 어떤 OS를 사용하는가 ?

프로세서와 마찬가지입니다.  요즘은 수퍼컴에서도 윈도우즈도 많이 사용합니다.  물론 대세는 리눅스입니다.  이번에 Summit에 올라가는 OS도 POWER 계열 프로세서의 아키텍처인 ppc64le용 Redhat 7.5 Linux가 올라가 있습니다.


10. 똑같은 CPU와 똑같은 OS를 쓴다면, 수퍼컴은 대체 무엇이 특수한가 ?

초기의 수퍼컴은 위에서 언급한 것처럼 수학 계산용 특수 CPU를 매우 빠른 속도로 돌리는 방식이었습니다.  지금도 수퍼컴하면 흔히 생각나는 Cray가 바로 그런 수퍼컴의 선구자였지요.  그러나 무작정 CPU clock speed를 높은 GHz로 돌리는 것에는 반도체 물성에 따른 한계가 있고 또 일반 프로세서의 성능이 좋아지면서 점차 일반 프로세서의 서버들 수십~수천 대를 고성능 네트워크로 엮는 cluster 방식이 주종을 이루게 되었습니다.  이러한 cluster 방식의 수퍼컴은 그 클러스터를 이루는 개개의 서버 성능도 중요하지만, 그것을 연결하는 네트워크의 성능 및 병렬 프로그래밍을 위한 SW 기술도 중요합니다.  또한 전력을 적게 사용해야 하고, 많은 data를 고속으로 처리하기 위한 병렬 파일시스템이 필요합니다.

Summit은 IBM의 AC922이라는 2-socket 서버 4,608대로 이루어져 있는데, 이 서버들은 2장의 POWER9 프로세서 뿐만 아니라, 가속기로 NVIDIA의 최신 Telsa GPU인 V100을 6장씩 장착했습니다.  그리고 발열 문제를 효율적으로 해결하기 위해 수냉식으로 되어 있습니다.






11.  Summit은 과거의 수퍼컴과 무엇이 다른가 ?

가장 큰 차이는 GPU 기술을 본격적으로 채택한 수퍼컴이라는 점입니다.  Summit이 대체하게 되는 오크 릿지의 기존 수퍼컴인 Titian과 비교를 해보면 그 차이는 명확합니다.  Summit은 Titian보다 노드(node) 수, 즉 구성 요소인 서버 대수는 1/4 수준이면서도 성능은 7.4배를 냅니다.  덕분에 그렇게 성능을 많이 내면서도 전력소비량도 기존의 1.4배에 불과합니다.


(이 표에는 노드 당 성능이 42 TFLOPS라고 나와 있습니다만, 이는 double-precision, 즉 FP64 성능을 기준으로 한 것입니다.  또한 원래 V100 SXM2의 FP64 성능은 NVIDIA에 따르면 7.8 TFLOPS이므로, 7.8 x 6장 = 46.8 TFLOPS가 맞을텐데, Oak Ridge의 홈페이지에는 42 TFLOPS라고 나옵니다.  오타일까요 ? )


12. 결국 Summit의 핵심은 GPU인 것 같다.   요즘 Deep Learning에 GPU 서버를 많이 사용하는데, 그런 GPU 서버와 이 Summit은 무엇이 다른가 ?

기본적으로는 동일합니다.  그러나 중요한 차이가 2가지 있습니다.  하나는 NVLink이고, 다른 하나는 PCIe Gen4 입니다.  둘다 I/O 쪽 기술이지요.

NVLink는 NVIDIA가 개발한 GPU 연결 기술로서, 일반 x86 서버에서도 사용됩니다.  그러나 IBM POWER9에서만 가능한 것이 따로 있습니다.  PCIe Gen3 포트만 장착된 Intel Xeon 프로세서에서는 NVLink를 GPU간의 연결에만 사용할 수 있고, Intel Xeon 프로세서와 GPU 간의 통신은 느린 PCIe를 사용해야 합니다.  그와 달리, IBM POWER9에는 NVLink 2.0 port가 실리콘에 박혀 있습니다.  이를 통해 POWER9 프로세서는 PCIe가 아닌, NVLink를 통해 V100 GPU와 직접 통신을 합니다.  GPU 간의 peer-to-peer 통신이 NVLink로 되어 있을 경우 Caffe 등을 이용한 deep learning에서는 어느 정도 효과를 볼 수 있지만, HPC 업무에는 오로지 CPU와 GPU 간의 통신이 중요합니다.

또 있습니다.  IBM POWER9은 2018년 여름 현재, PCIe Gen4 포트가 장착된 유일한 프로세서입니다.  이를 통해 AC922은 고속 네트워크인 100Gb EDR Infiniband를 일반 x86 서버보다 2배의 대역폭으로 연결할 수 있습니다.  이 infiniband를 통해 Summit은 고속 병렬파일시스템을 연결하고, 또 Summit을 이루는 4,608대의 AC922 서버 간의 MPI (Message Passing Interface) 통신을 고속으로 수행합니다.

이러한 이유 때문에 IBM와 NVIDIA, 그리고 인피니밴드 업체인 Mellanox의 OpenPOWER 컨소시엄이  Summit과 Sierra라고 하는 2대의 수퍼컴을 개발 구매하는 CORAL project의 공급자로 채택된 것입니다.




2018년 5월 31일 목요일

Tensorflow 1.8을 source에서 build하기 (CUDA 9.2, ppc64le, POWER9)

최근 IBM이 tensorflow 1.8을 ppc64le에서도 사용할 수 있다고 발표했습니다.  그 prerequisite은 CUDA 9.2가 설치되어 있는 환경이어야 한다는 점입니다.  아래 site에서 wheel file을 받아서 아래처럼 설치하면 간단히 쓸 수 있습니다.

[ibm@centos01 files]$ wget ftp://ftp.unicamp.br/pub/ppc64el/ai_frameworks/tensorflow/tensorflow-1.8.0-cp27-none-linux_ppc64le.whl

[ibm@centos01 files]$ which python
~/anaconda2/bin/python

[ibm@centos01 files]$ pip install tensorflow-1.8.0-cp27-none-linux_ppc64le.whl


그러나 위 site에는 python2.7을 위한 wheel file만 있습니다.  python3.6을 위한 tensorflow가 필요하시다면 직접 source에서 build하셔야 합니다.   현재로서는 이걸 build하실 때 아래와 같이 약간 source 수정이 필요합니다.

먼저, tensorflow 1.8.0에서는 기존 버전과 눈에 띄게 달라진 점이 있습니다.  NCCL ('니클'이라고 읽습니다) library를 사용한다는 점입니다.  따라서 NCCL을 먼저 설치해야 하는데, 다행히 쉽습니다.

[ibm@centos01 ~]$ git clone https://github.com/NVIDIA/nccl
[ibm@centos01 ~]$ cd nccl
[ibm@centos01 nccl]$ make
[ibm@centos01 nccl]$ sudo make install

python 버전이 3.x 인 것을 확인하십시요.

[ibm@centos01 ~]$ which python
~/anaconda3/bin/python

[ibm@centos01 ~]$ git clone https://github.com/tensorflow/tensorflow

[ibm@centos01 ~]$ cd tensorflow

[ibm@centos01 tensorflow]$  git checkout tags/v1.8.0

예전 버전과 마찬가지로,  -march=native가 default로 들어가 있으면 error가 나므로 해당 부분을 다 -mcpu=power8으로 수정하십시요.

[ibm@centos01 tensorflow]$ vi ./configure.py
...
    default_cc_opt_flags = '-mcpu=power8'
...
    default_cc_opt_flags = '-mcpu=power8'
...
   write_to_bazelrc('build:opt --host_copt=-mcpu=power8')
...

그리고 configure를 수행합니다.  아래 표시된 질문 외에는 다 default 값을 택하시면 됩니다.

[ibm@centos01 tensorflow]$ ./configure
...
Do you wish to build TensorFlow with Google Cloud Platform support? [Y/n]: n
...
Do you wish to build TensorFlow with Amazon S3 File System support? [Y/n]: n
...
Do you wish to build TensorFlow with Apache Kafka Platform support? [Y/n]: n
...
Do you wish to build TensorFlow with CUDA support? [y/N]: y
...
Please specify the CUDA SDK version you want to use, e.g. 7.0. [Leave empty to default to CUDA 9.0]: 9.2
...
Please specify the cuDNN version you want to use. [Leave empty to default to cuDNN 7.0]: 7

Please specify the location where cuDNN 7 library is installed. Refer to README.md for more details. [Default is /usr/local/cuda]:/usr/local/cuda-9.2
...
Please note that each additional compute capability significantly increases your build time and binary size. [Default is: 3.5,5.2]6.0,7.0
...

그리고나서 아래 issue #19291에 제시된 대로 third_party/png.BUILD 파일을 수정해주십시요.

https://github.com/tensorflow/tensorflow/pull/19291/commits/8f8a3c5151a674b3496691af49c3aa063841f292

[ibm@centos01 tensorflow]$ vi third_party/png.BUILD     #31번째 줄 대신 아래를 삽입

#    ],
    ] + select({
        "@org_tensorflow//tensorflow:linux_ppc64le": [
            "powerpc/powerpc_init.c",
            "powerpc/filter_vsx_intrinsics.c",
        ],
        "//conditions:default": [
        ],
    }),


//* 이 수정을 해주지 않으면 아래와 같은 error를 만나시게 됩니다.

ERROR: /home/ibm/.cache/bazel/_bazel_ibm/4869dbc4f6d1a096d34c86242ee59bba/external/boringssl/BUILD:115:1: C++ compilation of rule '@boringssl//:crypto' failed (Exit 1)
external/boringssl/src/crypto/pkcs8/pkcs8.c: In function 'ascii_to_ucs2':
external/boringssl/src/crypto/pkcs8/pkcs8.c:86:3: error: 'for' loop initial declarations are only allowed in C99 mode
   for (size_t i = 0; i < ulen - 2; i += 2) {
   ^
*//



이제 예전과 동일하세 bazel build 하시면 됩니다.

[ibm@centos01 tensorflow]$ bazel build --config=opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
...
Target //tensorflow/tools/pip_package:build_pip_package up-to-date:
  bazel-bin/tensorflow/tools/pip_package/build_pip_package
INFO: Elapsed time: 8178.924s, Critical Path: 252.09s
INFO: Build completed successfully, 11585 total actions

예전에 비해 build 시간이 굉장히 길어진 것을 느끼실 겁니다.  이제 whl file을 만듭니다.

[ibm@centos01 tensorflow]$ bazel-bin/tensorflow/tools/pip_package/build_pip_package ~/files/tensorflow_pkg

만들어진 whl file을 보면 확실히 기존 TF1.5.1보다 size도 2배 가량 커졌습니다.

[ibm@centos01 tensorflow]$ ls -l ~/files/tensorflow_pkg
total 162328
-rw-rw-r--. 1 ibm ibm  55160703 May  9 15:17 tensorflow-1.5.1-cp36-cp36m-linux_ppc64le.whl
-rw-rw-r--. 1 ibm ibm 111062624 May 31 16:07 tensorflow-1.8.0-cp36-cp36m-linux_ppc64le.whl

이 whl file을 설치하시면 됩니다.

[ibm@centos01 tensorflow]$ pip install ~/files/tensorflow_pkg/tensorflow-1.8.0-cp36-cp36m-linux_ppc64le.whl
...
      Successfully uninstalled numpy-1.13.1
Successfully installed absl-py-0.2.2 astor-0.6.2 gast-0.2.0 grpcio-1.12.0 markdown-2.6.11 numpy-1.14.3 tensorboard-1.8.0 tensorflow-1.8.0 termcolor-1.1.0

[ibm@centos01 tensorflow]$ pip list | grep tensor
tensorboard                        1.8.0
tensorflow                         1.8.0

이 TF1.8.0으로 Neural Machine Translation의 training과 inference를 수행해보면, 동일한 HW에서 기존 TF1.5.1의 수행 결과보다 더 빨라진 것 같지는 않습니다.

여기서 build한 tensorflow 1.8.0의 wheel file을 아래 google drive에 올려놓겠습니다.  이것을 사용하시려면 CUDA 9.2가 설치되어 있어야 한다는 점을 유의하시기 바랍니다.

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

2018년 5월 16일 수요일

Ubuntu ppc64le 환경에서 nvidia-docker를 source로부터 build하기

최근에 nvidia-docker를 source에서 build 해보니 기존에 있던 ppc64le branch가 없어져서 그냥 하면 error가 납니다.   물론 nvidia-docker는 다음과 같이 apt repository에서 편리하게 설치가 가능합니다.

$ sudo vi /etc/apt/sources.list.d/nvidia-docker.list
deb https://nvidia.github.io/libnvidia-container/ubuntu16.04/$(ARCH) /
deb https://nvidia.github.io/nvidia-container-runtime/ubuntu16.04/$(ARCH) /
deb https://nvidia.github.io/nvidia-docker/ubuntu16.04/$(ARCH) /

$ sudo vi /etc/apt/sources.list.d/docker.list
deb [arch=ppc64el] https://download.docker.com/linux/ubuntu xenial stable


그래도 필요에 의해서 nvidia-docker를 source로부터 build해야 할 경우가 있습니다.   이 경우에도 근성만 있으면 아래와 같이 build가 가능합니다.

minsky_test@minsky:~/files$ git clone https://github.com/NVIDIA/nvidia-docker.git

minsky_test@minsky:~/files$ cd nvidia-docker

minsky_test@minsky:~/files/nvidia-docker$ git fetch --all

minsky_test@minsky:~/files/nvidia-docker$ git checkout tags/v1.0.1

여기서 그냥 make를 하시면 결국 다음과 같은 "exec format error"가 납니다.

minsky_test@minsky:~/files/nvidia-docker$ sudo make
...
http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64 /" > /etc/apt/sources.list.d/cuda.list
 ---> Running in 9bc30333d07a
standard_init_linux.go:178: exec user process caused "exec format error"
...
make: *** [tools] Error 2

이건 기본적으로 이 build를 위해 pull 해오는 golang container image가 ppc64le가 아닌 AMD64 아키텍처의 것이기 때문입니다.

minsky_test@minsky:~/files/nvidia-docker$ sudo docker inspect golang:1.5 | grep Arch
        "Architecture": "amd64",

이 문제와 기타 다른 문제들을 해결하기 위해 아래와 같이 Makefile과 Dockerfile.build을 일부 수정해주면 됩니다.

minsky_test@minsky:~/files/nvidia-docker$ vi Makefile
...
#ifneq ($(MAKECMDGOALS),rpm)
#PKG_ARCH := amd64
#else
#PKG_ARCH := x86_64
#endif
PKG_ARCH := ppc64le
...


minsky_test@minsky:~/files/nvidia-docker$ vi Dockerfile.build
#FROM golang:1.5
FROM ppc64le/golang:1.9
...
#    apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/7fa2af80.pub && \
    apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/ppc64el/7fa2af80.pub && \
...
#    echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64 /" > /etc/apt/sources.list.d/cuda.list
    echo "deb http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/ppc64el /" > /etc/apt/sources.list.d/cuda.list
...
#        cuda-cudart-dev-6-5=6.5-14 \
        cuda-cudart-dev-8-0=8.0.61-1 \
#        cuda-misc-headers-6-5=6.5-19 && \
        cuda-misc-headers-8-0=8.0.61-1 && \
...
#RUN objcopy --redefine-sym memcpy=memcpy@GLIBC_2.2.5 /usr/local/cuda-6.5/lib64/libcudart_static.a   #으로 comment-out합니다
...
#ENV CGO_CFLAGS "-I /usr/local/cuda-6.5/include -I /usr/include/nvidia/gdk"
ENV CGO_CFLAGS "-I /usr/local/cuda-8.0/include -I /usr/include/nvidia/gdk"
#ENV CGO_LDFLAGS "-L /usr/local/cuda-6.5/lib64"
ENV CGO_LDFLAGS "-L /usr/local/cuda-8.0/lib64"

이제 build를 하면 됩니다.  make tarball을 수행하면 nvidia-docker와 nvidia-docker-plugin binary를 tar.xz로 묶어 줍니다.  이걸 /usr/local 등 적절한 위치에 풀어주기만 하면 됩니다.

minsky_test@minsky:~/files/nvidia-docker$ sudo make tarball
...
Find tarball at /home/minsky_test/files/nvidia-docker/dist

minsky_test@minsky:~/files/nvidia-docker$ tar -tvf /home/minsky_test/files/nvidia-docker/dist/nvidia-docker_1.0.1_ppc64le.tar.xz
-rwxr-xr-x root/miruware 5247984 2018-05-16 16:57 nvidia-docker/nvidia-docker
-rwxr-xr-x root/miruware 6489232 2018-05-16 16:57 nvidia-docker/nvidia-docker-plugin

물론 이렇게 source에서 build한 nvidia-docker는 service로 등록하기 전엔 아래처럼 손으로 start 해주고 kill로 죽여야 합니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ sudo ./nvidia-docker-plugin &

minsky_test@minsky:~/files/nvidia-docker/bin$ sudo ./nvidia-docker run -ti bsyu/tf1.3-ppc64le:v0.1 bash

root@78d0b67e2c8d:/# nvidia-smi
Wed May 16 08:05:31 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.111                Driver Version: 384.111                   |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000002:01:00.0 Off |                    0 |
| N/A   35C    P0    31W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  Off  | 00000003:01:00.0 Off |                    0 |
| N/A   35C    P0    30W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  Off  | 0000000A:01:00.0 Off |                    0 |
| N/A   35C    P0    32W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  Off  | 0000000B:01:00.0 Off |                    0 |
| N/A   30C    P0    31W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

아래에 이렇게 만들어진 nvidia-docker tarball을 google drive에 올려놓았습니다.

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

nvidia-driver 올린 뒤 container 속에서의 "Driver/library version mismatch" error

다음과 같이 nvidia-driver가 384.111인 환경에서 docker image bsyu/tf1.3-ppc64le:v0.1를 구동했습니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ sudo ./nvidia-docker run -ti bsyu/tf1.3-ppc64le:v0.1 bash

그 속에 들어가서 nvidia-smi 명령으로 nvidia-driver가 384.111인 것을 확인합니다.

root@78d0b67e2c8d:/# nvidia-smi
Wed May 16 08:05:31 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 384.111                Driver Version: 384.111                   |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000002:01:00.0 Off |                    0 |
| N/A   35C    P0    31W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  Off  | 00000003:01:00.0 Off |                    0 |
| N/A   35C    P0    30W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  Off  | 0000000A:01:00.0 Off |                    0 |
| N/A   35C    P0    32W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  Off  | 0000000B:01:00.0 Off |                    0 |
| N/A   30C    P0    31W / 300W |     10MiB / 16276MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

이 docker container에 변화를 주기 위해 다음과 같이 tensorflow models를 clone 해서 넣습니다.

root@78d0b67e2c8d:/# git clone https://github.com/tensorflow/models.git

root@78d0b67e2c8d:/# cd /models/tutorials/image/cifar10

여기서 cifar10 training을 잠깐 시켜봐도 좋습니다.   도중에 중단시키고 빠져 나갑니다.

root@78d0b67e2c8d:/models/tutorials/image/cifar10# python cifar10_train.py
...
2018-05-16 08:15:25.329494: step 1520, loss = 1.97 (9342.9 examples/sec; 0.014 sec/batch)
2018-05-16 08:15:25.454485: step 1530, loss = 1.86 (10240.0 examples/sec; 0.013 sec/batch)
2018-05-16 08:15:25.580138: step 1540, loss = 2.06 (10186.0 examples/sec; 0.013 sec/batch)
2018-05-16 08:15:25.711379: step 1550, loss = 1.73 (9754.1 examples/sec; 0.013 sec/batch)
^Z
[1]+  Stopped                 python cifar10_train.py
root@78d0b67e2c8d:/models/tutorials/image/cifar10# exit


이제 parent OS로 나왔습니다.  docker ps 명령으로 다음과 같이 78d0b67e2c8d container가 남아 있는 것을 보실 수 있습니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                           PORTS               NAMES
78d0b67e2c8d        bsyu/tf1.3-ppc64le:v0.1   "bash"                   11 minutes ago      Exited (148) 43 seconds ago                          vigilant_jennings
af8e4f0af9d2        9d72ea809195              "/bin/sh -c 'go ge..."   42 minutes ago      Exited (2) 42 minutes ago                            practical_brown
021b52c86fdf        588a60a80ab7              "/bin/sh -c 'go ge..."   About an hour ago   Exited (2) About an hour ago                         nifty_beaver
716660e1b44b        bf2674b6db4a              "/bin/sh -c 'go ge..."   About an hour ago   Exited (1) About an hour ago                         blissful_pasteur
7e0b933581c5        3349633cccc3              "/bin/sh -c 'apt-g..."   About an hour ago   Exited (100) About an hour ago                       unruffled_haibt
53853b98c3f0        958e9eb53afd              "/bin/sh -c 'NVIDI..."   About an hour ago   Exited (2) About an hour ago                         goofy_williams
85afec3a1429        52a84e97014b              "/bin/bash -c 'mak..."   3 weeks ago         Exited (2) 3 weeks ago                               vigilant_curie
5e172a9eb6c0        3426d0bdc1ee              "/bin/sh -c 'cd /p..."   3 weeks ago         Exited (2) 3 weeks ago                               thirsty_wescoff
27725169f8c2        c9cf4b61ab78              "/bin/sh -c 'pip i..."   3 weeks ago         Exited (127) 3 weeks ago 

이제 nvidia driver를 390으로 올립니다.

minsky_test@minsky:~$ sudo apt-get install nvidia-390-dev nvidia-390

당장 nvidia-smi를 해보면 error가 납니다.  원래는 reboot을 해야 하는데, 그러지 않았기 때문인가 봅니다.

minsky_test@minsky:~$ nvidia-smi
Failed to initialize NVML: Driver/library version mismatch

이걸 rebooting하지 않고 하기 위해서는 nvidia-docker-plugin을 죽인 뒤, 현재 load된 nvidia 관련 module들을 rmmod로 제거한 뒤 다시 nvidia-docker-plugin을 살리면 됩니다.

minsky_test@minsky:~$ ps -ef | grep 86949 | grep -v grep
root      86949  86948  0 17:03 pts/7    00:00:03 ./nvidia-docker-plugin

minsky_test@minsky:~$ sudo kill -9 86949

minsky_test@minsky:~$ sudo lsmod | grep nvidia
nvidia_drm             59673  0
nvidia_modeset       1173401  1 nvidia_drm
nvidia_uvm            869865  4
nvidia              16625272  779 nvidia_modeset,nvidia_uvm
drm_kms_helper        182400  2 ast,nvidia_drm
drm                   453521  5 ast,ttm,drm_kms_helper,nvidia_drm

minsky_test@minsky:~$ sudo rmmod nvidia_drm

minsky_test@minsky:~$ sudo rmmod nvidia_uvm

minsky_test@minsky:~$ sudo rmmod nvidia_modeset

minsky_test@minsky:~$ sudo rmmod nvidia

nvidia 관련 모듈이 다 없어진 것을 아래와 같이 확인합니다.

minsky_test@minsky:~$ sudo lsmod | grep nvidia
minsky_test@minsky:~$

이제 다시 nvidia-docker-plugin을 살립니다.  그러면 nvidia 관련 module들이 다시 load 됩니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ sudo ./nvidia-docker-plugin &

이제 nvidia-smi로 보면 driver 버전이 390.31로 올라온 것을 볼 수 있습니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ nvidia-smi
Wed May 16 17:32:17 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.31                 Driver Version: 390.31                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000002:01:00.0 Off |                    0 |
| N/A   37C    P0    31W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  Off  | 00000003:01:00.0 Off |                    0 |
| N/A   36C    P0    30W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  Off  | 0000000A:01:00.0 Off |                    0 |
| N/A   36C    P0    32W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  Off  | 0000000B:01:00.0 Off |                    0 |
| N/A   31C    P0    31W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

이제 아까 exit했던 bsyu/tf1.3-ppc64le:v0.1의 container인 78d0b67e2c8d에 다시 attach 해보겠습니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ sudo ./nvidia-docker start 78d0b67e2c8d
78d0b67e2c8d

minsky_test@minsky:~/files/nvidia-docker/bin$ sudo ./nvidia-docker attach 78d0b67e2c8d
root@78d0b67e2c8d:/#

이 속에서 nvidia-smi 해봐도 다음과 같은 error만 납니다.

root@78d0b67e2c8d:/# nvidia-smi
Failed to initialize NVML: Driver/library version mismatch

이렇게 예전 버전의 384 driver를 가지고 구동된 container는 다시 제대로 작동시킬 방법이 없습니다.  새로 다시 시작해야 하는데, 그러자면 기존에 변경시켜둔 file 내용들이 날라갑니다.  그렇게 변경시켜둔 file들을 보존하려면 docker commit을 하시면 됩니다.  가령 아까 위에서 clone 받아둔 /models의 내용이 그대로 보존될 수 있습니다.

먼저 parent OS에서 다음과 같이 새로운 이름의 image로 해당 container id를 commit 합니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ ./nvidia-docker commit 78d0b67e2c8d bsyu/tf1.3-ppc64le:v0.2
sha256:4e5cf1b9f9672a41d2a71737f32a0d0f2a042d9162ab351433d16a828946d4f4

이제 새로 만들어진 bsyu/tf1.3-ppc64le:v0.2 image를 새로 start 합니다.

minsky_test@minsky:~/files/nvidia-docker/bin$ ./nvidia-docker run -ti bsyu/tf1.3-ppc64le:v0.2 bash

이제 nvidia-smi를 해보시면 새로운 driver version으로 잘 올라오는 것을 보실 수 있습니다.

root@53f8f0993f34:/# nvidia-smi
Wed May 16 08:39:33 2018
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 390.31                 Driver Version: 390.31                    |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla P100-SXM2...  Off  | 00000002:01:00.0 Off |                    0 |
| N/A   34C    P0    30W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla P100-SXM2...  Off  | 00000003:01:00.0 Off |                    0 |
| N/A   34C    P0    30W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla P100-SXM2...  Off  | 0000000A:01:00.0 Off |                    0 |
| N/A   33C    P0    31W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla P100-SXM2...  Off  | 0000000B:01:00.0 Off |                    0 |
| N/A   29C    P0    31W / 300W |     10MiB / 16280MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

물론 /models directory도 그대로 잘 보존되어 있습니다.

root@53f8f0993f34:/# cd /models/tutorials/image/cifar10
root@53f8f0993f34:/models/tutorials/image/cifar10# ls
BUILD      __init__.py  cifar10.py       cifar10_input.py       cifar10_multi_gpu_train.py
README.md  __pycache__  cifar10_eval.py  cifar10_input_test.py  cifar10_train.py