2019년 5월 22일 수요일

ppc64le 환경에서 IBM Cloud private (ICP) 설치하기


GPU 자원에 대해 private cloud를 구축하는 고객분들이 점점 늘어나고 있습니다.  NVIDIA가 이제 virtual GPU를 CUDA에서도 지원하기는 합니다만, 주로 deep learning에 사용되는 GPU를 그렇게 virtual GPU로 나눠쓰는 것은 실질적인 이익이 별로 없습니다.  어차피 GPU 메모리가 부족한 상황이니까요.  그래서 GPU cloud를 구축할 때 사용되는 기술은 가상화보다는 docker orchestration이 대세를 이루고 있습니다.

IBM은 docker orchestration에 대해 IBM Cloud private (ICp)라는 솔루션을 제공합니다.  이는 Kubernetes 기반으로 만들어진 private cloud 솔루션이라고 할 수 있습니다.  Redhat의 OpenShift와 비슷한 솔루션이라고 보시면 됩니다.  설치도 매우 간단하며, 당연히 IBM POWER9, 즉 ppc64le 아키텍처 버전도 있습니다. 

이번 posting에서는 IBM의 POWER9 CPU와 NVIDIA V100 GPU를 장착한 AC922 서버에 ICp를 설치해보도록 하겠습니다. 
먼저 docker와 nvidia-docker를 설치해야 하는 것은 당연하고요, 그 외에 다음과 같이 사전 작업을 몇가지 해줘야 합니다.  아래 내용은 이 link에 나온 manual을 따라 한 것입니다.  참조하십시요.

https://www.ibm.com/support/knowledgecenter/en/SSBS6K_2.1.0/installing/install_containers.html

먼저 /etc/hosts에 IP를 등록하거나 DNS에 등록된 IP를 준비합니다.  원래 최소 조건이 master node, proxy node, worker node1, worker node2가 필요합니다.  Boot node는 master node와 같은 node에 있어도 괜찮습니다.  그러나 여기서는 GPU 서버인 AC922이 딱 1대 있기 때문에, 어쩔 수 없이 1대가 master node, worker node, proxy node 역할을 모두 하도록 했습니다.   그래서 /etc/hosts에 다음과 같이 IP address 하나에 4개의 이름을 주었습니다.

root@uniac922:~# cat /etc/hosts
127.0.0.1       localhost
192.168.0.20    uniac922 proxy master node1 node2

그리고 vm.max_map_count를 256K로 늘려줍니다.  이는 프로세스가 사용할 수 있는 메모리 맵 영역의 최대 수를 뜻합니다.

root@uniac922:~# sudo sysctl -w vm.max_map_count=262144
vm.max_map_count = 262144

위의 튜닝 효과가 reboot 이후에도 유효하게 하기 위해서는 아래와 같이 /etc/sysctl.conf에도 등록을 해줘야 합니다.

root@uniac922:~#  sudo vi /etc/sysctl.conf
vm.max_map_count=262144

그리고 각 node들끼리 passwd 입력 없이 ssh가 되어야 합니다.  제 경우처럼 localhost 자체로 ssh하는 경우도 마찬가지입니다.  이는 아래와 같이 해주면 됩니다.

root@uniac922:~# ssh-keygen -t rsa

root@uniac922:~# vi /etc/ssh/sshd_config
#PermitRootLogin prohibit-password
PermitRootLogin yes

root@uniac922:~# ssh-copy-id master
root@uniac922:~# ssh-copy-id proxy
root@uniac922:~# ssh-copy-id node1

미리 download 받아둔 ICp 설치 파일을 다음과 같이 docker에 load 합니다.

root@uniac922:~# ls -l *.tar.gz
-rw-rw-r-- 1 root root 6163151506 May 14 23:46 ibm-cloud-private-ppc64le-2.1.0.1.tar.gz

root@uniac922:~# tar xf ibm-cloud-private-ppc64le-2.1.0.1.tar.gz -O | docker load
...
2d67d9d7b31b: Loading layer [==================================================>]   2.56kB/2.56kB
f64ed19c4c4c: Loading layer [==================================================>]  3.072kB/3.072kB
Loaded image: ibmcom/metering-reader-ppc64le:2.1.0.1
72e8e5a1b8a4: Loading layer [==================================================>]  5.229MB/5.229MB
45f2ce399ddb: Loading layer [==================================================>]   2.56kB/2.56kB
187003a06729: Loading layer [==================================================>]  3.584kB/3.584kB
8ab0cc971235: Loading layer [==================================================>]     98MB/98MB
Loaded image: ibmcom/icp-identity-manager-ppc64le:2.1.0.1

이를 성공적으로 하고 나면 다음과 같이 수십개의 docker image들이 load된 것을 보실 수 있습니다.

root@uniac922:~# sudo docker images | grep ibmcom
ibmcom/icp-inception-ppc64le                              2.1.0.1-ee                         526770d6fda6        17 months ago       332MB
ibmcom/icp-catalog-ui-ppc64le                             2.1.0.1                            eb2a8475a640        17 months ago       725MB
ibmcom/metering-reader-ppc64le                            2.1.0.1                            f73cd423f4c6        17 months ago       177MB
ibmcom/kubernetes-ppc64le                                 v1.8.3-ee                          96d8c62383ff        17 months ago       521MB
...
ibmcom/mariadb-ppc64le                                    10.1.16                            e1d96397e3e8        2 years ago         451MB
ibmcom/pause-ppc64le                                      3.0                                0e777c06d387        3 years ago         739kB

위의 이미지들은 기본 docker image 저장 장소인 /var/lib/docker에 대략 25GB 정도의 space를 차지합니다.  혹시 / 또는 /var 파일시스템에 그런 여유 공간이 없다면 시작 전에 아래와 같이 docker의 root directory를 여유가 많은 filesystem으로 바꿔두셔야 합니다.

[root@ac922 ~]# vi /lib/systemd/system/docker.service
...
#ExecStart=/usr/bin/dockerd
ExecStart=/usr/bin/dockerd -g /data/docker

이어서 ICp configuration 파일들이 저장될 installation directory을 만듭니다.  여기서는 /opt/ibm-cloud-private-2.1.0.1 로 하겠습니다.

root@uniac922:~# mkdir /opt/ibm-cloud-private-2.1.0.1

