search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

CICC科普欄目|Docker與深度學習

【摘要】這篇文章介紹了Docker與深度學習結合的例子。Docker的優勢是解決了依賴的問題,方便分發個人工作成果;缺點是不直接支持GPU,需要開發者自己安裝nvidia-docker。Docker提供了一種將Linux Kernel中需要的內容靜態鏈接到你的應用中的方法。Docker容器可以使用宿主機的GPUs,因此我們可以把TensorFlow或者機器學習代碼的任何依賴都鏈接到容器中,這樣其他小夥伴就可以使用你的工作成果了。你可以發布一個可再現的機器學習項目,它幾乎不需要用戶設置,不需要用戶花6小時去下載依賴或者報錯:

# 6 hours of installing dependencies python train.py > ERROR: libobscure.so cannot open shared object

相反,你可以這樣做:

dockrun tensorflow/tensorflow:0.12.1-gpu python train.py TRAINING SUCCESSFUL

這種方法可以直接運行你的train.py腳本,所有的依賴包括GPU支持都幫你準備好了。Docker容器是短暫的,不需要持久化任何數據,你可以把Docker容器想象成1G大的tensorflow.exe,它把你所有的依賴都編譯進去了。

Why

開源軟體因為有難以重現、複雜的依賴網路:不同版本的編譯器、丟失頭文件、錯誤的庫路徑等,所有這些導致在軟體的安裝配置階段浪費你大量的時間。使用Docker時,理論上你只要要讓Docker正確工作,然後你所有的代碼就可以運行了。幸運的是,Docker已經融資1.8億美元,並將一部分投入到docker開發中,轉換成可以工作的軟體。我打算在Linux上用Docker,Mac上的用法應該一樣,除了不支持GPU。

應該怎麼做

針對機器學習的使用場景,你最好把你的代碼發布到GitHub repo上。你的依賴通常表示成一系列Linux命令行,這些命令行能複製粘帖到終端中運行。(譯者註:即依賴放到Dockerfile中)。Docker用一個命令替換第二部分(譯者註:第一部分是把代碼放到GitHub repo上,第二部分是在Docker鏡像中執行命令行,配置你的依賴),該命令將拉取運行代碼所需的正確docker鏡像。你會把所有的依賴集成到3G大(壓縮后)的鏡像中,用戶可以直接下載使用你的鏡像。我們看看Torch

pix2pix

的實現方式:

git clone https://github.com/phillipi/pix2pix.git cd pix2pix bash datasets/download_dataset.sh facades # install dependencies for some time ... # train env \ DATA_ROOT=datasets/facades \ name=facades \ niter=200 \ save_latest_freq=400 \ which_direction=BtoA \ display=0 \ gpu=0 \ cudnn=0 \ th train.lua

儘管訓練腳本的依賴很少(做到這樣很偉大了),但是腳本使用的工具卻有很多依賴,而且這些依賴文檔不全面,組合在一個鏡像中非常複雜繁瑣。

如果你不小心弄亂了依賴,可能會遇到下面的錯誤:

luajit: symbol lookup error: /root/torch/install/lib/lua/5.1/libTHNN.so: undefined symbol: TH_CONVERT_ACCREAL_TO_REAL

Docker提供了一種方法,通過Docker Hub分發二進位鏡像(譯者註:原文是artifact)。

Dockerized

在Linux server上直接安裝docker和nvidia-docker,Docker容器可以訪問GPU,沒有明顯的性能損失。如果你在Mac上你需要安裝

Docker for Mac

,在Mac上使用Docker我還是有很多經驗的。現在你還不能在GPU上運行任何東西,Mac幾乎不再支持CUDA。你可以在CPU模式下測試,它工作良好,只是有點慢。我這裡有一個在Ubuntu 16.04 LTS上安裝Docker的腳本,適用於雲服務提供商:裝好Docker后,運行pix2pix代碼:

sudo docker run --rm --volume /:/host --workdir /host$PWD affinelayer/pix2pix <command>

下面是完整的腳本,多行顯示方便閱讀:

git clone https://github.com/phillipi/pix2pix.git cd pix2pix bash datasets/download_dataset.sh facades sudo docker run \ --rm \ --volume /:/host \ --workdir /host$PWD \ affinelayer/pix2pix \ env \ DATA_ROOT=datasets/facades \ name=facades \ niter=200 \ save_latest_freq=400 \ which_direction=BtoA \ display=0 \ gpu=0 \ cudnn=0 \ th train.lua

它會下載我構建的鏡像(鏡像包含Torch,支持nvidia-docker),大小在3G。運行後會列印debug信息,到這裡已經很棒了。但運行在GPU上更重要,因為pix2pix的架構設計在GPU上可以獲得足夠的訓練速度。

GPU

在GPU上運行只需要把上面命令中的docker鏡像替換成nvidia-dockernvidia-docker不包含在標準Docker中,所以你需要額外的工作。下面的腳本可以在Ubuntu 16.04 LTS上配置nvidia-docker:大概花費5分鐘,而且我已經在AWS和Azure上測試過了。兩者都是NVIDIA K80卡,額定值為2.9 FP32 TFLOPS。nvidia-docker配置好運行:

sudo nvidia-docker run --rm nvidia/cuda nvidia-smi

假設上面的命令正常運行,重新運行pix2pix的腳本:

sudo nvidia-docker run \ --rm \ --volume /:/host \ --workdir /host$PWD \ affinelayer/pix2pix \ env \ DATA_ROOT=datasets/facades \ name=facades \ niter=200 \ save_latest_freq=400 \ which_direction=BtoA \ display=0 \ th train.lua

它使用相同的Docker鏡像,但是支持GPU。

提示

使用Python和TensorFlow時,有許多有用的命令行選項:

--env PYTHONUNBUFFERED=x

這會讓python立即列印輸出,而不是先緩存起來。

--env CUDA_CACHE_PATH=/host/tmp/cuda-cache

這使得你每次啟動Tensorflow時都沒有1分鐘的延遲,它必須從頭重新編譯CUDA內核。

這兩個選項集成到Docker命令行中后:

sudo nvidia-docker run \ --rm \ --volume /:/host \ --workdir /host$PWD \ --env PYTHONUNBUFFERED=x \ --env CUDA_CACHE_PATH=/host/tmp/cuda-cache \ <image> \ <command>

這個命令很長,你可以定義命令別名:

alias dockrun="sudo nvidia-docker run --rm --volume /:/host --workdir /host\$PWD --env PYTHONUNBUFFERED=x --env CUDA_CACHE_PATH=/host/tmp/cuda-cache"

定義別名后運行pix2pix-tensorflow

git clone https://github.com/affinelayer/pix2pix-tensorflow.git cd pix2pix-tensorflow python tools/download-dataset.py facades dockrun affinelayer/pix2pix-tensorflow python pix2pix.py \ --mode train \ --output_dir facades_train \ --max_epochs 200 \ --input_dir facades/train \ --which_direction BtoA除了Tensorflow 0.12.1(當時當前發布的版本)之外沒有別的依賴關係。但是即使如此,第一個GitHub issue是一個用戶使用錯誤版本的Tensorflow導致的。

如何集成

幸運地是,集成到你自己的項目中非常簡單。你先新建空目錄,新建文件Dockerfile。然後構建鏡像:

mkdir docker-build cd docker-build curl -O https://affinelayer.com/docker/Dockerfile sudo docker build --rm --no-cache --tag pix2pix .

構建結束后你就可以查看鏡像了:

sudo docker images pix2pix REPOSITORY TAG IMAGE ID CREATED SIZE pix2pix latest bf5bd6bb35f8 3 seconds ago 11.38 GB

通過docker push把你的鏡像推送到Docker Hub上:

sudo docker tag pix2pix <accountname>/pix2pix sudo docker push <accountname>/pix2pix

Docker新用戶可以先使用我的鏡像。docker提供了不依賴Docker Hub分發鏡像的機制,但是他用起來不是很方便:

# save image to disk, this took about 18 minutes sudo docker save pix2pix | gzip > pix2pix.image.gz # load image from disk, this took about 4 minutes gunzip --stdout pix2pix.image.gz | sudo docker load

再現性

雖然Docker鏡像容易複製,但是從Dockerfile到鏡像的轉換不一定是可複製的。你可以使用下面的命令檢查鏡像的構建歷史記錄:

sudo docker history --no-trunc pix2pix

它不會顯示被添加到鏡像中的所有文件。比如,如果你的Dockerfile包含git clone或者apt-get update,很可能在兩個不同的日子裡構建產生不同的鏡像。

另外,如果docker構建時指定了cpu版本,那麼鏡像在其它機器上很可能不工作。

只要我們分發的是Docker鏡像,那麼它就是可再現的。如果你想通過Dockerfile再現鏡像,如果你不非常小心編寫構建Dockerfile的話,很可能失敗。(譯者註:鏡像構建好后不會變,可再現,但是從Dockerfile構建,很可能因為cpu版本、git clone倉庫更新而不可再現鏡像)

目前還不清楚這些優勢是否值得付出努力,但是如果你的Dockerfile是從頭開始構建的,並且使用--network none選項,大多數情形鏡像是可重現的。

如果鏡像再現很容易,這項技術將會很酷。現在Docker已經取得實質性進展,讓依賴再現成為可能,這是偉大的進步。

譯者說

這篇文章介紹了Docker與深度學習結合的例子。Docker的優勢是解決了依賴的問題,方便分發個人工作成果;缺點是不直接支持GPU,需要開發者自己安裝nvidia-docker。文章最後作者論述了Docker鏡像的可再現問題,總結如下:
  • 分發的是docker鏡像,那麼基本可以保證鏡像的一致性(可再現)。

  • 分發的是dockerfile,dockerfile中存在git clone或者apt update,會因為時間因素導致clone的repo更新導致鏡像不一致。

免費訂閱!

【主編】想了解哪些軍事及學術知識?歡迎留言給我們

C2

如何加入學會

註冊學會會員:

個人會員:

(c2_china),回復「個人會員」獲取入會申請表,按要求填寫申請表即可,如有問題,可在公眾號內進行留言。通過學會審核後方可在線進行支付寶繳納會費。

單位會員:

(c2_china),回復「單位會員」獲取入會申請表,按要求填寫申請表即可,如有問題,可在公眾號內進行留言。通過學會審核後方可繳納會費。

學會近期活動

1. CICC企業會員交流會

會議時間:(具體時間詳見後續通知)

感謝關注



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