【Docker系列】Docker入门教程

环境配置的难题

如果你正好是一个运维工程师而且你正感觉你的运维环境一团糟,麻烦请你思考一下这是为什么?你是不是正在运维着一个使用 php、java、C#甚至 C/C++等用各种语言编写的应用都在运行的环境里?这个环境是不是因为某种历史原因,使你的操作系统运行着各个版本的内核甚至还有 windows?即使是同样语言编写的业务也运行着不同版本的库?你的整个系统环境是不是甚至找不出来两台硬件、操作系统、库版本以及语言版本完全一样的环境?于是你每次遇到问题都要去排查到底那个坑到底在那里?从网络、内核到应用逻辑。你每次遇到产品升级都要在各种环境上做稳定性测试,发现不同的环境代码 crash 的原因都不尽相同。你就像一个老中医一样去经历各种疑难杂症,如果遇到问题能找到原因甚至都是幸运的,绝大多数情况是解决了但不知道原因和没解决自动好了也不知道原因。于是你们在一个特定的公司的环境中积累着“经验”,成为你们组新手眼中的大神,凭借历经故障养成的条件反射在快速解决不断发生的重复问题,并故弄玄虚的说:这就是工作经验。因为经验经常是搞不清楚原因时的最后一个遮羞布。当别人抱怨你们部门效率低的时候,你一般的反应是:”you can you up,no can no 逼逼!“

来自知乎

简介 & 简单原理

  • 可重复
  • 可移植。镜像应该可以运行在任何主机上并且运行尽可能多的次数。

用了 Docker,就像世界出现了集装箱,这样你的业务就可以随意的、无拘无束的运行在任何地方。

Docker 公司的口号:Build,Ship,and Run Any App,Anywhere。大概意思就是编译好一个应用后,可以在任何地方运行,不会像传统的程序一样,一旦换了运行环境,往往就会出现缺这个库,少那个包的问题。

Docker concepts

  • 镜像(Image):Docker 把应用程序及其依赖,打包在 image 文件里面
  • 容器(Container): 镜像本身是只读的,容器从镜像启动时,Docker在镜像的上层创建一个可写层,镜像本身不变。同一个 image 文件,可以生成多个同时运行的容器实例。
  • 注册服务器(Registry): 存放实际的镜像的地方,比如Docker的官方仓库Docker HubDocker Store
  • 仓库(Repository): 仓库是存放一组关联镜像的集合,比如同一个应用的不同版本的镜像。比如tensorflow

基本操作

关于镜像的基本操作

1
2
3
4
5
6
7
docker images          # 列出本机所有的docker镜像
docker inspect img_id # 查看镜像详细信息
docker history img_id # 查看镜像分层
docker rmi img_id # 删除镜像
docker rmi -f $(docker images -q) # 删除所有镜像
docker pull repository:tag # 拉取镜像,类似 git pull
docker push repository:tag # 上传镜像,类似git push

关于容器的基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1. 基于镜像启动一个容器
NAME=name_test # 命名你的容器,姓名_任务_其他
PROJECT_DIR=`pwd`/tutorial
nvidia-docker run -it \
--name $NAME \
-v $PROJECT_DIR:/root/ \
tensorflow/tensorflow:latest-gpu bash


# 2. 运行程序
cd /root
export CUDA_VISIBLE_DEVICES= # 只占用cpu
python convolutional.py
# 3. 退出容器
ctrl+p+q # 临时退出容器而不终止它 (不关闭bash进程)
# ctrl+d # 退出shell,退出容器
# 4. 查看所有正在运行的容器,并通过name找到你运行的容器
docker ps
# 5. 查看运行日志
docker logs container_id
# 6. 重新进入容器
docker attach container_id # 进入同一个bash
# 或者
docker exec -it container_id bash # 重新创建一个bash
# 7. 删除容器
docker rm container_id
# 8. 删除所有容器
docker rm -f $(docker ps -a -q)
# 9. Copy a file from host to container 注意区别dockerfile的COPY命令
docker cp foo.txt 72ca2488b353:/foo.txt

思考
attachexec的区别
docker cp 与 dockerfile中的COPY的区别
ctrl+p+qctrl+d的区别
exit退出容器后,为什么容器并未删除?

使用建议

  • 合理命名镜像和容器
  • 少用port
  • 不要把频繁更新的项目打入镜像
  • 不用的镜像及时删除
  • 不用的容器及时退出

扩展阅读

定制自己的镜像 - Dockerfile

自己写dockerfile

  • FROM: 指定基础镜像
  • MAINTAINER:用来指定维护者的姓名和联系方式
  • ENV: 设置环境变量
  • RUN:在shell或者exec的环境下执行的命令。RUN指令会在新创建的镜像上添加新的层
  • EXPOSE: 指定容器在运行时监听的端口
  • COPY:
  • VOLUME: 授权访问从容器内到主机上的目录。用于containers之间共享数据
  • WORKDIR: 指定RUN、CMD与ENTRYPOINT命令的工作目录。
  • ENTRYPOINT:
  • CMD: 提供了容器默认的执行命令

