1.背景
前段時間,使用 python + unicorn + xgboost + pytorch 寫了一個機器學習訓練平臺的后端服務,
根據公司開發需要,需具備兩種需求:1. 可以本地加載使用;2.支持web服務,
2. 使用本地加載使用
2.1 問題
針對第一種方式,為避免客戶安裝使用python 環境,因此將項目打包成.exe ,使用pyinstaller 進行打包,但
1.遇到體積大的問題,于是根據網上建議,使用為目創建虛擬環境,同時根據requiremnts ,將本項目所用的包全部放在虛擬環境下,最終2G 項目被打包成800兆,項目可在window上啟動;
2.項目啟動后,測試發現,使用.exe (onedir)項目啟動效率比使用vscode 啟動項目,要低非常多,大概降低5-6倍;
后來使用各種方法:
1. 網上說,除了pyinstaller 外,可使用Nuitka 編譯打包,但經過測試,發現沒有作用;
2.嘗試使用嵌入式 Python + 腳本啟動(性能 100%),經測試發現,效果還是不行;
3.使用Conda 安裝帶 MKL 的完整環境 ,測試發現:效果還是差;
那么到底是什么影響打包成.exe 的性能變差呢?
1.XGBoost 的 n_jobs=-1
會 spawn N 個子進程(Windows 必然 spawn);
2.每個子進程啟動時:
初始化新的 Python 解釋器
走 PyInstaller runtime hook 重定向模塊搜索路徑
重新加載
numpy
,scipy
,xgboost
等.pyd
(C++ 庫初始化)
3.所有這些步驟在源碼 + fork (linux)下幾乎是 0 成本,但在 spawn(window) 下是全量重復執行;
4.模型越大、并行核心數越多,額外開銷就越大
2.2 解決辦法
針對于window 的.exe? ,
? ? os.environ['OMP_NUM_THREADS'] = '1'
? ? os.environ['OPENBLAS_NUM_THREADS'] = '1'
? ? os.environ['MKL_NUM_THREADS'] = '1'
? ? os.environ['VECLIB_MAXIMUM_THREADS'] = '1'
? ? os.environ['NUMEXPR_NUM_THREADS'] = '1'
? ? torch.set_num_threads(1)
xgboost(n_jobs=1
)
3. 支持web 服務
3.1 問題
對于fastapi + ?unicorn + xgboost + pytorch? ,其實更適合用于web 項目,因此,我將項目拷貝到服務器
在服務器上使用nginx 反向代理
但這里遇到2個問題:
問題1:針對本地加載,我接口端口用的是8000,因此接口都是
http:://127.0.0.1:8000/ 接口名
而我使用web 端口之后,nginx 默認使用80端口,因此,對內網代理轉發后,會變成
http::// 公網id :80(可省略)/接口名,導致,和前端對接的時候,前端需要根據是本地pc 部署還是web 部署 使用不同的接口
問題2:
在訓練過程中的數據發送,選擇sse 方式,因此需要在nginx 配置sse
3.2 解決方案
對于web 端,內網端口改成8080 (或者其他非8000端口),然后nginx 監聽端口從80 改成8000,
C:\nginx\nginx-1.28.0>start nginx.exe
C:\nginx\nginx-1.28.0>nginx -s reload
C:\nginx\nginx-1.28.0>nginx -s quit? ?