在阿里云容器服务中体验 RAPIDS 加速数据科学

阅读数:1654 2019 年 12 月 15 日 10:00

在阿里云容器服务中体验RAPIDS加速数据科学

摘要

算法、数据和算力称为人工智能的三大要素,如果没有算力的支撑,人工智能难以落地。而 Nvidia GPU 的强劲算力是 AI 模型训练加速的首选,但是它的价格也确实不菲。如何能够简单,有效同时低成本的使用 Nvidia GPU 的算力,使用阿里云容器服务 +ECI+Arena 的方案是一个可以参考的选项。

而一谈起 Nvidia GPU,大家首先会想到的就是深度学习,传统的机器学习和数据分析的方法对 GPU 的利用却很少,实际上 Nvidia 有一个非常优秀的项目 RAPIDS,全称 Real-time Acceleration Platform for Integrated Data Science,是 NVIDIA 针对数据科学和机器学习推出的 GPU 加速库。更多 RAPIDS 信息请参见官方网站。这是一个致力于将 GPU 加速带给传统算法的项目,并且提供了与 Pandas 和 scikit-learn 一致的用法和体验。实际上 RAPIDS 有三个模块:cuDF 相当于 Pandas,cuML 相当于 scikit-learn,cuGraph 则是处理图数据的。由于它的兼容性很好,我们可以把 RAPIDS 与深度学习框架结合,用 cuDF 来利用 GPU 加速处理数据,然后使用 TensorFlow 和 PyTorch 的深度学习模型框架处理任务。

在阿里云容器服务中体验RAPIDS加速数据科学

在本文中,我们将介绍如何利用 TensorFlow 和 Rapids 实现在阿里云容器服务上以图搜图的功能;同时通过 ECI 实现 GPU 资源的使用即申请,秒级的 GPU 资源准备速度,完成即释放,用户无需提前准备 GPU 实例;而站在使用者的角度,他并不需要和 Kubernetes 的基础设施打交道,通过 arena 的命令行,就可以实现包含 GPU 的 RAPIDS 环境的构建和运行,并且完成对 GPU 基础设施的管理。

执行步骤

步骤 1:准备集群

准备托管 k8s 的集群,所谓托管 k8s 的集群就是这个 k8s 的管控节点由阿里云承担资源和运维成本,并且创建了虚拟的 Kubelet 节点

需要您已创建好容器服务 Kubernetes 集群。 您可以选择管版的 Kubernetes 集群。

由于需要运行系统组件容器,节点中至少有一个 Worker 节点。

  1. 安装虚拟节点,具体可以参考虚拟节点
  2. 配置 virtual-kubelet-autoscaler,当集群内的 GPU 资源不足的时候,通过 virtual-kubelet-autoscaler 将弹出使用 GPU 的 ECI 实例。具体参考文档

步骤 2:从无到有运行 arena 创建 RAPIDS 服务

1. 安装 arena

复制代码
$ wget http://kubeflow.oss-cn-beijing.aliyuncs.com/arena-installer-0.3.0-b556a36-linux-amd64.tar.gz
$ tar -xvf arena*.tar.gz
$ cd arena-installer
$ ./install.sh

2. 先运行一下 arena 命令查看集群的 GPU 资源, 可以看到在该用户集群下,有一个真实节点并没有包含 GPU 资源,同时存在了一个虚拟节点,该节点并不真实存在,无需付费,同时它提供了无限的 GPU 资源可以扩展。

复制代码
$ arena top node
arena top node
NAME IPADDRESS ROLE STATUS GPU(Total) GPU(Allocated)
cn-shanghai.192.168.1.248 192.168.1.248 <none> ready 0 0
virtual-kubelet 172.20.2.18 agent ready 1000 0
-----------------------------------------------------------------------------------------
Allocated/Total GPUs In Cluster:
0/1000 (0%)

3. 再提交 rapids 任务前,我们需要做一些准备。准备的目的是加速创建过程和简化访问操作。

3.1. 设置访问方式。将访问方式设置为 LoadBalancer(该方法只是为了示例简单,并不推荐您在生产环境开放外网 ip 方访问)

复制代码
$ find /charts/ -name "*.yaml" | xargs sed -i "s/NodePort/LoadBalancer/g"

3.2. 加速启动速度

