Docker與深度學習

pingguo 7年前發布 | 12K 次閱讀 Docker 深度學習

這篇文章介紹了Docker與深度學習結合的例子。Docker的優勢是解決了依賴的問題,方便分發個人工作成果;缺點是不直接支持GPU,需要開發者自己安裝nvidia-docker。

Docker提供了一種將Linux Kernel中需要的內容靜態鏈接到你的應用中的方法。Docker容器可以使用宿主機的GPUs,因此我們可以把TensorFlow或者機器學習代碼的任何依賴都鏈接到

容器中,這樣其他小伙伴就可以使用你的工作成果了。

你可以發布一個可再現的機器學習項目,它幾乎不需要用戶設置,不需要用戶花6小時去下載依賴或者報錯:

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的腳本,適用于云服務提供商:

curl -fsSL https://affinelayer.com/docker/setup-docker.py | sudo python3

裝好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-docker 。

nvidia-docker 不包含在標準Docker中,所以你需要額外的工作。下面的腳本可以在Ubuntu 16.04 LTS上配置nvidia-docker:

curl -fsSL https://affinelayer.com/docker/setup-nvidia-docker.py | sudo python3

大概花費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=&quot;sudo nvidia-docker run --rm --volume /:/host --workdir /host\$PWD --env PYTHONUNBUFFERED=x --env CUDA_CACHE_PATH=/host/tmp/cuda-cache&quot;

定義別名后運行 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

pix2pix-tensorflow 除了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更新導致鏡像不一致。

 

 

來自:http://dockone.io/article/2127

 

 本文由用戶 pingguo 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!