root@uniac922:~# cd /opt/ibm-cloud-private-2.1.0.1

여기서 ibmcom/icp-inception-ppc64le:2.1.0.1-ee 이미지 속에서 cluster라는 directory 전체를 이 directory로 다음과 같이 copy합니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# sudo docker run -v $(pwd):/data -e LICENSE=accept ibmcom/icp-inception-ppc64le:2.1.0.1-ee cp -r cluster /data

내용을 보면 다음과 같은 configuration file들이 보입니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# ls -l ./cluster
total 20
-rw-r--r-- 1 root root 4799 May 15 14:17 config.yaml
-rw-r--r-- 1 root root   88 May 15 14:17 hosts
drwxr-xr-x 3 root root 4096 May 15 14:17 misc
-r-------- 1 root root    1 May 15 14:17 ssh_key

이 중에서 먼저 hosts에 아래와 같이 IP address를 지정해주고 설정을 해줍니다.   여기서는 모든 서버들이 다 같은 IP를 가지는 비정상적 상태라는 거 잊지 마십시요.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# vi cluster/hosts
[master]
192.168.0.20   kubelet_extra_args='["--eviction-hard=memory.available<100Mi,nodefs.available<2Gi,nodefs.inodesFree<5%", "--image-gc-high-threshold=100%", "--image-gc-low-threshold=100%"]'

[worker]
192.168.0.20
192.168.0.20

[proxy]
192.168.0.20   kubelet_extra_args='["--eviction-hard=memory.available<100Mi,nodefs.available<2Gi,nodefs.inodesFree<5%", "--image-gc-high-threshold=100%", "--image-gc-low-threshold=100%"]'

#[management]
#4.4.4.4

그리고 다음과 같이 ssh_key를 copy 해줍니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# cp ~/.ssh/id_rsa ./cluster/ssh_key

cluster/images라는 directory를 만들고, 아까 받아둔 ICp 설치 file을 거기로 copy해둡니다.

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# mkdir -p cluster/images

root@uniac922:/opt/ibm-cloud-private-2.1.0.1# cp /home/ibm/files/ICp/ibm-cloud-private-ppc64le-2.1.0.1.tar.gz cluster/images/

그리고 cluster/config.yaml 파일을 다음과 같이 일부 수정하여 /etc/hosts를 써도 error가 나지 않도록 해줍니다.

ibm@uniac922:/opt/ibm-cloud-private-2.1.0.1$ cd cluster

ibm@uniac922:/opt/ibm-cloud-private-2.1.0.1/cluster$ sudo vi config.yaml
# loopback_dns: false
loopback_dns: true

# 위의 수정을 해주지 않고 /etc/hosts에 의존할 경우 아래와 같은 error가 납니다.
TASK [check : Validating DNS server] ************************************************************************************************************
fatal: [192.168.0.20]: FAILED! => {"changed": false, "failed": true, "msg": "A loopback IP is used in your DNS server configuration. For more details, see https://ibm.biz/dns-fails."}


그리고 ICp version 3.x 부터는 아래처럼 config.yaml에서 ansible user의 password를 32글자 이상으로 설정해야 합니다. 

[root@c633-met1 cluster]# vi config.yaml
...
## Advanced Settings
default_admin_user: admin
# default_admin_password:
default_admin_password: ibm08ibm08ibm08ibm08ibm08ibm08ibm
# ansible_user: <username>


안 그럴 경우 다음과 같은 이상한 error가 납니다.

fatal: [localhost]: FAILED! => changed=false msg: 'The password is not set. You must specify a password that meets the following criteria :  ''^([a-zA-Z0-9\-]{32,})$''


이제 다음과 같이 ibmcom/icp-inception-ppc64le:2.1.0.1-ee image를 run 시켜 install 명령을 수행합니다.

ibm@uniac922:/opt/ibm-cloud-private-2.1.0.1/cluster$ sudo docker run --net=host -t -e LICENSE=accept -v $(pwd):/installer/cluster/  ibmcom/icp-inception-ppc64le:2.1.0.1-ee install

# 혹시 이 과정 중에서 도중에 실패가 일어난다든가 할 경우, 그대로 다시 install 하지 말고 install을 uninstall로 바꿔서 깨끗히 환경을 정리한 뒤 다시 해야 합니다.  그러지 않을 경우 다음과 같은 error를 만날 수 있습니다.
fatal: [192.168.0.20]: FAILED! => {"changed": false, "failed": true, "msg": "The environment was not clean, please first uninstall the ICP and then reinstall."}


다음과 같은 메시지가 나오면 성공적으로 종료된 것입니다.  시간이 생각보다 오래 걸립니다.

...
PLAY RECAP *********************************************************************
192.168.0.20               : ok=176  changed=54   unreachable=0    failed=0
localhost                  : ok=229  changed=113  unreachable=0    failed=0
POST DEPLOY MESSAGE ************************************************************
The Dashboard URL: https://192.168.0.20:8443, default username/password is admin/admin
Playbook run took 0 days, 1 hours, 30 minutes, 3619 seconds

그리고 혹시 이렇게 설치된 ICp를 재기동하고 싶으면 docker daemon을 다음과 같이 restart 하면 됩니다.
# sudo systemctl docker restart


이후는 https://192.168.0.20:8443 로 들어가서 web browser를 접속하여 둘러보면 됩니다.   이때 default userid/passwd는 admin/admin 입니다.



처음 나오는 메뉴는 dashboard 입니다.  여기서 CPU나 메모리는 물론, deploy된 pod들과 GPU의 상태도 모니터링 가능합니다.





Namespace 관련 메뉴는 화면 왼쪽 Navigation 중 Manage 메뉴에 있습니다.   여기서 새로운 namespace를 생성할 수도 있습니다.





ICp는 local server에 자체적인 local docker image repository를 가지고 있습니다.  여기에 image를 저장하기 위해서는 먼저 다음과 같이 local repository에 login을 해야 합니다.  여기에 사용되는 userid/passwd는 물론 admin/admin 입니다.

ibm@uniac922:~$ sudo docker login mycluster.icp:8500
Username: admin
Password:
Login Succeeded

이제 현재 load된 image 중에서 하나를 다른 이름으로 tagging한 뒤 local repository에 그 새 이름으로 tagging된 image를 push 해보겠습니다.  실은 이름을 mycluster.icp:8500/"namespace"/"image이름"의 형태로 tagging해야 push가 가능합니다.  따라서 다음과 같은 이름으로 tagging하겠습니다.