3.2.1.GPU 的容器镜像通常很大,以本实验要使用的 rapids 容器镜像为例,它的容量为 14.7GB. 通常启动时间会在 10 分钟左右。而通过镜像缓存的能力可以将这个从无到有的过程缩短到 20s 左右。

复制代码
docker images | grep rapids
registry.cn-shanghai.aliyuncs.com/tensorflow-samples/rapids-samples 0.8.2-cuda10.0-runtime-ubuntu16.04 4597a0334d41 12 days ago 14.7GB

3.2.2. 而在 serverless kubernetes 中,你只需要创建一个 ImageCache CRD,就可以直接使用镜像缓存的能力。

复制代码
$ cat > imagecache.yaml << EOF
apiVersion: eci.alibabacloud.com/v1
kind: ImageCache
metadata:
name: imagecache-rapids
spec:
images:
- registry.cn-shanghai.aliyuncs.com/tensorflow-samples/rapids-samples:0.8.2-cuda10.0-runtime-ubuntu16.04
imageCacheSize:
50
EOF
$ kubectl create -f imagecache.yaml

3.2.3. 提交后稍等片刻。查看 ImageCache 状态,其中 CACHID 可以做后面提交任务时指定的 snapshot-id

复制代码
$ kubectl get imagecache
NAME AGE CACHEID PHASE PROGRESS
imagecache-rapids 3d9h imc-uf6dxdji7txxxxx Ready 100%

具体操作可以参考文档

4. 提交 rapids 的开发环境

复制代码
$ arena serve custom \
--name=rapids \
--selector=type=virtual-kubelet \
--toleration=all \
--annotation=k8s.aliyun.com/eci-image-snapshot-id=imc-uf6dxdji7txxxxx \
--annotation=k8s.aliyun.com/eci-instance-type=ecs.gn5i-c8g1.2xlarge \
--gpus=1 \
-e=PASSWORD=mypassw0rd \
--restful-port=80 \
--image=registry.cn-shanghai.aliyuncs.com/tensorflow-samples/rapids-samples:0.8.2-cuda10.0-runtime-ubuntu16.04
configmap/rapids-201912011815-custom-serving created
configmap/rapids-201912011815-custom-serving labeled
service/rapids-201912011815 created
deployment.extensions/rapids-201912011815-custom-serving created

--selector=type=virtual-kubelet表示通过 Virtual Node 启动 Pod
--annotation=k8s.aliyun.com/eci-instance-type=ecs.gn5i-c8g1.2xlarge表示指定使用 ECI 的实例类型,ecs.gn5i-c8g1.2xlarge 代表阿里云 P4 机型。具体规格可以查看文档
--annotation=k8s.aliyun.com/eci-image-snapshot-id=imc-uf6dxdji7txxxxx指定 3.2.3 步中的 CACHEID
-e=PASSWORD=mypassw0rd就是通过环境变量 PASSWORD 设置访问 RAPIDS notebook
--gpus=1表示申请的 GPU 数目

4. 查看访问地址,这里是 ENDPOINT_ADDRESS 和 PORTS 的组合, 在本示例中它是106.15.173.2:80。同时发现该任务在32 秒的时候就可以变成 Running 状态

复制代码
$ arena serve list
NAME TYPE VERSION DESIRED AVAILABLE ENDPOINT_ADDRESS PORTS
rapids CUSTOM 201911181827 1 1 105.13.58.3 restful:80
$ arena serve get rapids
arena serve get rapids
NAME: rapids
NAMESPACE: default
VERSION: 201912011815
DESIRED: 1
AVAILABLE: 1
SERVING TYPE: CUSTOM
ENDPOINT ADDRESS: 106.15.173.2
ENDPOINT PORTS: restful:80
AGE: 32s
INSTANCE STATUS AGE READY RESTARTS NODE
rapids-201912011815-custom-serving-6b54d5cd-swcwz Running 32s 1/1 0 N/A

5. 再次查看集群的 GPU 使用情况,发现已经有一个 GPU 资源被占用了

复制代码
$ arena top node
NAME IPADDRESS ROLE STATUS GPU(Total) GPU(Allocated)
cn-shanghai.192.168.1.248 192.168.1.248 <none> ready 0 0
virtual-kubelet 172.20.2.20 agent ready 1000 1
-----------------------------------------------------------------------------------------
Allocated/Total GPUs In Cluster:
1/1000 (0%)

