---
# System prepended metadata

title: Docker and TensorFlow Benchmark
tags: [AI]

---

---
title: 'Docker and TensorFlow Benchmark'
disqus: hackmd
---
[TOC]

# <font color='#B8860B'>機器學習(ML) VS. 深度學習(DL)</font>
深度學習(Deep Learning)是機器學習(Machine Learning)的分支
把資料透過多個處理層中的線性or非線性轉換，自動取出特徵(feature)

* 機器學習 --> 特徵是由人力撰寫的演算法產生出來的，  
 需要經過各領域專家對資料進行分析研究，了解資料的特性後，才能產生出有用、效果好的特徵。以上的過程 就是特徵工程(feature engineering)

  機器學習可分為三種型式:
    1. 監督學習（supervised learning）
    2. 非監督學習（unsupervised learning）
    3. 強化學習（reinforcement learning）

* 深度學習 --> 具有自動抽取特徵的能力，也被視為一種特徵學習(feature learning)
可以取代專家的特徵工程所花費的時間。


## <font color='#DAA520'>監督學習 vs. 非監督學習</font>
* 監督學習(Superised Learning)
    所用的數據就是來自這些**被定義（有標籤）的數據**。
  什麼是被定義？ 假設今天我們要讓程式學會如何分辨一張照片上的動物是貓還是狗，那就必須要先有一系列的貓狗圖片，並且每一張都有明確註明哪個是貓哪個是狗，讓程式可以藉由標籤來分類。
* 非監督式學習
    運用的資料**無需被定義**，而數據裡的資料只有特徵沒有標籤。
  以前面的例子來說，這時候演算法僅能根據特徵區分出兩大類型，然而，我們卻無法得知哪一個類型分別為哪一種動物。
* 監督與非監督差異在於收集到的資料是否有<font color='red'>被標籤（Labeled）</font>
也就是，數據是否有被定義

## <font color='#DAA520'>類神經網路</font>
一種模仿生物神經系統的數學模型。在類神經網路中，會有數個階層，每個階層中有數十到數百個神經元。
每個神經元會跟下一層的神經元有特殊的連接關係，使上一層神經元的輸出 
經過權重計算(weight)後傳遞給下一層的神經元。
類神經網路的架構，指的就是階層數量、每層中的神經元數量、各層之間神經元的連接方式、以及活化函數的類型設定等。
這些參數設定都是在使用類神經網路前，由人力設定好，參數的設定會影響類神經網路的效能表現。
類神經網路的學習和訓練過程，就是試著**找到最佳的權重設定**。

## <font color='#DAA520'>Deep Learning的訓練</font>
深度學習和類神經網路的架構，想成是一組可以用來描述資料的函數，
只要找到正確的函數參數，就可以透過這個函數把我們輸入的資料轉化成預測結果(prediction).

深度學習的訓練分為三個步驟：
1. 定義網路架構 (network structure):
先選出一群可能的函數來進行接下來的深度學習訓練過程，定義了適當的網路架構才能透過訓練過程來產生一個有效的深度學習模型(Model)

2. 定義學習目標 (learning target):
用一個數值來描述機器學習或深度學習的模型的好壞．也被稱為適性函數或目標函數．
定義正確的學習目標才能經由訓練的過程來產生符合需求的深度學習模型，
常見的目標函數包括均方根誤差(MSE)、Cross entropy等等

3. 透過數值方法進行訓練 (numerical method)
實際的訓練過程就是使用特定的數值方法，找出定義好的網路架構中最好的權重組合．讓學習目標的指標越小越好的過程．
在ＤＬ中通常使用隨機梯度下降法( Stochastic gradient descent, SGD) 來對權重組合及學習目標進行最佳化．
隨機梯度下降法是在所有權中組合的高維空間中，每次沿著每個維度下降的方向走，經過多次同樣的步驟，就可以找到較好的權重組合．

## <font color='#DAA520'>DL網路架構</font>

1. 卷積神經網路(CNN):
最常見的深度學習網路架構之一
因為網路架構中的卷積層(Convolutional layer)和池化層(Pooling layer)強化了模式辨識及相鄰資料間的關係，使得卷積神經網路的應用在影像、聲音等訊號類型的資料型態能得到很好的效果．
* 卷積層 -> CNN最核心的部分，通常由數十到數百個濾鏡組成，每個濾鏡會對不同的影像模式(image pattern)進行強化，這些濾鏡實際強化的影像模式也是由訓練過程找出來的，所以卷積層可以針對不同的問題產生出不同的濾鏡效果．

* 池化層 -> 類似訊號處理中的降維採樣(Down sampling)，通常會接在卷積層之後．
一般用於影像辨識的CNN，會在處理輸入資料時，有一到三次的卷積層加池化層的處理，之後再接兩層以上的完全連接層，才輸出預測結果。 

