---
# System prepended metadata

title: CPE 多執行緒測試說明(Python Flask)
tags: [flask]

---

# 多執行緒測試說明(Python Flask)
## 測試方向
1. 使用 CPE 內的高通 AI-Chip 執行推論
2. 測試高通 AI-Chip 同時多執行緒的推論速度
3. 比較與 Nvidia-RTX4060 的推論速度

## 測試模型種類
1. LEDA _ AutoEncoder
2. LEDA _ Classification
3. YOLOv8 _ Classification
4. YOLOv8 _ ObjectDetection
5. YOLOv8 _ Segmentation

## 測試設備
1. CPE & 高通 AI-Chip
2. Nvidia - RTX4060

## 多執行緒測試方法（Python Flask）
### 方法與步驟
* 原本推論測試程式為 Python，要達成同時多執行緒執行有一定難度，無法快速測試出結果。
* Python Flask 是一種輕量級 Web 應用架構，提供從 URL 到 Python 函數之間得連結。可以拿來寫網頁應用或是 API。
* 由於此次測試重點在於推論時間，其引用的模型與測試集皆相同，我們只須考慮如何讓多個模型同時跑起來即可。用到的就是 URL 與 Python 函數的串接，將原本程式改成 Flask server，再撰寫一個 client 同時呼叫多個函式即可達成多線程執行的目的。

### 安裝 Python Flask
#### python3 & pip 環境版本確認
* 如果系统中只安装了Python2 --> 只能使用pip。
* 如果系统中只安装了Python3 --> 可以使用pip也可以使用python3，二者是相同的。
* 如果系统中同时安装了Python2和Python3 --> pip默認给Python2用。
* sudo的python的環境與anaconda不同，須注意自己在哪個環境下。
```
sudo python3 -V       # 檢查 Python3 版本
sudo pip -V           # 檢查 pip 環境
sudo python3 -m pip install    # 可以確保pip install是安裝到正確的python3路徑 
```

#### 安裝 Python Flask
```
sudo python3 -m pip install flask    # 安裝flask
```
如果遇到有關blinker相關錯誤，請重新安裝blinker。
```
ERROR: Cannot uninstall 'blinker'. It is a distutils installed project and thus we cannot accurately determine which files belong to it which would lead to only a partial uninstall.

sudo -H pip install --ignore-installed -U blinker    # 安裝blinker
```

#### 在程式中啟動 Flask
```python=
from flask import Flask

app = Flask(__name__)    # 初始化Flask

# 告訴 Flask，哪個 URL 應該觸發我們的函式。
# 斜線代表的就是根目錄，可以疊加。
@app.route("/")

# 例如: 新增一個 /hello 的位址
# 當收到 URL (http://127.0.0.1:5000/hello) 會觸發hello function
@app.route("/hello")
def hello():
    return "Hello, World!"

if __name__ == '__main__':
    app.run(debug=True, port=5000)   # 啟動 Flask 應用程式

```

#### 將原本推論腳本改成 API 形式（以 leda_ae.py 為例） 
1. 將原本main底下的程式碼改成某個flask的route
```python=
@app.route('/leda_ae', methods=['POST'])
def init():    
    parser = argparse.ArgumentParser()
    parser.add_argument("--model", required=True, help="your fp16 model dir.")
    parser.add_argument(
        "--img", default=str("images/bus.jpg"), help="Path to input image."
    )
    parser.add_argument(
        "--count",
        type=int,
        default=3,
        help="Count to run. -1 for loop",
    )
    args = parser.parse_args()
    run(args.model, args.img, args.count)
```
2. 將main改成啟動flask
```python=
if __name__ == '__main__':
    app.run(debug=True, port=5000)   # 啟動 Flask 應用程式
``` 

3. 撰寫另一個python client的程式
```python=
import requests

if __name__ == '__main__':

    url = "http://127.0.0.1:8000/seg_v8"
    
    response = requests.post(url)
    print(response)
```

## CPE測試步驟
1. 在終端機輸入指令，要注意自己的檔案位置，會導致指令些許不同。
   `sudo python3 flask/leda_ae_flask_5000.py --model model/leda_ae`