6. 如果想查询是哪个 Pod 占用了这个 GPU, 可以在原有命令中加一个 -d 就可以看到具体的 Pod 名称。

复制代码
$ arena top node -d
NAME: cn-shanghai.192.168.1.248
IPADDRESS: 192.168.1.248
ROLE: <none>
Total GPUs In Node cn-shanghai.192.168.1.248: 0
Allocated GPUs In Node cn-shanghai.192.168.1.248: 0 (0%)
-----------------------------------------------------------------------------------------
NAME: virtual-kubelet
IPADDRESS: 172.20.2.20
ROLE: agent
NAMESPACE NAME GPU REQUESTS
default rapids-201912011815-custom-serving-6b54d5cd-swcwz 1
Total GPUs In Node virtual-kubelet: 1000
Allocated GPUs In Node virtual-kubelet: 1 (0%)
-----------------------------------------------------------------------------------------
Allocated/Total GPUs In Cluster: 1/1000 (0%)

7. 根据步骤 4 中的访问地址和端口,打开本地浏览器。输入http://{ENDPOINT ADDRESS}:{ENDPOINT PORT},在本例子中是http://105.13.58.3:80

说明: 推荐使用 Chrome 浏览器。

8. 输入启动命令中设置的密码,然后单击Log in。 在本例子中,密码为mypassw0rd

在阿里云容器服务中体验RAPIDS加速数据科学

步骤三:执行以图搜图的示例

1. 进入示例所在目录 cuml。

2. 双击 cuml_knn.ipynb 文件。

3. 单击在阿里云容器服务中体验RAPIDS加速数据科学

说明: 单击一次执行一个 cell,请单击至示例执行结束,详细说明请参见示例执行过程

在阿里云容器服务中体验RAPIDS加速数据科学

示例执行过程

图像搜索示例的执行过程分为三个步骤:处理数据集、提取图片特征和搜索相似图片。本文示例结果中对比了 GPU 加速的 RAPIDS cuml KNN 与 CPU 实现的 scikit-learn KNN 的性能。

1. 处理数据集。

1.1 下载和解压数据集。 本文示例中使用了 STL-10 数据集,该数据集中包含 10 万张未打标的图片,图片的尺寸均为:96 x 96 x 3, 您可以使用其他数据集,为便于提取图片特征,请确保数据集中图片的尺寸相同。

本文示例提供了download_and_extract(data_dir)方法供您下载和解压 STL-10 数据集。RAPIDS 镜像中已经将数据集下载到./data 目录,您可以执行download_and_extract()方法直接解压数据集。

在阿里云容器服务中体验RAPIDS加速数据科学

1.2. 读取图片。 从数据集解压出的数据为二进制格式,执行read_all_images(path_to_data)方法加载数据并转换为 NHWC(batch, height, width, channels)格式,以便用 Tensorflow 提取图片特征。

在阿里云容器服务中体验RAPIDS加速数据科学

1.3. 展示图片。 执行show_image(image)方法随机展示一张数据集中的图片。

在阿里云容器服务中体验RAPIDS加速数据科学

1.4. 分割数据集。 按照 9:1 的比例把数据集分为两部分,分别用于创建图片索引库和搜索图片。

在阿里云容器服务中体验RAPIDS加速数据科学

2. 提取图片特征。 使用开源框架 Tensorflow 和 Keras 提取图片特征,其中模型为基于 ImageNet 数据集的 ResNet50(notop)预训练模型。

2.1 设定 Tensorflow 参数。 Tensorflow 默认使用所有 GPU 显存,我们需要留出部分 GPU 显存供 cuML 使用。您可以选择一种方法设置 GPU 显存参数:

  • 方法 1:依据运行需求进行显存分配。
复制代码
config.gpu_options.allow_growth = True
  • 方法 2:设定可以使用的 GPU 显存比例。本示例中使用方法 2,并且 GPU 显存比例默认设置为 0.3,即 Tensorflow 可以使用整块 GPU 显存的 30%,您可以依据应用场景修改比例。
复制代码
config.gpu_options.per_process_gpu_memory_fraction = 0.3

在阿里云容器服务中体验RAPIDS加速数据科学

2.2 下载 ResNet50(notop)预训练模型。 连接公网下载模型(大小约 91M),目前该模型已经被保存到 /root/.keras/models/ 目录。