注意

  • CMDENTRYPOINT 的区别:
    • CMD不能接受参数,运行时可被覆盖;
    • ENTRYPOINT能够接收参数,运行时不可被覆盖
  • COPY与映射-v的区别

示例dockerfile

build images

从文件进行build

1
docker build -f dockerfile . -t tensorflow/t2t:nmt

或 从标准输入中读取 Dockerfile 进行构建

1
cat dockerfile | docker build -

docker镜像升级

  • 更改 & commit的方式 (不推荐)
    • 一定不要用别人commit的镜像,是坑,用的时间越长坑越多
  • 更改dockerfile,重新build镜像 (推荐)

Dockerfile的优化技巧

  • apt-get install之前先apt-get update
  • 尽量选取满足需求但较小基础镜像,(比如debian:wheezy,仅有86MB大小)
  • 清理编译生成文件、安装包的缓存等临时文件
  • 安装各个软件时候要指定准确的版本号,并避免引入不需要的依赖
  • 从安全的角度考虑,应用尽量使用系统的库和依赖
  • 使用Dockerfile创建镜像时候要添加.dockerignore文件或使用干净的工作目录

扩展阅读:

练习

登录服务器ssh docker1@**.**.**.12

关于镜像的操作

参考上文↑

关于容器的基本操作

  1. 从已有docker启动容器,参考
    https://hub.docker.com/r/tensorflow/tensorflow/
  2. 从bash启动容器,参考上文↑

optinal:

  • httpd: 利用docker搭一个http server
  • gitlab: 利用docker搭一个gitlab server
  • kaldi: 利用docker跑kaldi
  • pytorch: 利用docker跑pytorch

Dockerfile相关

  1. 找到tensorflow的dockerfile,并参考
  2. 找到nvidia/cuda的dockerfile,并参考
  3. 自己根据需求,修改dockerfile,build image

思考

  1. 卸载 + commit 操作,镜像会变小吗?
  2. run yum clean cache这样写dockerfile,镜像会变小吗?
  3. 可以在一个容器中同时运行多个应用进程吗?
  4. Docker运行时内部删除的文件,如何恢复?
  5. RUN rm -rf somefile 镜像会减小吗?示例

扩展阅读

从wmt竞赛看机器翻译史

简介 & 汇总

  • wmt15
  • wmt16
  • wmt17
  • wmt18

WMT15

WMT16

WMT2017

搜狗机器翻译团队获得 WMT 2017 中英机器翻译冠军

审计署

审计署

尚未出现transformer,主流模型是attention-RNN。

核心问题通常是如何优化神经网络结构以便解决机器翻译中的词对齐、罕见词、长句等难点问题。

2014 年提出的注意力(attention)模块就是针对性处理因为不同语言语法结构不同产生的语序不同、来源词与目标词对齐难的问题。注意力机制通过选全局性的选择关注源语言橘子的不同部分,动态地构建上下文向量来对传统 RNN 编码器-解码器进行了优化,极大改善了语言调序,尤其是中长距离调序问题。

WMT2018

腾讯信息安全部征战世界机器翻译大赛获不俗战绩 - 2018

阿里、腾讯冠军。主流方法transformer。比wmt17提升

审计署

审计署

阿里达摩院 - 5项冠军

5个项目包括英文-中文翻译、英文-俄罗斯语互译、英文-土耳其语互译,达摩院在这几个项目的自动评测指标BLEU都位居第一。

  • 陈博兴博士
  • 司罗教授 - NLP 首席科学家

基于业界最新的Transformer结构,进行了网络结构的改进和对词语位置信息的充分利用。

尽管 Transformer 在解码速度和位置编码等方面有一些缺点,但它仍然是当前效果最好的神经机器翻译基本架构

腾讯

transformer改进

将 Transformer 中的 Multi-Head Attention 替换为多个自注意力分支,而模型会在训练阶段中将学习结合这些分支注意力模块。其次,阿里采用了一种编码相对位置的表征以扩展自注意力机制,并令模型能更好地理解序列元素间的相对距离。

多模型融合

  • 主体是transformer
  • rnn seq2seq
    每一种翻译任务都集成了几十上百个基础模型

参考

专访达摩院

云知声 - 第三

transformer + 数据生成(back translation)、多形态模型融合(ensemble)、多特征重排序(rerank)等,优化翻译效果。