ibm@uniac922:~$ sudo docker tag ibmcom/kubernetes-ppc64le:v1.8.3-ee mycluster.icp:8500/admin/kubernetes-ppc64le:v1.8.3-ee

다음과 같이 새 이름으로 tag된 image를 확인할 수 있습니다.  이어서 push 하면 됩니다.

ibm@uniac922:~$ sudo docker images | grep kubernetes-ppc64le
ibmcom/kubernetes-ppc64le                                 v1.8.3-ee                          96d8c62383ff        17 months ago       521MB
mycluster.icp:8500/kube-system/kubernetes-ppc64le         v1.8.3-ee                          96d8c62383ff        17 months ago       521MB

ibm@uniac922:~$ sudo docker push mycluster.icp:8500/kube-system/kubernetes-ppc64le:v1.8.3-ee


이렇게 push된 image는 화면 왼쪽 Navigation 중 Catalog --> Images에서 확인하실 수 있습니다.




기타 화면들의 screenshot을 올려둡니다.  보시면 job을 생성하면서 거기에 GPU를 1개 이상 할당하는 메뉴도 있습니다.
























2019년 5월 16일 목요일

Ubuntu 18.04 ppc64le 환경에 nvidia-docker2 설치하는 방법


여기서는 CUDA 9.2를 설치한다고 가정합니다.  혹시 CUDA 10.1 등을 설치하는 경우는 그에 맞게 CUDA 버전을 바꾸십시요.

CUDA repository를 download 받아서 설치합니다.   참고로 local repo file을 받아서 설치하면 이런저런 error가 나니, network repo file을 받는 것이 좋습니다.

u0017649@sys-97899:~$ wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1604/ppc64el/cuda-repo-ubuntu1604_9.2.148-1_ppc64el.deb

u0017649@sys-97899:~$ sudo dpkg -i cuda-repo-ubuntu1604_9.2.148-1_ppc64el.deb

u0017649@sys-97899:~$ sudo apt-get install `apt-cache pkgnames | grep cuda | grep 9-2`

apt-key 값을 받습니다.  이때 URL 중에 ubuntu1804가 아니라 ubuntu1604가 있지만 상관없습니다.

u0017649@sys-97899:~$ sudo apt-key adv --fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/ppc64el/7fa2af80.pub

u0017649@sys-97899:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7EA0A9C3F273FCD8

Docker repository를 add 합니다.

u0017649@sys-97899:~$ sudo add-apt-repository "deb [arch=ppc64el] https://download.docker.com/linux/ubuntu `lsb_release -cs` stable"

u0017649@sys-97899:~$ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 7EA0A9C3F273FCD8

이제 docker-ce를 설치합니다.  원래 그냥 설치하면 더 최신인 docker-ce 18.06.3이 설치될텐데, 그건 nvidia-docker2에서 아직 지원하지 않으므로 여기서는 docker-ce=18.06.1로 버전을 지정해서 설치해야 합니다.

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

u0017649@sys-97899:~$ sudo apt-get install docker-ce=18.06.1~ce~3-0~ubuntu containerd.io

이어서 nvidia-docker2 설치를 위한 key값을 받고 apt-repository를 등록합니다.

u0017649@sys-97899:~$ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -

u0017649@sys-97899:~$ curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu18.04/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list

apt repository를 update하고 nvidia-docker2를 설치하면 됩니다.

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

u0017649@sys-97899:~$ sudo apt-get install -y nvidia-docker2

이제 docker daemon을 restart 한 뒤 테스트 삼아 ubuntu:18.04 image를 download 받습니다.

u0017649@sys-97899:~$ sudo systemctl restart docker

u0017649@sys-97899:~$ sudo docker pull ubuntu:18.04

u0017649@sys-97899:~$ sudo docker inspect ubuntu:18.04 | grep -i arch
        "Architecture": "ppc64le",

CUDA 9.0 + Python 3.5.3 + Tensorflow 1.12 + Ubuntu 18.04 docker image 최소화하여 만들기



Docker image size를 최소화해서 만들기 위해서는 일단 anaconda를 사용하면 안됩니다.  Anaconda를 설치하는데만도 4GB 정도가 들어가니까요.   또한 anaconda의 python 3.5.2는 gcc 4.8로 build된 것에 비해, Ubuntu 18.04에서 나오는 모든 library는 gcc 7.2로 build된 것이라서 CXX_ABI 문제가 발생할 가능성이 큽니다. 

이런 이유로, python을 anaconda를 이용하여 설치하지 않고, 그냥 source에서 build했습니다.  원래 Python 3.5.2 환경으로 하려고 했으나, python 3.5.2에는 아래 link에 나오는 pip 관련 error가 있습니다.  이 error는 python 3.5.3에서 fix 되었기 때문에 부득이하게 python 3.5.3을 설치하기로 했습니다.

https://stackoverflow.com/questions/50126814/ignoring-ensurepip-failure-pip-requires-ssl-tls-error-in-ubuntu-18-04 

먼저, 지난번에 만들어둔 CUDA 9.0과 Ubuntu 18.04 기반의 docker image를 run 시킵니다.

ibm@uniac922:~/files$ sudo docker run --runtime=nvidia -ti --rm -v ~/files:/mnt bsyu/ubuntu18.04_cuda9-0_ppc64le:v0.3

root@f47afeb949b5:/# cd /mnt

Python 3.5.3의 source를 download 받습니다.

root@75ecf9980173:/mnt# wget https://www.python.org/ftp/python/3.5.3/Python-3.5.3.tgz

root@75ecf9980173:/mnt# ls -l Python-3.5.3.tgz
-rw-rw-r-- 1 1003 1003 20656090 Jan 17  2017 Python-3.5.3.tgz

root@75ecf9980173:/mnt# tar -zxf Python-3.5.3.tgz

root@75ecf9980173:/mnt# cd Python-3.5.3

Python의 build는 간단합니다.  configure-make-make install 순입니다.

root@75ecf9980173:/mnt/Python-3.5.3# ./configure

root@75ecf9980173:/mnt/Python-3.5.3# make -j 32

root@75ecf9980173:/mnt/Python-3.5.3# make install

