HRBUST《高级软件工程》大作业---“ 创建Docker容器,利用容器共享GPU资源,并完成基于GPU的计算,如Tensorflow ”

1.作业要求:

创建Docker容器,利用容器共享GPU资源,并完成基于GPU的计算,如Tensorflow。

2.主机配置:

* Ubuntu18.04 系统

* GeForce GTX 1060 显卡

3.安装步骤:

1.安装docker

2.安装nvidia显卡驱动,(安装cuda、cudnn可选)

3.安装nvidia-docker

4.nvidia-docker pull tensorflow镜像

5.从镜像运行3个tensorflow容器,并测试GPU利用情况。(运行程序为mnist手写数字识别)

6.查看GPU资源使用情况,看看是否docker共享了资源。

4.过程详解:

4.1 安装docker

#更新apt源
$ sudo apt-get update

#安装其他库文件
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common


#添加Docker官方GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

添加Docker官方GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

#验证是否成功
sudo apt-key fingerprint 0EBFCD88

#将docker稳定版添加到apt仓库中
$sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

#将docker添加到apt库中后随即更新源
sudo apt-get update

#接下来就可以通过apt-get命令获取docker了
sudo apt-get install docker-ce docker-ce-cli containerd.io

此时,相信你的docker已经安装好了。下面测试一下:

sudo docker run hello-world

如果你的图是下面的结果那么你就安装成功了。(否则需要继续安装)

 

#创建docker用户组,并将当前用户加入组
$ sudo groupadd docker
$ sudo gpasswd -a${USER} docker
$ sudo service docker restart

4.2 安装NVIDIA驱动

我们在https://www.geforce.cn/drivers这个网址查询了Nvidia驱动输入我们的查询条件即可。经查询,为了找一个稳定的版本,我们选择了430的驱动。(其中还需要一些调整,请自行百度,主要写思路和步骤)

sudo apt-get install nvidia-driver-430

为了验证驱动安装成功,可以输入下面的指令。

nvidia-smi

若出现下面的图说明安装成功,否则请先安装驱动:

4.3安装nvidia-docker

1 首先添加到apt仓库

curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - \
curl -s -L https://nvidia.github.io/nvidia-docker/ubuntu16.04/amd64/nvidia-docker.list | \ 
   sudo tee /etc/apt/sources.list.d/nvidia-docker.list
sudo apt-get update

2 其次安装nvidia-docker2,并重新载入daemon.json

sudo apt-get install -y nvidia-docker2

验证安装成功方式即查看他的映像:

sudo nvidia-docker images

 

 4.4.nvidia-docker pull tensorflow的镜像:

由于我们做的实验是创建多个容器共享GPU资源,于是我们需要pull tensorflow的GPU版本。

直接输入命令:

sudo nvidia-docker pull tensorflow/tensorflow:latest-gpu

可以通过查看 nvidi-docker images 来确定该镜像已被拉取。 

******************************************************************************************************************************* 

特别注意:这个文件很大,建议换国内的docker源,如可以用中国科学技术大学的docker源。

在文件     /etc/ default/ docker 中加入以下参数,表示使用中国科学技术大学镜像仓库

DOCKER_OPTS="--registry-mirror=https://docker.mirrors.ustc.edu.cn" 

******************************************************************************************************************************* 

4.5 运行3个tensorflow容器,并测试GPU利用情况

4.5.1 创建 nvidia-docker 容器

输入命令: 代表创建一个用tensorflow/tensorflow:latest-gpu的镜像形成的容器,给容器的名字叫做tensorflow02,-it代表是交互模式,-v代表是映射路径,即把docker里的/usr/local/mytf2文件夹映射到宿主机里的/usr/local/mytf2文件夹下 ,-p代表docker里的8889端口映射到宿主机里的8888端口。( Note:第一次已经运行了,可以用stop+镜像名停止运行 )

sudo nvidia-docker run -it --name=tensorflow02 -v /usr/local/mytf2:/usr/local/mytf2 -p 8889:8888 tensorflow/tensorflow:latest-gpu /bin/bash

之后,现在tensorflow02已经开始运行了。我们可以用stop来停止容器运行。同时下次启动用start来启动。 

#创建容器
sudo nvidia-docker run [--参数] 镜像名

#启动容器:
sudo nvidia-docker start [容器名/id]           #如tensorflow02

#运行容器:(运行已经创建好的)
sudo nvidia-docker exec -it [容器名/id] /bin/bash