参数名称 说明
weights 取值范围:
- None:随机初始化权重值。
- imagenet:权重值的初始值设置为通过 ImageNet 预训练过的模型的权重值。
本示例中设置为 imagenet。
include_top 取值范围:
- True:包含整个 ResNet50 网络结构的最后一个全链接层。
- False:不包含整个 ResNet50 网络结构的最后一个全链接层。
本示例中,使用神经网络模型 ResNet50 的主要目的是提取图片特征而非分类图片,因此设置为 False。
input_shape 可选参数,用于设置图片的输入 shape,仅在 include_top 设置为 False 时生效。
您必须为图片设置 3 个 inputs channels,且宽和高不应低于 32。此处设为 (96, 96, 3)。
pooling 在 include_top 设置为 False 时,您需要设置池化层模式,取值范围:
- None:输出为 4D tensor。
- avg:平均池化,输出为 2D tensor。
- max:最大池化,输出为 2D tensor。 本示例中设置为 max。

在阿里云容器服务中体验RAPIDS加速数据科学

您可以执行model.summary()方法查看模型的网络结构。

在阿里云容器服务中体验RAPIDS加速数据科学

2.2 提取图片特征。 对分割得到的两个图片数据集执行model.predict()方法提取图片特征。

在阿里云容器服务中体验RAPIDS加速数据科学

  1. 搜索相似图片。

3.1 使用 cuml KNN 搜索相似图片。 通过k=3设置 K 值为 3,即查找最相似的 3 张图片,您可以依据使用场景自定义 K 值。

其中,knn_cuml.fit()方法为创建索引阶段,knn_cuml.kneighbors()为搜索近邻阶段。

在阿里云容器服务中体验RAPIDS加速数据科学

KNN 向量检索耗时 791 ms。

3.2 使用 scikit-learn KNN 搜索相似图片。 通过n_neighbors=3设置 K 值为 3,通过n_jobs=-1设置使用所有 CPU 进行近邻搜索。

说明: ecs.gn5i-c8g1.2xlarge 的配置为 8 vCPU。

在阿里云容器服务中体验RAPIDS加速数据科学

KNN 向量检索耗时 7 分 34 秒。

3.3 对比 cuml KNN 和 scikit-learn KNN 的搜索结果。 对比两种方式的 KNN 向量检索速度,使用 GPU 加速的 cuml KNN 耗时 791 ms,使用 CPU 的 scikit-learn KNN 耗时 7min 34s。前者为后者的近 600 倍。

验证两种方式的输出结果是否相同,输出结果为两个数组:

  • distance:最小的 K 个距离值。本示例中搜索了 10000 张图片,K 值为 3,因此distance.shape=(10000,3)

  • indices:对应的图片索引。indices.shape=(10000, 3)

    由于本示例所用数据集中存在重复图片,容易出现图片相同但索引不同的情况,因此使用 distances,不使用 indices 对比结果。考虑到计算误差,如果两种方法得出的 10000 张图片中的 3 个最小距离值误差都小于 1,则认为结果相同。

在阿里云容器服务中体验RAPIDS加速数据科学

图片搜索结果

本示例从 1 万张搜索图片中随机选择 5 张图片并搜索相似图片,最终展示出 5 行 4 列图片。

第一列为搜索图片,第二列至第四列为图片索引库中的相似图片,且相似性依次递减。每张相似图片的标题为计算的距离,数值越大相似性越低。

在阿里云容器服务中体验RAPIDS加速数据科学

步骤 4:清理工作

复制代码
$ arena serve delete rapids
service "rapids-201912011815" deleted
deployment.extensions "rapids-201912011815-custom-serving" deleted
configmap "rapids-201912011815-custom-serving" deleted
INFO[0000] The Serving job rapids with version 201912011815 has been deleted successfully

总结

本文介绍通过 Arena + 阿里云 Serverless Kubernetes 快速,简单,低成本的使用 RAPIDS 加速数据科学。

本文转载自云栖社区。

原文链接

https://yq.aliyun.com/articles/735438?spm=a2c4e.11153959.0.0.715cd55arelKky

评论

发布
用户头像
好棒

2019 年 12 月 17 日 14:55
回复
很有用的内容

2019 年 12 月 17 日 14:55
回复
郭瑞 回复 郭瑞
666
2019 年 12 月 17 日 14:55
回复
没有更多了