Build된 python은 /usr/local/bin/python3 으로 설치됩니다.   따라서 PATH에 /usr/local/bin을 추가해줘야 합니다.  물론 pip도  /usr/local/bin/pip3로 설치됩니다.

root@75ecf9980173:/mnt/Python-3.5.3# export PATH=/usr/local/bin:$PATH

root@75ecf9980173:/mnt/Python-3.5.3# echo "export PATH=/usr/local/bin:$PATH" >> ~/.bashrc

root@75ecf9980173:/mnt/Python-3.5.3# which python3
/usr/local/bin/python3

root@75ecf9980173:/mnt/Python-3.5.3# which pip3
/usr/local/bin/pip3

root@75ecf9980173:/mnt/Python-3.5.3# cd ..

이제 지난번에 anaconda의 python 3.5.2 환경에서 build했던 tensorflow의 wheel file을 이용해 pip3 명령으로 설치합니다.   이때 numpy나 keras-applications 등과 같은 prerequisite package들도 함께 자동으로 설치됩니다.

root@75ecf9980173:/mnt# pip3 install tensorflow_pkg3/tensorflow-1.12.0-cp35-cp35m-linux_ppc64le.whl

이제 python3를 구동하여 tensorflow를 import하고 GPU를 제대로 물고 오는지 test해봅니다.   아래와 같이 잘 됩니다.

root@6afae4bd06e3:/mnt# python3
Python 3.5.3 (default, May 16 2019, 11:02:36)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import tensorflow as tf

>>> sess=tf.Session()
2019-05-16 11:48:42.110194: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0004:04:00.0
totalMemory: 15.75GiB freeMemory: 15.45GiB
2019-05-16 11:48:42.260439: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 1 with properties:
...
2019-05-16 11:48:44.235074: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:3 with 14943 MB memory) -> physical GPU (device: 3, name: Tesla V100-SXM2-16GB, pci bus id: 0035:04:00.0, compute capability: 7.0)


이제 docker image의 크기를 줄이기 위해 아래와 같이 불필요한 file들과 package들을 삭제합니다.

root@6afae4bd06e3:~# rm -rf /var/lib/apt/lists/*  ~/.cache/*

root@6afae4bd06e3:~# apt remove curl fontconfig fontconfig-config fonts-dejavu-core fonts-dejavu-extra git git-man keyboard-configuration less lsb-release make manpages manpages-dev wget cuda-cublas-dev-9-0 cuda-npp-dev-9-0


다른 ssh session을 열어서 parent OS에서 위의 docker container를 image로 commit합니다.

ibm@uniac922:~$ sudo docker commit 6afae4bd06e3 bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le:v0.2
sha256:93a146481e72fbc8714ddbb1adfb596c7f20a094bf5788fbd856fc5e2a489b71

Image 크기를 보면 거의 7GB 정도 되는 것을 보실 수 있습니다.

ibm@uniac922:~$ sudo docker images | grep py353
bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le             v0.2                               93a146481e72        3 seconds ago       6.99GB

이제 이것의 size를 줄이기 위해, 아래와 같이 export 합니다.

ibm@uniac922:~$ sudo docker export 6afae4bd06e3 > ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le_v0.2.tar

여러가지 file들을 지웠기 때문에, export된 tar file의 크기는 4.2GB 정도에 불과합니다.

ibm@uniac922:~$ ls -l ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le_v0.2.tar
-rw-rw-r-- 1 ibm ibm 4204572160 May 16 11:58 ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le_v0.2.tar

이제 이것을 import 합니다.  이때 nvidia driver volume 등을 제대로 가져오기 위해 --change 옵션을 넣어야 하는 것을 잊지 마십시요.

ibm@uniac922:~$ cat ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le_v0.2.tar | sudo docker import  --change "ENV NVIDIA_VISIBLE_DEVICES=all" --change "ENV NVIDIA_DRIVER_CAPABILITIES compute,utility" --change "ENV LD_LIBRARY_PATH /usr/local/nvidia/lib64:/usr/local/nvidia/lib:/usr/local/cuda/lib64:/usr/lib:/usr/lib64:/lib:/lib64:/usr/local/lib:/usr/local/lib64" - bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le:v0.3

이렇게 import된 docker image의 크기는 4.2GB 정도입니다.  원래보다 거의 3GB 정도 줄었습니다.

ibm@uniac922:~$ sudo docker images | grep py353
bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le             v0.3                               be956177f42a        6 seconds ago       4.16GB
bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le             v0.2                               93a146481e72        10 minutes ago      6.99GB

이 새로운 이미지에서 tensorflow가 잘 동작하는지 확인합니다.  아래와 같이 잘 됩니다.

ibm@uniac922:~$ sudo docker run --runtime=nvidia -ti --rm -v ~/files:/mnt bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le:v0.3 bash

root@a8d890e2a25a:/# python3
Python 3.5.3 (default, May 16 2019, 11:02:36)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

>>> import tensorflow as tf

>>> sess=tf.Session()
2019-05-16 03:07:31.017607: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1432] Found device 0 with properties:
name: Tesla V100-SXM2-16GB major: 7 minor: 0 memoryClockRate(GHz): 1.53
pciBusID: 0004:04:00.0
totalMemory: 15.75GiB freeMemory: 15.44GiB
...
2019-05-16 03:07:33.042540: I tensorflow/core/common_runtime/gpu/gpu_device.cc:1115] Created TensorFlow device (/job:localhost/replica:0/task:0/device:GPU:0 with 14938 MB memory) -> physical GPU (device: 0, name: Tesla V100-SXM2-16GB, pci bus id: 0004:04:00.0, compute capability: 7.0)


이제 이 v0.3 image를 latest라는 tag로 tagging하고, docker hub로 push 합니다.

ibm@uniac922:~$ sudo docker images | grep py353
bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le             latest                             be956177f42a        2 minutes ago       4.16GB
bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le             v0.3                               be956177f42a        2 minutes ago       4.16GB

ibm@uniac922:~$ sudo docker push bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le:v0.3

이것을 사용하시기 위해서는 아래 명령으로 pull 하시면 됩니다.


$ sudo docker pull bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le:v0.3

또는

$ sudo docker pull bsyu/ubuntu18.04_cuda9-0_py353_tf1.12_ppc64le:latest

2019년 5월 8일 수요일