#查看所有容器情况
nvidia-docker ps -a

#删除容器
sudo nvidia-docker rm [容器名/id]

同样的我们再创建两个容器,一共三个容器来测试效果:

sudo nvidia-docker run -it -p 8888:8888 -v /usr/local/mytf:/usr/local/mytf --name=tensorflow01 tensorflow/tensorflow:latest-gpu /bin/bash

sudo nvidia-docker run -it -p 8890:8888 -v /usr/local/mytf2:/usr/local/mytf2 --name=tensorflow03 tensorflow/tensorflow:latest-gpu /bin/bash

4.5.2 运行一个容器测试Python程序

记住我们的目的是打开3个终端,各运行一个tensorflow容器,测试相应的python代码,然后查看gpu利用情况。

我们首先测试一个容器:

我们先将文件复制到 /usr/local/mytf2 文件夹下。(这个目录映射到了容器tensorflow02的 /usr/local/mytf2文件夹下)

sudo cp test.py /usr/local/mytf2

进入tensorflow01容器执行该python文件

sudo nvidia-docker exec -it tensorflow02 /bin/bash

cd /usr/local/mytf2 && python ./test.py
开启tensorflow01容器

 

运行结果0.9178

同时再次打开一个终端运行查看nvidia-smi即,终端运行情况。

发现改程序的确调用了GPU资源。到现在为止,我已经用tensorflow容器成功运行了一个python程序,并且该python程序确实使用了该资源。(下面列出了一个我们遇到的坑)

******************************************************************************************************************************* 

Note:我们在运行该程序的时候碰到了一个问题:

mnist无法运行,ModuleNotFoundError: No module named 'tensorflow.examples.tutorials'

 

解答:原来是因为pip install tensorflow 的时候没有获取到tutorials文件夹。

解决办法:从tensorflow的github网站下载tutorials文件夹复制到本地的

C:\Users\您的用户名\AppData\Local\Programs\Python\Python36\Lib\site-packages\tensorflow_core\examples文件夹下。(这个是windows版本。我在文末已经提供了下载链接,可以直接copy我的tutorials文件夹。)

而在Ubuntu环境中,先进入tensorflow容器,python2的文件夹路径为: /usr/local/lib/python2.7/dist-packages/tensorflow_core/examples.   (将tutorials文件夹复制到该目录下即可)

输入命令:

sudo nvidia-docker exec -it tensorflow01

#然后进入有tutorials的父目录,执行下面的复制命令,将
sudo cp -r ./tutorials /usr/local/lib/python2.7/dist-packages/tensorflow_core/examples/

(注意,每个人的路径可能不同,先找到python的安装路径,然后将改文件夹复制到tensorflow_core/examples的文件夹下。) 

******************************************************************************************************************************* 

4.5.2运行3个容器,分别运行python程序,并查看资源利用率。

运行3个容器的时候我们才发现事情并不简单,第一个容器执行第一个python程序,6G的显卡内存使用了将近5G,运行第二个容器运行该容器下的python程序,发现不能执行。原来第一个python程序已经把显卡资源占满了,不能分配内存了,所以我们应该对python代码进行调整,设置程序运行的内存限额。我们设置的模式为内存动态调配

给python代码添加下面的代码:

config = tf.ConfigProto()
config.gpu_options.allow_growth=True
sess = tf.Session(config=config)

最后我们调用nvidia-smi发现,程序运行正确,每个程序运行了使用了191MB,而不是将内存全占满。

下面是经过代码调试后的实验过程。

#打开第一个终端
sudo nvidia-docker exec -it tensorflow01 /bin/bash
python /usr/local/mytf2/test.py

#打开第二个终端
sudo nvidia-docker exec -it tensorflow02 /bin/bash
python /usr/local/mytf2/test.py

#打开第三个终端
sudo nvidia-docker exec -it tensorflow03 /bin/bash
python /usr/local/mytf2/test.py

#再次打开一个终端查看GPU使用情况
nvidia-smi
准备测试

最终,我们看到了如下图所示的结果。 

测试结果

4.6 (测试已经在4.5里介绍了,就不再赘述。)

5.总结:

最终我们的系统实现了创建容器,利用容器共享GPU资源的任务。

******************************************************************************************************************************* 

附录:

附上我们的最终的测试代码:

1.第一份测试代码 test.py

#!/usr/bin/python
#coding=utf-8
import time
from tensorflow.examples.tutorials.mnist import input_data

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
#import tensorflow as tf

