TPU使用说明
1 TPU分类和收费标准
1.1 分类和计费说明
地区 | 抢占式TPU | Cloud TPU |
---|---|---|
美国 | $1.35/hour | $4.5/hour | |
欧洲 | $1.485/hour | $4.95/hour | |
亚太区地区 | $1.566/hour | $5.22/hour |
- 抢占式 TPU 是 Cloud TPU 在需要将资源分配给另一项任务时,可以随时终止(抢占)的 TPU。抢占式 TPU 的费用要比普通 TPU 低廉得多。
- TPU 以 1 秒钟为增量单位进行计费。
为了连接到 TPU,我们必须配置一台虚拟机(单独结算)。要注意的是虚拟机和TPU是分别计费的。
也就是说仅在启动 TPU 之后,Cloud TPU 的计费才会开始;在停止或删除 TPU 之后,计费随即停止。运行 ctpu pause
或 gcloud compute tpus stop
即可停止 TPU。同样,只有在虚拟机激活之后,我们才会向您收取虚拟机费用。
如果虚拟机已停止,而 Cloud TPU 未停止,您需要继续为 Cloud TPU 付费。如果 Cloud TPU已停止或删除,而虚拟机未停止,则您需要继续为虚拟机付费。
1.2 实用查询链接
1.3 价格计算实例
以下示例解释了如何计算一项训练作业的总费用,该作业使用美国区域的 TPU 资源和 Compute Engine 实例。
一家机器学习研究机构通过创建 Compute Engine 实例预配了一台虚拟机,他们选择的是 n1-standard-2 机器类型。他们还创建了一项 TPU 资源,其 Compute Engine 实例和 TPU 资源的累计使用时间都是 10 小时。为了计算该训练作业的总费用,这家机器学习研究机构必须将以下几项相加在一起:
- 所有 Compute Engine 实例的总费用
- 所有 Cloud TPU 资源的总费用
资源 | 每小时每台机器的价格(美元 | ) 机器数量 | 计费小时数 | 各资源总费用 | 训练作业总费用 |
---|---|---|---|---|---|
Compute Engine n1-standard-2 实例 | $0.095| 1| 10| $0.95 | _ | |||
Cloud TPU 资源 | $4.50| 1| 10| $45.00 | _ | |||
$45.95 |
使用抢占式 TPU 的价格示例
在以下示例中,使用的资源和时长与上例相同,但这一次该研究机构决定使用抢占式 TPU 来节省成本。抢占式 TPU 的费用是每小时 $1.35,而非普通 TPU 的每小时 $4.50。
资源 | 每小时每台机器的价格(美元 | ) 机器数量 | 计费小时数 | 各资源总费用 | 训练作业总费用 |
---|---|---|---|---|---|
Compute Engine n1-standard-2 实例 | $0.095 |1| 10| $0.95 | - | |||
抢占式 TPU | $1.35| 1| 10| $13.50 | - | |||
$14.45 |
2 使用步骤
2.1 创建GCP project
点击链接Google Cloud Platform之后会进入这样一个界面:
点击创建项目,输入项目名,等一会项目就会创建成功,有时可能需要刷新一下网页项目才会出现。
2.2 创建Cloud Storage bucket
Cloud Storage 简单来说就是用来存储模型训练数据和训练结果的。官方的解释是它是适用于非结构化对象的一种功能强大且经济有效的存储解决方案,非常适合托管实时网页内容、存储用于分析的数据、归档和备份等各种服务。
注意:要想使用Cloud Storage,需要启用结算功能。
2.2.1 创建存储分区
存储分区用于保存您要在 Cloud Storage中存储的对象(任何类型的文件)。
- 首先在控制台左侧选择 【存储】(如下图示(中英文))就能进入Cloud Storage页面了,
- 之后点击 【创建存储分区】
- 输入storage名即可创建完成,注意名称需要是unique的,否则无法创建成功。
2.2.2 上传和共享对象
要开始使用您的存储分区,只需上传对象并开放其访问权限即可。
2.2.3 清理
在最后一步中,您将删除之前为本教程创建的存储分区和对象。
2.3 打开Cloud Shell,使用ctpu工具
Shell在控制台右上角,如下图示:
输入ctpu print-config
可以查看配置信息。我的输入结果是这样的:
ctpu configuration:
name: hkbuautoml
project: test01-219602
zone: us-central1-b
If you would like to change the configuration for a single command invocation, please use the command line flags.
2.3.1 创建Computer Engine VM和TPU
命令为:ctpu up [optional: --name --zone]
注意: name只能用小写字母和数字组成,大写字母或者其他字符都会报错。
这里我创建了一个名为tputest
的tpu。输入y确认创建。
上面的ctpu up
命令主要做了如下几件事:
- 开启Computer Engine和Cloud TPU服务
- 创建预装有最新稳定版本TensorFlow的Computer Engine VM。其中默认的Zone是
us-central1-b
。 - 使用TensorFlow的相应版本创建Cloud TPU,并将Cloud TPU的名称作为环境变量(
TPU _ NAME
)传递给Computer Engine VM。 - 通过向Cloud TPU服务帐户授予特定的IAM角色(见下图),确保您的Cloud TPU可以从GCP项目中获得所需的资源。
- 执行其他的检查。
- 将您登录到新的Compute Engine VM。
2.3.2 检查是否登录成功
当成功登录VM后,我们可以看到shell prompt已经由username@project
转变成username@tpuname
。
2.3.3 运行一个TensorFlow程序
- 创建代码文件
pico cloud-tpu.py
示例代码如下
import os
import tensorflow as tf
from tensorflow.contrib import tpu
from tensorflow.contrib.cluster_resolver import TPUClusterResolver
def axy_computation(a, x, y):
return a * x + y
inputs = [
3.0,
tf.ones([3, 3], tf.float32),
tf.ones([3, 3], tf.float32),
]
tpu_computation = tpu.rewrite(axy_computation, inputs)
tpu_grpc_url = TPUClusterResolver(
tpu=[os.environ['TPU_NAME']]).get_master()
with tf.Session(tpu_grpc_url) as sess:
sess.run(tpu.initialize_system())
sess.run(tf.global_variables_initializer())
output = sess.run(tpu_computation)
print(output)
sess.run(tpu.shutdown_system())
print('Done!')
运行代码,结果如下:
[array([[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.]], dtype=float32)]
Done!
2.3.4 释放资源
代码跑完后切记要释放资源,否则系统会继续计费。释放资源方法如下:
1. 断开与Computer Engine VM的连接:
(vm)$ exit
成功断开之后shell prompt会变成项目名而不是VM名。
2. 删除Computer Engine VM和Cloud TPU
$ ctpu delete
!!!特别注意:如果在创建VM的时候指定了name,name在删除的时候同业也要指定name。我在删除的时候没有加name,虽然命令行结果显示删除成功,但是后面我在控制台查看资源使用情况,发现VM实例依旧存在。所以最保险的办法是命令输完后,去控制台看看实例是否还存在。
3. 删除Storage
命令为:gsutil rm -r gs://Your-storage-name
通过Colab使用TPU
该方法可以免费使用TPU,但是磁盘空间有限,最多50G,而且默认已使用24G, 所以对于要训练大数据集或者要保存模型的可能还是得使用Google Cloud。
Colab使用方法很简单,只需要使用自己的谷歌账号在Colab上新建一个Jupyter-notebook,在创建好之后将修改>笔记本设置>硬件加速器设置成TPU即可使用。另外可以通过在命令行中输入如下命令(需要加感叹号 !)来查看TPU的ip:
!echo $TPU_NAME
我的输出是
grpc://10.75.136.130:8470
3. AutoML Demo
本次使用的AutoML demo是Google官方提供的代码,即AmoebaNet。Google也有提供如何在TPU上运行该代码的教程:Training AmoebaNet-D on Cloud TPU
3.1 在Colab上运行结果
为检验代码是否可以正常运行,采用的是Google提供的伪造的ImageNet数据集:gs://cloud-tpu-test-datasets/fake_imagenet
。代码是在Colab上运行,环境如下:
- python 2.7
- tensorflow 1.13
最后无法正常运行,报错信息显示是由于保存checkpoints有问题。
3.2 在Google Cloud上运行结果
3.2.1 配置环境
按照如上操作配置好VM,TPU和STORAGE BUCKET后,还需要命令行中配置如下信息:
- TPU_NAME
我的TPU信息如下:
所以TPU_NAME即为对应ip和端口号(8470)
export TPU_NAME=grpc://10.240.1.10:8470
- STORAGE BUCKET
这个的作用是用来保存checkpoints和模型参数,输入如下命令进行配置:
export STORAGE_BUCKET=gs://STORAGE_BUCKET_NAME
STORAGE_BUCKET_NAME需要替换成你自己定义的Name,例如我的是skin100.
最后保存的信息大致如下
3.2.2 代码结构
下面先介绍一下代码的结构,我们所使用的AmoebaNet的代码是在tensorflow库下的一个tpu子库中,即:
tpu
|__benchmarks
|__tools
|__models
|__...
|__common
|__official
|__amoabanet
|__amoebanet.py
|__...
直接运行amoebanet.py会报错,因为其中的代码需要用到common目录下的代码,所以可以把common文件夹复制到amobanet目录下:
cd tpu
cp -r ./models/common ./models/official/amoebanet
之后就可以直接运行代码了,运行环境需要是python2,另外tensorflow的环境已经默认配置好。
cd tpu/models/official/amoebanet
python amoeba_net.py \
--tpu=$TPU_NAME \
--data_dir=gs://cloud-tpu-test-datasets/fake_imagenet \
--model_dir=$STORAGE_BUCKET
- tpu: 注意这里不是输入tpu的名称,而是需要输入tpu的ip和port,上面已经介绍了。
- data_dir使用的是google官方提供的fake ImageNet路径,使用这个可以更快查看代码能否跑通。并且代码中使用的数据集需要是tfrecord格式,具体如何设置可以参照官方教程prepare your dataset
- model_dir: 用来保存模型参数和checkpoints的路径,上面已经介绍了。
3.2.3 运行结果
下面将一些重要的输出结果记录如下:
- Number of flops: 4.7GFLOPS(Forward)
- number of trainable params: 84812042 ≈ 323M
- global_step/sec: 1.85615
- examples/sec: 475.1735
3.3 环境配置问题
参考:https://askubuntu.com/questions/916711/how-can-i-install-cudnn-on-ubuntu-14-04
在Google Cloud上能正常运行TPU代码,但是GPU却不行。而Colab是反过来的。如果是想在本地的GPU上跑的话,环境配置(以v100为例)如下:
- tensorflow-gpu 1.13
- cuda10
- cudnn 7.4.2
cuda10可以通过anaconda一键安装(可搜索"conda cloud cuda"), cuDNN可能会麻烦一点,因为anaconda cloud上提供的最新cuDNN版本是7.3.1,而tensorflow 1.13需要7.4.2版本,所以你可以在cuDNN官网下载。
下载之后的详细步骤如下:
- 首先需要将下载的后缀名为solitairetheme8的文件修改后缀,改成 .ga.tgz,然后用如下命令解压缩
tar -zxvf cudnn_***.ga.tgz
- 解压之后可以得到一个名为cuda的文件夹,里面有两个文件夹(include和lib64)以及一个文件(NVIDIA_SLA_cuDNN_Support.txt)。我的cuda文件夹的路径是
/home/xinhe/cuda
- 进入bashrc文件里配置环境
export CUDNN_HOME=~/cuda
export LD_LIBRARY_PATH=${CUDNN_HOME}/lib64:${LD_LIBRARY_PATH}
export CPLUS_INCLUDE=${CUDNN_HOME}/include:$CPLUS_INCLUDE
source ~/.bashrc
大功告成,只需要输入如下命令即可开始在gpu上运行AmoebaNet代码
python2 amoebe_net.py \
--use_tpu=False \
--data_dir=./dataset/fake_imagenet \
--model_dir=./model_gpu \ # 你可以自己创建这个目录
--image_size=224 \
--train_batch_size=32 \
--val_batch_size=32
3.4 fake ImageNet
其实上面AmoebaNet要在本地GPU上成功地跑起来,还需要用到tfrecord格式的数据,你可以通过使用谷歌云提供的gsutil
工具来下载这些数据(大约70G)。
gsutil的安装教程参考官网:https://cloud.google.com/storage/docs/gsutil_install?hl=zh-cn
gsutil
安装好之后,只需要运行一行代码即可把数据集下载下来:
cd your_project_path
mkdir dataset
gsutil cp -r gs://cloud-tpu-test-datasets/fake_imagenet ./dataset
最后你就可以得到一个名为fake_imagenet的文件夹了,这里面有tfrecord格式的数据。
4. Transformer
4.1 生成训练数据集
在用户的个人VM上,
添加如下环境变量:
export STORAGE_BUCKET=gs://YOUR-BUCKET-NAME
export DATA_DIR=$STORAGE_BUCKET/data
export TMP_DIR=YOUR-TMP-DIRECTORY
其中,
- YOUR-BUCKET-NAME 是用户的 Cloud Storage bucket。
- DATA_DIR 是数据集储存的位置。
- YOUR-TMP_DIRECTORY 是用于存储临时数据的位置。
如果用户向计算引擎VM添加了新磁盘,需要在添加的磁盘上创建一个临时目录。
mkdir /mnt/disks/mnt-dir/t2t_tmp
下载tensor2tensor模型
pip install tensor2tensor
添加tensor2tensor环境变量
export PATH=.local/bin:$PATH
生成WMT14数据集
t2t-datagen --problem=translate_ende_wmt32k_packed --data_dir=$DATA_DIR --tmp_dir=$TMP_DIR
4.2 在单个云TPU上训练英德翻译模型
OUT_DIR=$STORAGE_BUCKET/training/transformer_ende_1
t2t-trainer \
--model=transformer \
--hparams_set=transformer_tpu \
--problem=translate_ende_wmt32k_packed \
--train_steps=10 \
--eval_steps=3 \
--data_dir=$DATA_DIR \
--output_dir=$OUT_DIR \
--use_tpu=True \
--cloud_tpu_name=$TPU_NAME
上面的命令运行10个训练步骤,然后执行3个评估步骤。用户可以(并且应该)通过调整--train_steps
标志来增加训练步骤的数量。在大约40k步之后,翻译通常开始合理。该模型通常在约250k步后收敛到其最高质量。
4.3 退出并删除环境
与VM断开连接
exit
删除VM
ctpu delete [optional: --zone]
检查VM是否已经删除
2019/04/28 16:16:23 WARNING: Setting zone to "us-central1-b"
No instances currently exist.
Compute Engine VM: --
Cloud TPU: --
删除BUCKET
gsutil rm -r gs://YOUR-BUCKET-NAME
4.4 运行结果
结果记录如下:
- Training Cost: 33TFLOPs/Step
- number of trainable params: 61277184*4 ≈ 245M
- global_step/sec: 9.31
- examples/sec: 595.92
更详细的资料可参考官方文档。