ppc64le Ubuntu 18.04 환경에서 PyTorch 설치하기



여기서는 Ubuntu 18.04 기반에 CUDA 10-0 버전이 설치되어 있는 docker image 속에 PyTorch v1.0.1을 설치하는 과정을 보시겠습니다.

먼저 nvidia-docker2로 CUDA 10-0과 Anaconda3 v4.4이 설치되어 있는 Ubuntu 18.04 기반의 docker image를 run 시킵니다.

[root@ac922 ~]# docker run --runtime=nvidia -ti --rm -v /data/files:/mnt bsyu/ubuntu18.04_cuda10-0_python352_ppc64le:v0.1


Docker container 안에서, 먼저 openblas 등의 필요 SW를 설치합니다.

root@d7a720117c80:/# cd /mnt

root@d7a720117c80:/mnt# apt-get install -y libblas-dev libopenblas-base

root@d7a720117c80:/mnt# conda install numpy pyyaml setuptools cmake cffi openblas


다음과 같이 ONNX를 먼저 설치합니다.

root@d7a720117c80:/mnt# git clone --recursive https://github.com/onnx/onnx.git

root@d7a720117c80:/mnt# pip install -e onnx/


이제 pytorch의 source를 git clone으로 받습니다.

root@d7a720117c80:/mnt# git clone https://github.com/pytorch/pytorch.git

root@d7a720117c80:/mnt# cd pytorch

root@d7a720117c80:/mnt/pytorch# git submodule update --init

root@d7a720117c80:/mnt/pytorch# git checkout tags/v1.0.1

root@d7a720117c80:/mnt/pytorch# export CMAKE_PREFIX_PATH=/opt/anaconda3


여기서 한가지 source file을 수정해야 합니다.   아래와 같이 4줄을 //으로 comment-out하는 것이 수정의 내용입니다.  이렇게 수정하지 않으면 "fatal error: onnx/onnx.pb.h: No such file or directory"라는 error를 만나시게 됩니다.

root@d7a720117c80:/mnt/pytorch# vi third_party/onnx/onnx/onnx_pb.h
...
//#ifdef ONNX_ML
#include "onnx/onnx-ml.pb.h"
//#else
//#include "onnx/onnx.pb.h"
//#endif


이제 아래와 같이 setup.py를 수행하여 install 합니다.

root@d7a720117c80:/mnt/pytorch# python setup.py install


이제 install이 끝났습니다.   아래와 같이 다른 directory로 이동하여 python을 구동한 뒤, import torch를 해보십시요.

root@d7a720117c80:/mnt/pytorch# cd ..
root@d7a720117c80:/mnt# python
Python 3.5.6 |Anaconda custom (64-bit)| (default, Aug 26 2018, 22:03:11)
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> from __future__ import print_function
>>> x = torch.Tensor(5, 3)
>>> print(x)
tensor([[0.0000e+00, 0.0000e+00, 7.1479e+22],
        [7.3909e+22, 2.5318e-12, 8.1465e-33],
        [1.3563e-19, 1.8888e+31, 4.7414e+16],
        [2.5171e-12, 8.0221e+17, 1.3556e-19],
        [1.3563e-19, 1.3563e-19, 1.8561e-19]])


이때 GPU를 제대로 사용하는지 확인해보시려면 아래와 같이 cuda()를 사용해보십시요.

>>> if torch.cuda.is_available():
...   x = x.cuda()
...   y = y.cuda()
...   x + y
...
tensor([[-1.3789e-07,  4.3664e-41, -1.3789e-07],
        [ 7.3909e+22,  4.8930e-12,  1.1625e+33],
        [ 8.9605e-01,  1.1632e+33,  5.6003e-02],
        [ 7.0374e+22,  1.5301e+10,  1.0795e+30],
        [ 6.1205e+10,  1.8812e+31,  1.3567e-19]], device='cuda:0')



2019년 5월 3일 금요일

이미 만들어진 docker image의 size를 줄이는 방법


이미 만들어놓은 docker image의 크기를 줄여야 할 필요가 있을 수 있습니다.   가령 지난번 posting 에서 docker image를 만들 때는 크기를 줄이는 것에 대한 고려는 전혀 없었습니다.   가령 docker build할 때 /tmp/temp 밑에 있던 임시 파일들을 지우지도 않았고, 또 RUN을 너무 많이 썼습니다.   (저는 몰랐습니다만) docker image의 layer는 저런 RUN 1줄마다 따로 만들어진다는군요.

가령 dockerfile 안에 들어있는 아래와 같은 5줄은...

RUN apt-key add /tmp/temp/apt.key1
RUN add-apt-repository "deb [arch=ppc64el] https://download.docker.com/linux/ubuntu bionic stable"
RUN dpkg -i /tmp/temp/cuda-repo-ubuntu1604_9.0.176-1_ppc64el.deb
RUN apt-key add /tmp/temp/apt.key2 && apt-get update
RUN apt-get install -y `apt-cache pkgnames | grep cuda | grep -v qnx | grep -v armhf | grep -v aarch64 | grep 9-0`

아래와 같이 1줄로 줄이는 것이 전체 docker image size를 줄이는데 도움이 됩니다.

RUN apt-key add /tmp/temp/apt.key1 && add-apt-repository "deb [arch=ppc64el] https://download.docker.com/linux/ubuntu bionic stable" && dpkg -i /tmp/temp/cuda-repo-ubuntu1604_9.0.176-1_ppc64el.deb && apt-key add /tmp/temp/apt.key2 && apt-get update && apt-get install -y `apt-cache pkgnames | grep cuda | grep -v qnx | grep -v armhf | grep -v aarch64 | grep 9-0`


Docker image의 크기를 작게 만드는 것은 물론 만들 때부터 그런 점을 고려해서 작은 size로 만드는 것이 좋습니다.  그러나. 이미 만들어진 docker image의 크기를 줄이는 것도 가능합니다.  export와 import를 사용하면 됩니다.

가령 아래의 image는 size가 8.19GB입니다.

ibm@uniac922:~/files/docker$ sudo docker images | grep cuda9-2_python368_pytorch1.01_ppc64le | grep latest
bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le    latest              b6695ad4cb7f        9 days ago          8.19GB