# 2019/11/27 13:39 add
config = tf.ConfigProto()
config.gpu_options.allow_growth=True  
 #2019/11/27 13:39 add end

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)


x = tf.placeholder(tf.float32, [None, 784])  


W = tf.Variable(tf.zeros([784, 10]))
b = tf.Variable(tf.zeros([10]))


y = tf.nn.softmax(tf.matmul(x, W) + b)


y_ = tf.placeholder("float", [None, 10])
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))  


train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)


init = tf.global_variables_initializer()

#update 2019/11/27 13:39 
sess = tf.Session(config=config)
sess.run(init)
#update 2019/11/27 13:39 

for i in range(1, 1000):
    time.sleep(0.03)
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})


correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))
print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

2.第二份测试代码:

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

import numpy as np
from tensorflow.examples.tutorials.mnist import input_data

batch_size = 128
test_size = 256

def init_weights(shape):
    return tf.Variable(tf.random_normal(shape, stddev=0.01))

def model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden):
    l1a = tf.nn.relu(tf.nn.conv2d(X, w,                       # l1a shape=(?, 28, 28, 32)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l1 = tf.nn.max_pool(l1a, ksize=[1, 2, 2, 1],              # l1 shape=(?, 14, 14, 32)
                        strides=[1, 2, 2, 1], padding='SAME')
    l1 = tf.nn.dropout(l1, p_keep_conv)

    l2a = tf.nn.relu(tf.nn.conv2d(l1, w2,                     # l2a shape=(?, 14, 14, 64)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l2 = tf.nn.max_pool(l2a, ksize=[1, 2, 2, 1],              # l2 shape=(?, 7, 7, 64)
                        strides=[1, 2, 2, 1], padding='SAME')
    l2 = tf.nn.dropout(l2, p_keep_conv)

    l3a = tf.nn.relu(tf.nn.conv2d(l2, w3,                     # l3a shape=(?, 7, 7, 128)
                        strides=[1, 1, 1, 1], padding='SAME'))
    l3 = tf.nn.max_pool(l3a, ksize=[1, 2, 2, 1],              # l3 shape=(?, 4, 4, 128)
                        strides=[1, 2, 2, 1], padding='SAME')
    l3 = tf.reshape(l3, [-1, w4.get_shape().as_list()[0]])    # reshape to (?, 2048)
    l3 = tf.nn.dropout(l3, p_keep_conv)

    l4 = tf.nn.relu(tf.matmul(l3, w4))
    l4 = tf.nn.dropout(l4, p_keep_hidden)

    pyx = tf.matmul(l4, w_o)
    return pyx

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels
trX = trX.reshape(-1, 28, 28, 1)  # 28x28x1 input img
teX = teX.reshape(-1, 28, 28, 1)  # 28x28x1 input img

X = tf.placeholder("float", [None, 28, 28, 1])
Y = tf.placeholder("float", [None, 10])

w = init_weights([3, 3, 1, 32])       # 3x3x1 conv, 32 outputs
w2 = init_weights([3, 3, 32, 64])     # 3x3x32 conv, 64 outputs
w3 = init_weights([3, 3, 64, 128])    # 3x3x32 conv, 128 outputs
w4 = init_weights([128 * 4 * 4, 625]) # FC 128 * 4 * 4 inputs, 625 outputs
w_o = init_weights([625, 10])         # FC 625 inputs, 10 outputs (labels)

p_keep_conv = tf.placeholder("float")
p_keep_hidden = tf.placeholder("float")
py_x = model(X, w, w2, w3, w4, w_o, p_keep_conv, p_keep_hidden)

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=py_x, labels=Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
predict_op = tf.argmax(py_x, 1)

with tf.Session() as sess:
    # you need to initialize all variables
    tf.global_variables_initializer().run()

    for i in range(100):
        training_batch = zip(range(0, len(trX), batch_size),
                             range(batch_size, len(trX)+1, batch_size))
        for start, end in training_batch:
            sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end],
                                          p_keep_conv: 0.8, p_keep_hidden: 0.5})

        test_indices = np.arange(len(teX)) # Get A Test Batch
        np.random.shuffle(test_indices)
        test_indices = test_indices[0:test_size]

        print(i, np.mean(np.argmax(teY[test_indices], axis=1) ==
                         sess.run(predict_op, feed_dict={X: teX[test_indices],
                                                         p_keep_conv: 1.0,
                                                         p_keep_hidden: 1.0})))

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值