马尔可夫模型(Markov models

马尔可夫性质(英语:Markov property)是概率论中的一个概念,因为俄国数学家安德雷·马尔可夫得名。当一个随机过程在给定现在状态及所有过去状态情况下,其未来状态的条件概率分布仅依赖于当前状态;换句话说,在给定现在状态时,它与过去状态(即该过程的历史路径)是条件独立的,那么此随机过程即具有马尔可夫性质。具有马尔可夫性质的过程通常称之为马尔可夫过程。

马尔可夫模型(Markov models)包括四种:

全观测 部分观测
System is autonomous 马尔科夫链 HMM
System is controlled 马尔科夫决策过程 部分观测马尔科夫决策过程
  • 马尔可夫链(英语:Markov chain),又称离散时间马可夫链(discrete-time Markov chain) 。下一状态的概率分布只能由当前状态决定,在时间序列中它前面的事件均与之无关。
  • m阶马尔可夫链。未来状态取决于其前m个状态

    这个的转移概率矩阵,是什么样的?这个矩阵会特别大吧?
  • Markov random field

bi-gram的转义概率是个二元矩阵,n-gram的转义概率是什么?n元的tensor吗?
n元的tensor会非常稀疏。

n-gram的n大小对性能的影响

n更大的时候

n: 对下一个词出现的约束性信息更多,更大的辨别力,但是更稀疏,并且n-gram的总数也更多,为 V^n 个(V为词汇表的大小)

n更小的时候

在训练语料库中出现的次数更多,更可靠的统计结果,更高的可靠性 ,但是约束信息更少

其中当N为特定值的时候,我们来看一下n-gram可能的总数,如下表

词表中词的个数 |V|=20,000词

n 所有可能的n-gram数
2 bigram 400,000,000
3 trigram 8,0000,0000,0000,0000
4 4-grams 1.6 *10^17

3gram数据太大了

相关工作

google的inception-v1-4

Szegedy在网络实现的时候,令 label_smoothing = 0.1,num_classes = 1000。Label smooth提高了网络精度0.2%。

google的[transformer]

GPU cuda安装指南

支持cuda的nvidia GPU

https://developer.nvidia.com/cuda-gpus

##

NVIDIA TX1/TX2
优点:

  • 性能强
  • NVIDIA嵌入式级GPU
  • CUDA配套好
    缺点
  • 价格高
  • 自己做底板
  • 不能跑Android

查看有没有

Verify You Have a CUDA-Capable GPU

1
2
3
4
5
$ lspci | grep -i nvidia
83:00.0 3D controller: NVIDIA Corporation GK210GL [Tesla K80] (rev a1)
84:00.0 3D controller: NVIDIA Corporation GK210GL [Tesla K80] (rev a1)
87:00.0 3D controller: NVIDIA Corporation GK210GL [Tesla K80] (rev a1)
88:00.0 3D controller: NVIDIA Corporation GK210GL [Tesla K80] (rev a1)
1
$ nvidia-smi

参考

-

tensorflow gpu

tensorflow gpu

tensorflow默认抢占服务器所有GPU的所有显存,一段小程序也会占用所有GPU资源。

解决方案:

为tf指定GPU:

1
2
3
import os
os.environ[‘CUDA_VISIBLE_DEVICE’] = ‘1,2'
# os.environ['CUDA_VISIBLE_DEVICES'] = '' # 设置为空,则使用cpu。或者='-1'

或者

1
2
3
4
5
6
7
8
9
10
import tensorflow as tf
with tf.device('/gpu:0'): # Run nodes with GPU 0
m1 = tf.constant([[3, 5]])
m2 = tf.constant([[2],[4]])
product = tf.matmul(m1, m2)

sess = tf.Session()
print(sess.run(product))

sess.close()

或者设置环境变量

1
2
3
$ export CUDA_VISIBLE_DEVICES=0,1
# 指定cpu,指定 visible devices为空
$ export CUDA_VISIBLE_DEVICES=

其次是限制在每个可用GPU上占据需要使用的内存大小:

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

该设置会启用最少的GPU显存来运行程序。

在tensorflow中定义session时作如下设置,该设置会强制程序只占用指定比例的GPU显存。

1
2
3
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.4 # 占用GPU40%的显存
session = tf.Session(config=config)

多GPU

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tensorflow as tf

c = []
for i, d in enumerate(['/gpu:0', '/gpu:1', '/gpu:2']):
with tf.device(d):
a = tf.get_variable(f"a_{i}", [2, 3], initializer=tf.random_uniform_initializer(-1, 1))
b = tf.get_variable(f"b_{i}", [3, 2], initializer=tf.random_uniform_initializer(-1, 1))
c.append(tf.matmul(a, b))

with tf.device('/cpu:0'):
sum = tf.add_n(c)

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))

init = tf.global_variables_initializer()
sess.run(init)

print(sess.run(sum))
# [[-0.36499196 -0.07454088]
# [-0.33966339 0.30250686]]

如何设置多个worker gpu

tensor2tensor中的worker-gpu配置,是怎样实现的。