이 docker image를 run 시켜서 전에 못 지웠던 /tmp/temp도 지우고, apt autoremove로 필요없는 OS fileset들도 지운뒤 그 container를 commit하여 v0.5의 tag로 새로 이미지를 만들었습니다.   그러나 그 결과는 여전히 크기가 8.19GB입니다.

ibm@uniac922:~/files/docker$ sudo docker images | grep cuda9-2_python368_pytorch1.01_ppc64le | grep v0.5
bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le    v0.5                a8552891b60a        13 seconds ago      8.19GB

실제로 docker image의 크기가 줄어들려면, 이걸 그냥 commit를 하면 안 되고, docker export로 저장해야 합니다.

ibm@uniac922:~$ sudo docker ps -a
CONTAINER ID        IMAGE                                                         COMMAND                  CREATED             STATUS              PORTS                               NAMES
f5880eb6e4f0        bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le:v0.4   "bash"                   17 seconds ago      Up 16 seconds       8888/tcp                            modest_golick

ibm@uniac922:~$ sudo docker export f5880eb6e4f0 > ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le.v0.5.tar

이 export된 tar file의 크기는 5.7GB 정도입니다.

ibm@uniac922:~$ ls -ltr
total 5677172
-rw-r--r--  1 ibm ibm       8980 May  2 17:27 examples.desktop
drwxrwxr-x 17 ibm ibm       4096 May  2 17:37 anaconda2
drwxrwxr-x  3 ibm ibm       4096 May  3 13:52 files
-rw-rw-r--  1 ibm ibm 5813396992 May  3 15:20 ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le.v0.5.tar

이걸 import 해보겠습니다.

ibm@uniac922:~$ cat ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le.v0.5.tar | sudo docker import  --change "ENV NVIDIA_VISIBLE_DEVICES=all" --change "ENV NVIDIA_DRIVER_CAPABILITIES compute,utility" - bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le:v0.6

이제 size를 보면 위의 tar file size처럼 새로운 image인 v0.6의 size는 5.7GB인 것을 보실 수 있습니다.

ibm@uniac922:~$ sudo docker images | grep cuda9-2_python368_pytorch1.01_ppc64le
bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le    v0.6                5453478b0106        49 seconds ago      5.72GB
bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le    v0.5                a8552891b60a        2 hours ago         8.19GB
bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le    latest              b6695ad4cb7f        9 days ago          8.19GB



2019년 5월 2일 목요일

ppc64le (IBM POWER9) nvidia-docker2 환경에서 Ubuntu 기반의 docker image 만들기



Redhat 7.5 ppc64le (IBM POWER9) 위에 설치된 nvidia-docker2 환경에서 Ubuntu 기반의 docker image를 만드는 과정을 정리했습니다. 

먼저, 아래 posting 참조해서 Redhat 7.5 ppc64le에 nvidia-docker2 (정확하게는 nvidia-docker2가 아니라 nvidia-runtime)을 설치합니다.

http://hwengineer.blogspot.com/2019/04/ppc64le-redhat-7-nvidia-docker2-nvidia.html

아래와 같이 ubuntu 관련 apt key값들을 받아둡니다.  이것들은 나중에 ubuntu 기반의 docker image를 만들 때 사용됩니다.

[root@ac922 tmp]# mkdir docker

[root@ac922 tmp]# cd docker

[root@ac922 docker]# curl -fsSL https://download.docker.com/linux/ubuntu/gpg > apt.key1

[root@ac922 docker]# curl -fsSL https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/ppc64el/7fa2af80.pub > apt.key2

참고로, 이 key 파일들은 아래와 같이 생긴 text file들입니다.

[root@ac922 docker]# cat apt.key1
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
YT90qFF93M3v01BbxP+EIY2/9tiIPbrd
=0YYh
-----END PGP PUBLIC KEY BLOCK-----

[root@ac922 docker]# cat apt.key2
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1

mQINBFdtt4UBEAC8FDSWMR07GJZ265giLn7kLF+EsJCWESUq6Cd13QN0JQ/tLibi
QlW4ZjeOnEH9VPlqh/mKqNMG4SwRt8S+GHpePMQrr0aOkiRGfCclnAWIZURSAP+t
PLelCt43fkw1BBTopd/0oOzO8kHu8j8WU4A8GHxqghfFWPv54FQs2iaZ2eWR7a6d
79IJrbDKaVCCiQrkhCM8m648pNKHhuoJ9cQXFV+uvwkpfmKWGQ4ultxlOyjLHJLF
vuML2RuAO9IxbdZjzeYNN+T+wjFIBVcPnwEO+WrYgvGkT4r9aqVqTeg3EPb7QclV
sKBVJdxk4jZl0y22HAWqScVi6SJ15uK9pXxywDZkbpuRBWx4ThWiGe/FiUa2igi9
/SIvqN2TBY0g18sRTrylVr1wE1UGa/y7nDx6PoGCP1frBt8YUYt3pkM8Xvb2CRxx
CyWwmuFEQHC6jCEWf7FnoBHBYQwTVGNrU0vkuIeDrm+ZAcv8wx+ie1hlFhqCCJnf
jqeQ0/zA9RPmCPOkLyTdSsNZtlxxk7bzCdTdFFKzBjGTR7Gz3SMSp23d11eIyRiF
HQsp2v0SvnPJ6OcgB95Hmo544vi3RuoVfovtDOdfSBCRxP+GhhxkKSrTleQjD0/r
CGkdG2Kox3m9YllAsvZchLXlS7bZV9mGRF61mVMjF3HJRUQfBBm89VPQ+QARAQAB
tCBjdWRhdG9vbHMgPGN1ZGF0b29sc0BudmlkaWEuY29tPokCNwQTAQgAIQUCV223
hQIbAwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRD2D0s9f6KvgNArEAChnfcW
rYItgt7xXXubT6E+KpJyJ0RPrXf51S2mhciFbjDl+3EXRMRjOutVmgWYPWUUZaKR
8Iez3Lz4BRmwYOWBLtdnOLbKoSsQUX95rnPFjfly/DFLfjKxz4NRBmh4r4/rCYWm
2hmnXmOAi8kV7fqx3g5XMpJ//N6+T8ctEol2iZ82GrXjadcRWE4rAe7UyuEzJ74y
6ZKIzk5ijdgEKtcaBhzEWvoV5Pr9nkn7ByGsdehKR/gNnjPMYXrklSHGfphJIsS2
S32lMk/kuRjihBcWcYBXIPEQ7CV+PNW2TlkZj/YqTg637sZHwkhcjcNzxeqKvRYG
8V7Ju5hTDxL1UQBmgDS3cRx1lw7tYRG5bS67tbC2dc/CpPkG5agiZ/WyoHQDnn4r
1fRuOFx694QR6+0rAP6171xEEoNAPaH7gdJdhWKiYiJD0T2EEbW7wBUi/EupeKRv
kR12R1jUa1mlpxNtWQxJ7qp98T9+DmkxI1XDmWx0/g4ryuicwLDSqoPgNcRNdSQb
b8YfTqrkqaDdYzwLr/n0YKW3cYIvIeisV0WxRjb6OP7oAlAtaAhImlIc//51qNO7
/WAud6qMtnhFoZayR/BzLKqnCioN5GYr9BAKskpPHe9cDKVS3fg+Qvc1sNJID+jf
k52PqyW24Qsr0A9+5zQyE4tH9dfv120gj9avmg==
=0nKc
-----END PGP PUBLIC KEY BLOCK-----