<font color='red'>CNN架構的模型例如：AlexNet，VGG，Inception和ResNet</font>


2. 遞歸神經網路(RNN): 
 RNN 神經元內有一個暫存的記憶空間，可以把先前輸入資料產生的狀態儲存在暫存的記憶空間內，之後神經元就可以根據之前的狀態而計算出不同的輸出值．
因爲RNN可以儲存先前的狀態，所以可以處理不同長度的輸入資料，對時間序列、自然語言處理、語音辨識等應用有非常好的效果．
 


# <font color='#B8860B'>Docker介紹</font>
## <font color='#DAA520'>Docker vs Virtual Machine</font>
相對於VM，docker把安裝作業系統整合成一個本地端的作業系統即可。
不用像VM一樣，每安裝一個虛擬機就要再安裝一個作業系統，
可以大大的減少硬碟空間，也就是docker非常輕量化。
![](https://i.imgur.com/pWttro4.png =500x300)


## <font color='#DAA520'>dcoker基本組成</font>
![](https://i.imgur.com/Yb5vXEd.png)
上圖算是統整了 Docker 的重要組成與指令了，先來看看 Docker 中重要的三個最基本的東西：
* image: 這是一個*唯讀*的模板，可用來建立 container，如果有學過物件導向語言，可以想成 image 就是 class、container 是 object 或是 instance。
* container: 這就是我們的主角，是一個獨立、隔離的空間，裡面包括了我們執行一個應用程式所需要的元件。
* Docker registry: 這其實就很像 github，裡面存放了很多 images，公開的像是 Docker Hub，你也可以建立自己私人的 registry。

## <font color='#DAA520'>dcoker基本概念: container</font>

Docker的containter 對比於VM 就是一個一個的虛擬機，
只要有一個Image，就可以建造好幾個container，每個容器都可執行各自不同的作業 

## <font color='#DAA520'>dcoker基本概念: image </font>
Docker Image 採取Layer的方式建立，相同的東西就不會重複建構。
例如: Base Image 可能是Ubuntu的光碟，Layer A 是Nvidia官方建立的cuda環境Image，Layer B 是Tensorflow官方建立的環境Image。Nvidia在建構環境的時候不會從頭到尾自己建立，一定會從某個基礎版本開始往上建構，而這個基礎的版本(Base Image)就是Ubuntu。

![](https://i.imgur.com/ettkzhF.png)

這樣一層一層的建立Image方式，可以節省許多空間。例如: 如果要從官網上拉Tensorflow的Image，但docker已經偵測到底層的Base Image-Ubuntu，所以只會下載電腦中沒有的項目，因此大大提升下載Image的速度

**<font color='red' size='5'>Layer by Layer</font>**

![](https://i.imgur.com/CDh76Vi.png)

## <font color='#DAA520'>docker指令集</font>
>https://docs.docker.com/engine/reference/commandline/run/
>
Docker 常用指令與容器操作教學
>https://blog.gtwang.org/linux/docker-commands-and-container-management-tutorial/

# <font color='#B8860B'>TensorFlow</font>
* TensorFlow是一個機器學習框架，由Google開發的開源機器學習工具
* 支援Python、C++
> https://www.tensorflow.org/install/docker

官方的 TensorFlow Docker 映像檔位於Docker Hub 存放區中: 
> https://hub.docker.com/r/tensorflow/tensorflow/

```
tensorflow: 一種深度學習框架


不需從複雜的神經網路開始寫程式
大部分深度學習框架包含五個核心元件:
1. 張量 (Tensor) 
--> 深度學習框架中最核心的元件，因為所有的運算都是基於張量進行的。
(向量視為一階張量，矩陣就是二階張量)

2. 基於張量的各種操作
--> 例如簡單的矩陣乘法，或是卷積、池化和LSTM等稍稍複雜的運算

3. 計算圖(Computation Graph)
--> 有了張量和基於張量的各種操作後，下一步就是將各種操作整合起來，輸出我們需要的結果

4. 自動微分工具(Automatic Differentation)
5. BLAS、cuBLAS、cuDNN等

常見深度學習模型介紹:
1.卷積神經網路（CNN）-非時序性
2.遞歸神經網路（RNN）-時序性
----------------------------------------
非時序性辨識：針對影像、結構性資料等資料辨識。
時序性辨識：針對語音、翻譯、視頻等資料辨識。
```


# <font color='#B8860B'>SM/SP/CUDA Cores </font>
- SM = Streaming Multiprocessor 多個SP加上其他的資源組成一個SM
- SP = Streaming Processor 最基本的處理單元，也稱為CUDA Core
- TFLOPS = Floating-point operations per second；
縮寫：FLOPS,每秒所執行的浮點運算次數

![](https://i.imgur.com/i3QmjDT.png =350x350)

# <font color='#B8860B'>FP16 / FP32 </font>
* 雙精度(64位元) - Double Precision,DP 
* 單精度(32位元) - Single Precision,SP
* 浮點數(16位元) - Float Point,FP
  FP16: 16位元浮點數 / fp32: 32位元浮點數
* 浮點數 又稱為 半精度 - Half Precision,HP

# <font color='#B8860B'>Run Tensorflow benchmark On Ubuntu </font>

<font color='blue' size=4>1. Install NVIDIA Graphics Driver </font>
[Download runfile from Nvidia website](https://www.nvidia.com/object/unix.html)  

```
sudo apt update
sudo apt install gcc make
sudo chmod +x NVIDIA-Linux-x86_64-418.43.run   #下載的檔案要改成可執行的狀態才可run
sudo ./NVIDIA-Linux-x86_64-418.43.run
完成後重新啟動: sudo reboot
```

<font color='blue' size=4>2. Install Docker & NVIDIA Container Toolkit </font>
Install Docker-ce: 安裝步驟參考 [Docker官網](https://docs.docker.com/engine/install/ubuntu/)

Install NVIDIA Container: 現在統一正名為NVIDIA Container Toolkit，設定方式參考 [ installation guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)
docker-ce 和 nvidia container toolkit安裝完成後， 驗證docker是否可以抓到顯卡
```
＃Test nvidia-smi with the latest official CUDA image
$sudo docker run --gpus all nvidia/cuda:9.0-base nvidia-smi
```


📌 <font color='red' > Docker **19.03** 版本之後 開始支援Nvidia GPU，只需要安装
nvidia-container-toolkit工具包即可，不用再安裝nvidia-docker2那樣複雜配置 </font>
* Versions **earlier than 19.03** require nvidia-docker2 and the ==- -runtime=nvidia== flag.
* On versions **including and after** 19.03, you will use the nvidia-container-toolkit package and the ==- -gpus all== flag


<font color='blue' size=4>3. Running a TensorFlow container  </font>

📌<font color='red'>若要用 tf_cnn_benchmarks，不可下載tf2，因[tf_cnn_benchmarks](https://github.com/tensorflow/benchmarks/tree/master/scripts/tf_cnn_benchmarks)只維護tf1
</font>
* **在[Nvidia NGC](https://www.nvidia.com/en-us/gpu-cloud/containers/)下載TensorFlow image** ([Nvidia NGC TensorFlow release note](https://docs.nvidia.com/deeplearning/frameworks/tensorflow-release-notes/rel_20-08.html#rel_20-08))
    ```docker pull nvcr.io/nvidia/tensorflow:20.10-tf1-py3 ```
* **TensorFlow image下載好後，建立一個container**
```docker run --gpus all -it -v $(pwd):/workspace nvcr.io/nvidia/tensorflow:20.08-tf1-py3 ```

  ( -it = -i_allow input + -t_show termernal ;
     -v : Mount volume )
:::warning
📌<font color='red'>Note </font>
如何使用 Docker 的 Volume 功能，把資料寫入到實體機器上?
1. 在執行 docker run 指令時加上 -v 參數，使得 Container 裡面的檔案路徑Mapping 到實體主機的檔案路徑。
  ``` 例: $ docker run --gpus all -it -v $(pwd):/workspace nvcr.io/nvidia/tensorflow:20.08-tf1-py3```
    其中 $(pwd) 是實體主機的資料夾路徑 Mapping 到 Container 裡面的 /workspace 資料夾路徑。
2. 參考 https://ithelp.ithome.com.tw/articles/10192397
:::

<font color='blue' size=4>4. Running  TensorFlow benchmark in container (3個選擇) </font>
* **1.Tensorflow docker裡面內建nvidia-example 的cnn benchmark**
```python nvidia-examples/cnn/resnet.py --layers=50 --batch_size=96 --precision=fp32 ```

* **2.Tensorflow 官方Benchmark : tf_cnn_benchmarks**

  **Step 1: Clone Benchmark Repository**
    ```git clone https://github.com/tensorflow/benchmarks.git```

  **Step 2: Run Benchmark**
    ```
    cd benchmarks/scripts/tf_cnn_benchmarks/
    ```
    To run ResNet50 with synthetic data without distortions with a single GPU, run 
   ```
   python tf_cnn_benchmarks.py --num_gpus=1 --batch_size=32 --model=resnet50 --variable_update=parameter_server```
:::warning
📌<font color='red'>Note </font>
    tf_cnn_benchmark 預設值: <font color='red'>****batch_size=64 and FP32****</font>
    若要跑fp16:
    ```python tf_cnn_benchmarks.py --num_gpus=1 --batch_size=32 --use_fp16=True --model=resnet50 --variable_update=parameter_server
    ```  

<font color='red'>※ 若是用RTX2080以下的卡，要加上 ==- -allow_growth=1==, 不然會有錯誤訊息</font>
```python tf_cnn_benchmarks.py --num_gpus=1 --batch_size=32 --model=resnet50 --variable_update=parameter_server --allow_growth=1``` 


> https://hackmd.io/@chweng/r1Ec8EXWV?type=view#1X-GeForce-RTX-2080-Ti-FP32

> https://www.principledtechnologies.com/ibm/cloud-services-tensorflow-science-0419.pdf

:::
* **3. [LambdaBenchmark](https://lambdalabs.com/blog/titan-v-deep-learning-benchmarks/)**
  
    **Step 1: Clone Benchmark Repository**
    ```git clone https://github.com/lambdal/lambda-tensorflow-benchmark.git --recursive```

    **Step 2: Run Benchmark**
    ```
    cd lambda-tensorflow-benchmark
    ./benchmark.sh gpu_index num_iterations
    ```
    <font color='red'> default : gpu_index=0 && num_iterations=10</font>
    ✔ ./benchmark.sh 跑完約2.5 hr


    ✔ ./benchmark.sh 0 1 跑一次約 30 mins



# RTX 20 vs RTX 30 serise lambda-tensorflow-benchmark
#### <font color='blue'>Software</font>
* Ubuntu 20.04
* Nvidia-NGC 20.10-tf1-py3
* <font color='#FF5809'>NGC-20.10 include:
Tensorflow 1.15.4   
NVIDIA CUDA 11.1.0      
NVIDIA cuDNN 8.0.4 </font>

#### <font color='blue'>Hardware</font>
* i7-7900X-RTX 2080Ti with Driver version 450.80 
* i7-7900X-RTX 3080/3090  with Driver version 455.23 

📌<font color='#FF5809'>因為當下的長期支援板是450.80，不支援30系列。所以30系列driver用455.23</font>
#### <font color='blue'>Methods </font>
* **Step 1: Start docker images**
```docker run --gpus all -it -v $(pwd):/workspace```
* **Step 2: Clone Benchmark Repository**
```git clone https://github.com/lambdal/lambda-tensorflow-benchmark.git --recursive```
* **Step 3: Run Benchmark**
```
    cd lambda-tensorflow-benchmark
    ./benchmark.sh 
```
#### <font color='blue'>Results </font>
* **FP16: # Images Processed Per Sec During TensorFlow Training**
   <font color='#FF5809'>( RTX 3080 / RTX 3090 vs. RTX 2080 Ti)</font>
    * 11% / 31% faster on AlexNet
    * -55% / -46% faster on Inception v3
    * 22% / 39% faster on Inception v4
    * 19% / 44% faster on ResNet-50
    * 18% / 41% faster on ResNet-152
    * 15% / 43% faster on SSD300
    * -10% / 10% faster on VGG16

| Model / GPU  | RTX 2080 Ti | RTX 3080 | RTX 3090 |
| ------------ | ----------- | -------- | -------- |
| AlexNet      | 587.96      | 6563.93  | 7713.12  |
| Inception-v3 | 465.2       | 211.25   | 251.03   |
| Inception-v4 | 162.67      | 197.71   | 226.67   |
| ResNet-50    | 663.21      | 791.48   | 957.73   |
| ResNet-152   | 244.1       | 288      | 344.48   |
| SSD300       | 260.38      | 298.17   | 373.48   |
| VGG16        | 274.51      | 246.95   | 301.22   |

* **FP32: # Images Processed Per Sec During TensorFlow Training**
    <font color='#FF5809'>( RTX 3080 / RTX 3090 vs. RTX 2080 Ti)</font>
    * 11% / 31% faster on AlexNet
    * -55% / -46% faster on Inception v3
    * 22% / 39% faster on Inception v4
    * 19% / 44% faster on ResNet-50
    * 18% / 41% faster on ResNet-152
    * 15% / 43% faster on SSD300
    * -10% / 10% faster on VGG16
    


| Model / GPU  | RTX 2080 Ti | RTX 3080 | RTX 3090 |
| ------------ | ----------- | -------- | -------- |
| AlexNet      | 3539.28     | 4910.2   | 5539.71  |
| Inception-v3 | 205.17      | 278.03   | 327.54   |
| Inception-v4 | 83.95       | 106.1    | 119.67   |
| ResNet-50    | 302.96      | 404.08   | 488.51   |
| ResNet-152   | 116.42      | 142.62   | 164.08   |
| SSD300       | 158.66      | 210.01   | 253.33   |
| VGG16        | 188.86      | 265.47   | 318.82   |






https://hackmd.io/@chweng/r1Ec8EXWV?type=view#1X-GeForce-RTX-2080-Ti-FP32

https://www.principledtechnologies.com/ibm/cloud-services-tensorflow-science-0419.pdf



###### tags: `AI` 