在阿里雲容器服務中體驗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的深度學習模型框架處理任務。

在本文中,我們將介紹如何利用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

步驟三:執行以圖搜圖的示例

1.進入示例所在目錄cuml。

2.雙擊cuml_knn.ipynb文件。

3.單擊

說明: 單擊一次執行一個cell,請單擊至示例執行結束,詳細說明請參見示例執行過程

示例執行過程

圖像搜索示例的執行過程分爲三個步驟:處理數據集、提取圖片特徵和搜索相似圖片。本文示例結果中對比了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()方法直接解壓數據集。

1.2. 讀取圖片。 從數據集解壓出的數據爲二進制格式,執行read_all_images(path_to_data)方法加載數據並轉換爲NHWC(batch, height, width, channels)格式,以便用Tensorflow提取圖片特徵。

1.3. 展示圖片。 執行show_image(image)方法隨機展示一張數據集中的圖片。

1.4. 分割數據集。 按照9:1的比例把數據集分爲兩部分,分別用於創建圖片索引庫和搜索圖片。

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

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。

您可以執行model.summary()方法查看模型的網絡結構。

2.2 提取圖片特徵。 對分割得到的兩個圖片數據集執行model.predict()方法提取圖片特徵。

  1. 搜索相似圖片。

3.1 使用cuml KNN搜索相似圖片。 通過k=3設置K值爲3,即查找最相似的3張圖片,您可以依據使用場景自定義K值。

其中,knn_cuml.fit()方法爲創建索引階段,knn_cuml.kneighbors()爲搜索近鄰階段。

KNN向量檢索耗時791 ms。

3.2 使用scikit-learn KNN搜索相似圖片。 通過n_neighbors=3設置K值爲3,通過n_jobs=-1設置使用所有CPU進行近鄰搜索。

說明: ecs.gn5i-c8g1.2xlarge的配置爲8 vCPU。

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,則認爲結果相同。

圖片搜索結果

本示例從1萬張搜索圖片中隨機選擇5張圖片並搜索相似圖片,最終展示出5行4列圖片。

第一列爲搜索圖片,第二列至第四列爲圖片索引庫中的相似圖片,且相似性依次遞減。每張相似圖片的標題爲計算的距離,數值越大相似性越低。

步驟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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章