그리고나서 ppc64le 아키텍처의 Ubuntu 기반 docker base image를 아래와 같이 pull로 당겨옵니다.

[root@ac922 docker]# docker pull ubuntu:18.04

아래와 같이 작은 ubuntu 기반 image가 pull 된 것을 보실 수 있습니다.

[root@ac922 docker]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
ubuntu                              18.04               a7cbdb002963        4 weeks ago         129MB

이게 ppc64le 아키텍처의 image가 맞는지는 아래와 같이 확인하시면 됩니다.

[root@ac922 docker]# docker inspect ubuntu:18.04 | grep -i arch
        "Architecture": "ppc64le",

위에서 받은 base image를 이용하여, cuda10-0 기반의 ubuntu docker image를 만들기 위한 dockerfile을 아래와 같이 작성합니다.

[root@ac922 docker]# cat dockerfile.cuda10-0
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common gcc g++ zip unzip gzip bzip2 build-essential wget git vim-tiny  libcurl4-openssl-dev libssl-dev libssh2-1-dev
RUN mkdir /tmp/temp
COPY apt.key1 /tmp/temp
RUN apt-key add /tmp/temp/apt.key1
RUN add-apt-repository "deb [arch=ppc64el] https://download.docker.com/linux/ubuntu bionic stable"
COPY cuda-repo-ubuntu1804_10.0.130-1_ppc64el.deb /tmp/temp/
RUN dpkg -i /tmp/temp/cuda-repo-ubuntu1804_10.0.130-1_ppc64el.deb
COPY apt.key2 /tmp/temp
RUN apt-key add /tmp/temp/apt.key2
RUN apt-get update
RUN apt-get install -y `apt-cache pkgnames | grep cuda | grep -v qnx | grep -v armhf | grep -v aarch64 | grep 10-0`
COPY cudnn-10.0-linux-ppc64le-v7.5.0.56.solitairetheme8 /tmp/temp/
COPY nccl_2.4.2-1+cuda10.0_ppc64le.txz /tmp/temp/
LABEL com.nvidia.volumes.needed="nvidia_driver"
LABEL com.nvidia.cuda.version="10.1"
RUN echo "/usr/local/nvidia/lib" >> /etc/ld.so.conf.d/nvidia.conf
RUN echo "/usr/local/nvidia/lib64" >> /etc/ld.so.conf.d/nvidia.conf
RUN tar -xf /tmp/temp/cudnn-10.0-linux-ppc64le-v7.5.0.56.solitairetheme8 -C /usr/local
RUN tar -xf /tmp/temp/nccl_2.4.2-1+cuda10.0_ppc64le.txz -C /usr/local
# set the working directory
ENV LD_LIBRARY_PATH="/usr/local/nvidia/lib64:/usr/local/nvidia/lib:/usr/local/cuda/lib64:/usr/lib:/usr/lib64:/lib:/lib64:/usr/local/lib:/usr/local/lib64"
ENV PATH="/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/bin"
ENV NVIDIA_VISIBLE_DEVICES all
ENV NVIDIA_DRIVER_CAPABILITIES compute,utility
ENV NVIDIA_REQUIRE_CUDA "cuda>=10.0"
CMD /bin/bash

위와 같이 작성된 dockerfile을 이용하여 아래 docker build 명령으로 CUDA 10.0이 설치된 docker image를 build합니다.

[root@ac922 docker]# docker build -f dockerfile.cuda10-0 -t bsyu/ubuntu18.04_cuda10-0_ppc64le:v0.2 .

이제 아래와 같이 bsyu/ubuntu18.04_cuda10-0_ppc64le:v0.2 라는 이미지가 build 되었습니다.

[root@ac922 docker]# docker images
REPOSITORY                          TAG                 IMAGE ID            CREATED             SIZE
bsyu/ubuntu18.04_cuda10-0_ppc64le   v0.2                c723faffd5c5        About an hour ago   5.47GB
ubuntu                              18.04               a7cbdb002963        4 weeks ago         129MB

이 image를 아래와 같이 run 시켜 봅니다. 

[root@ac922 docker]# docker run --runtime=nvidia -ti --rm bsyu/ubuntu18.04_cuda10-0_ppc64le:v0.2 bash

아래와 같이 nvidia-smi 명령을 수행해보면 일단 잘 돌아가는 것을 보실 수 있습니다.

root@19b69f2a09a3:/# nvidia-smi -l 2
Fri Apr 12 12:55:21 2019
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 418.40.04    Driver Version: 418.40.04    CUDA Version: 10.1     |
|-------------------------------+----------------------+----------------------+
| 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 V100-SXM2...  On   | 00000004:04:00.0 Off |                    0 |
| N/A   40C    P0    65W / 300W |  31606MiB / 32480MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   1  Tesla V100-SXM2...  On   | 00000004:05:00.0 Off |                    0 |
| N/A   44C    P0    71W / 300W |  31606MiB / 32480MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   2  Tesla V100-SXM2...  On   | 00000035:03:00.0 Off |                    0 |
| N/A   40C    P0    65W / 300W |  31606MiB / 32480MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
|   3  Tesla V100-SXM2...  On   | 00000035:04:00.0 Off |                    0 |
| N/A   45C    P0    55W / 300W |  31606MiB / 32480MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+