![Screenshot from 2024-05-02 11-23-28](https://hackmd.io/_uploads/B1E8vKxfR.png)

2. 確認自己的url，並修改python client程式。
3. 再開一個終端機執行client端的程式。`sudo python3 flask/flask_test.py`

4. 如果有對正確的url發送請求，server端程式底下對應的函式會開始執行。
![Screenshot from 2024-05-02 11-30-58](https://hackmd.io/_uploads/HJ0bFYgz0.png)

5. 高通 Ai-chip 多開時會有調用問題，如下圖
![1714462994086](https://hackmd.io/_uploads/BJ62YtxfR.png)

## CUDA測試方法（RTX-4060）
### 利用GPU推論方法
#### 於 python 內安裝 onnxruntime-gpu
1. 依cuda, cudnn下載對應onnxruntime-gpu版本
版本對照：https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html
```
pip install onnxruntime-gpu==1.16.0
```
2. 於 cmd 依序輸入以下指令測試
```
python
import onnxruntime
onnxruntime.get_device()
onnxruntime.get_available_providers()
```
如果輸出結果為以下則代表安裝成功
```
'GPU'
['TensorrtExecutionProvider', 'CUDAExecutionProvider', 'CPUExecutionProvider']
```
#### 程式測試

1. 下載LEDA提供的資源庫(.zip)
連結：http://leda-office.synology.me:30000/LEDA/qualcomm-ai-chip/src/branch/onnxruntime
2. 依本地環境補足缺少的資源庫 
```
pip install (缺少的資源庫 EX:onnx)
```
3. 依照 README 執行指令即可

## 測試常見問題

### 常見問題1__找不到 zlibwapi.dll 檔案位置

程式報錯如下：
```
use CUDAExecutionProvider
Could not locate zlibwapi.dll. Please make sure it is in your library path!
```
這是因為 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.7\bin 內缺少了zlibwapi.dll導致

*註：網路上會建議你去Nvidia官網下載檔案，但現在官網已經不提供下載了*

* STEP1：在 C:\Program Files 搜尋 zlibwapi.dll
* STEP2：找到檔案位置後，複製一份至 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.x\bin 資料夾內

重新整理後，再執行一次程式應該就不會報錯了。

### 常見問題2__無法用cuda執行程式

## 測試結果
### CPE(單執行/雙執行/九執行) 
***YOLO_OD吃的資源比較多，一次請求吃兩個處理器，所以最多只能測4線程**
| 模型名稱                 | 推論秒數（ms）      | 前後處理秒數（ms）    | 推論FPS    |
| ------------------------ | ----------------- | ------------------ | --------- |
| LEDA _ AutoEncoder     | 2.08  / 2.17 / 3.86   | 0.72  / 0.80 / 2.9     | 357 / 710 / 1335|
| LEDA _ Classification    | 0.89  / 0.95 / 2.93 | 0.44  / 0.52 / 1.55       | 751 / 1354 / 2031|
| YOLOv8 _ Classification  | 1.59  / 1.77 / 4.56  | 0.52  / 0.67 / 1.57       | 474 / 818 / 1472|
| YOLOv8 _ ObjectDetection | 19.73 / 21.9 / 25.4   | 5.23  / 9.65 /11.5       | 40  / 63 / 108|
| YOLOv8 _ Segmentation    | 38.13 / 50.28 / 102.1 | 28.58 / 41.85 / 158.72       | 15  / 22 / 34.5 |

### RTX4060_Laptop(單執行/雙執行/多執行(同時發送10個請求)
| 模型名稱                   | 推論秒數（ms）          | 前後處理秒數（ms）        | 推論FPS          |
| ------------------------ | --------------------- | ---------------------- | --------------- |
| LEDA _ AutoEncoder       | 1.45  / 1.45 / 2.30   | 0.90  / 1.00 / 2.49    | 425 / 816 / 2090 |
| LEDA _ Classification    | 1.41  / 1.27 / 2.37   | 0.11  / 0.16 / 0.43    | 657 / 1398 / 3590 |
| YOLOv8 _ Classification  | 3.74  / 3.40 / 7.24   | 14.79 / 15.45 / 29.3   | 53 / 106 / 270    |
| YOLOv8 _ ObjectDetection | 10.27 / 11.83 / 40.61 | 20.12 / 21.59 / 45.84  | 32  / 60 / 110   |
| YOLOv8 _ Segmentation    | 12.81 / 21.35 / 40.79 | 62.14 / 56.66 / 105.71 | 13  / 24 / 60   |

## 結論
### 高通 AI-Chip 硬體調用極限
運算單元的調用問題，因為這些推論都是比較簡單的，照理來說是不太可能佔用太多資源，結論比較像是只有兩個運算單元可以調用，就算他們彼此都還有多餘算力。進一步確認要想辦法找到可以知道AI chip的資源佔用監控，就可以更加確定這個結論是否正確。(YOLOv8-OD 一次會調用兩個晶片？)

### LEDA 自主研發模型
不論是在 NVIDIA 或是 AI-Chip，與 YOLOv8 比較推論速度有明顯的提升。

### 高通 AI-Chip vs NVIDIA
高通優勢在cls模型下速度優於nv，但硬體資源調用還是nv佔優勢，在多執行緒的情況下高通無法完全釋放他的算力。