하지만 이 경우는 운이 좋은 것에 불과합니다.   Parent OS인 Redhat 7.5 ppc64le에도 nvidia driver 버전이 Ubuntu image속 버전과 동일한 418.40.04 이었기 때문에 이렇게 잘 수행되는 것입니다.  원래, nvidia-docker2에서는 image 속에 nvidia driver가 설치되어 있으면 안 됩니다.

만약 parent OS의 nvidia-driver 버전이 다른 경우, 아래와 같은 error message가 나면서 dicker run이 안 될 것입니다.  아래는 Ubuntu image 속의 driver가 410.104 버전인 경우입니다.

[root@ac922 docker]# docker run --runtime=nvidia -ti --rm bsyu/ubuntu18.04_cuda9-2_ppc64le:v0.1 bash

docker: Error response from daemon: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"process_linux.go:385: running prestart hook 1 caused \\\"error running hook: exit status 1, stdout: , stderr: exec command: [/usr/bin/nvidia-container-cli --load-kmods configure --ldconfig=@/sbin/ldconfig --device=all --compute --utility --pid=44664 /var/lib/docker/overlay2/65906de889a32465e87e680b8968834abaa1f4c4069beadab01bb7691f43523f/merged]\\\\nnvidia-container-cli: mount error: file creation failed: /var/lib/docker/overlay2/65906de889a32465e87e680b8968834abaa1f4c4069beadab01bb7691f43523f/merged/usr/bin/nvidia-smi: file exists\\\\n\\\"\"": unknown.

이를 해결하기 위해서는 docker image 속에 CUDA를 설치할 때 함께 설치된 nvidia driver를 제거해줘야 합니다.   먼저, 아래와 같이 nvidia-docker가 아닌 그냥 docker로 수행되도록 --runtime=nvidia 옵션을 빼고 docker를 구동합니다.  그렇게 하면 최소한 위의 'file exists' error는 나지 않을 것입니다.

[root@ac922 docker]# docker run -ti --rm bsyu/ubuntu18.04_cuda9-2_ppc64le:v0.1 bash             

이어서 image 속에 들어가보면 아래와 같은 nvidia driver들이 보일 것입니다. 

root@45fb663f025c:/# dpkg -l | grep nvidia
ii  nvidia-410                      410.104-0ubuntu1                  ppc64el      NVIDIA binary driver - version 410.104
ii  nvidia-410-dev                  410.104-0ubuntu1                  ppc64el      NVIDIA binary Xorg driver development files
ii  nvidia-modprobe                 410.104-0ubuntu1                  ppc64el      Load the NVIDIA kernel driver and create device files
ii  nvidia-opencl-icd-410           410.104-0ubuntu1                  ppc64el      NVIDIA OpenCL ICD
ii  nvidia-prime                    0.8.8.2                           all          Tools to enable NVIDIA's Prime
ii  nvidia-settings                 410.104-0ubuntu1                  ppc64el      Tool for configuring the NVIDIA graphics driver

아래와 같이 이 관련 fileset들을 다 지워버린 뒤, 새로운 tag로 해당 container를 commit 합니다.

root@45fb663f025c:/# apt-get remove -y nvidia-*

Docker image 속의 저 명령이 완료되면 다른 창에서 parent OS에 접속하여 다음고 같이 commit 합니다.

먼저 저 container의 ID를 확인하고...

[root@ac922 docker]# docker ps -a
CONTAINER ID        IMAGE                                   COMMAND             CREATED             STATUS              PORTS               NAMES
45fb663f025c        bsyu/ubuntu18.04_cuda9-2_ppc64le:v0.1   "bash"              42 seconds ago      Up 39 seconds                           elastic_gates

이어서 v0.2라는 새로운 tag로 commit 합니다.

[root@ac922 docker]# docker commit 45fb663f025c bsyu/ubuntu18.04_cuda9-2_ppc64le:v0.2
sha256:172cdbe6ba2f5f21ce8352a7be964d921d0340c82c1d1d91d54bf28d2c5e2c33


아래와 같이 여러가지 image들을 준비하여 public docker hub에 push로 올려 놓았습니다.  아래 이름을 참조하여 필요에 따라 pull 하여 사용하시기 바랍니다.


[root@ac922 docker]# docker images | grep latest
bsyu/ubuntu18.04_cuda9-2_python368_pytorch1.01_ppc64le    latest              b6695ad4cb7f        8 days ago          8.19GB
bsyu/ubuntu18.04_cuda10-0_ppc64le                         latest              a4f8442230bf        8 days ago          5.54GB
bsyu/ubuntu18.04_cuda10-0_python368_ppc64le               latest              817f3211acdb        8 days ago          7.29GB
bsyu/ubuntu18.04_cuda10-0_python352_ppc64le               latest              cadd3fdb9653        8 days ago          8.6GB
bsyu/ubuntu18.04_cuda10-0_python352_tf1.12_ppc64le        latest              929db5ab1260        8 days ago          18.2GB
bsyu/ubuntu18.04_cuda10-0_python368_pytorch1.01_ppc64le   latest              00fb9697002a        8 days ago          9.45GB
bsyu/ubuntu18.04_cuda10-0_python368_tf1.12_ppc64le        latest              cf2342b0c1b8        8 days ago          16.8GB
bsyu/ubuntu18.04_cuda10-0_python352_pytorch1.01_ppc64le   latest              e8d0a0897362        8 days ago          9.24GB
bsyu/ubuntu18.04_cuda9-2_python352_pytorch1.01_ppc64le    latest              9bf2cafb6836        8 days ago          8.92GB
bsyu/ubuntu18.04_cuda9-2_python352_tf1.12_ppc64le         latest              c1d6c56b6f11        8 days ago          17.4GB
bsyu/ubuntu18.04_cuda9-2_python352_ppc64le                latest              79d3a19ae9ad        8 days ago          8.35GB
bsyu/ubuntu18.04_cuda9-2_python368_tf1.12_ppc64le         latest              e80932cafae5        8 days ago          18.5GB
bsyu/ubuntu18.04_cuda9-2_ppc64le                          latest              eeae2d1f6fd4        8 days ago          5.26GB
bsyu/ubuntu18.04_cuda10-0_python368_cudf0.7.0_ppc64le     latest              86930ab12fe2        8 days ago          10.4GB