當前MindSpore對于Windows平臺的支持仍有欠缺,比如不支持GPU粱坤,編譯工具鏈導致的無法編譯debug版本而影響問題定位效率等。今年MindSpore將嘗試通過社區(qū)如易用性sig協(xié)作的方式瓷产,共同把這些問題解決站玄,為MindSpore的Windows用戶提供更好的使用體驗。
個人以前也沒有Windows以及MindSpore框架開發(fā)的經(jīng)驗濒旦,在網(wǎng)絡(luò)搜索關(guān)于MindSpore的資料時株旷,找到的更多是關(guān)于如何使用MindSpore進行網(wǎng)絡(luò)實現(xiàn)和訓練、推理,沒有從框架貢獻者的角度介紹如何參與或者給MindSpore貢獻代碼的內(nèi)容晾剖。所以锉矢,想借這個機會記錄好Windows下這些問題解決的過程,既能聯(lián)合社區(qū)的朋友們解決MindSpore在Windows下的問題齿尽,也能提升自己對于Windows下開發(fā)沽损、對于MindSpore在架構(gòu)和代碼層面的理解,還可以為想給MindSpore貢獻代碼的同學提供一些參考循头。
在開始解決實際的問題前绵估,我想第一步應(yīng)該是參考MindSpore官網(wǎng)的安裝指南來完成Windows下CPU版本的編譯,本文就是記錄下我編譯安裝的過程以及發(fā)現(xiàn)的問題卡骂。
Windows下編譯MindSpore CPU版本
1. 安裝依賴軟件
MindSpore的CPU版本在編譯時依賴軟件及安裝方式如下表:
軟件 | 版本要求 | 用途 | 安裝方法 |
---|---|---|---|
Windows | 10,64位 | 操作系統(tǒng)平臺 | |
python | 3.9.0/3.7.5 | Python語言解釋器 | 3.9.0 下載地址国裳,直接安裝即可 |
mingw | 7.3.0 | 編譯工具鏈 |
下載地址,解壓后將目錄加入到Path 環(huán)境變量下 |
git | 2.29.0 | 版本管理工具 | 下載地址全跨,下載直接安裝即可 |
cmake | >3.18.3 | 構(gòu)建工具 | 下載地址缝左,下載64位MSI版本直接安裝即可 |
strawberry perl | 5.28.1.2801 | perl編譯器 |
下載地址,解壓后將Perl的bin目錄加到Path 環(huán)境變量中 |
wheel | >0.32.0 | Python打包工具 | 執(zhí)行pip install wheel 即可 |
官網(wǎng)的Windows編譯安裝指南中推薦使用ActivePerl浓若,但其下載過程中還需要注冊渺杉,體驗并不好,所以我使用了strawberry perl挪钓,而且最好是zip包少办,因為MSI的安裝會將額外的gcc編譯工具鏈添加到
Path
中,影響編譯中g(shù)cc編譯器的選擇诵原;
對于以上需要安裝的工具,exe
以及msi
格式的軟件包都可以自動配置bin
目錄到Path
環(huán)境變量中(有些需要在安裝過程中指定挽放,如cmake)绍赛,而壓縮包版本則需要在解壓后,手動在Windows的環(huán)境變量Path
中添加新的路徑辑畦。如下圖吗蚌,如果strawberry-perl-5.28.2.1-64bit.zip
被解壓到D盤的根目錄,可以在系統(tǒng)變量Path
或者用戶變量Path
中增加D:\Strawberry\perl\bin
的項目纯出,同理蚯妇,也需要增加mingw bin的路徑,如圖中的D:\mingw64\bin
暂筝。
另一個需要配置的是pip的鏡像源箩言,可以考慮使用華為云Python鏡像,在C:\Users\<UserName>\pip\pip.ini
中添加如下內(nèi)容即可:
[global]
index-url = https://repo.huaweicloud.com/repository/pypi/simple
trusted-host = repo.huaweicloud.com
timeout = 120
2. 下載MindSpore源碼編譯
首先通過git clone --depth=1 https://gitee.com/mindspore/mindspore.git -b r1.6
下載框架的源碼焕襟,這里指定了1.6版本的tag陨收,原因當前的master分支編譯會出錯……。
然后啟動Windows的CMD,然后切換到代碼倉庫的目錄务漩,正式開始編譯前可以設(shè)置下patch
的環(huán)境變量MS_PATCH_PATH拄衰,以防止在三方庫打patch時因為git安裝路徑的問題找不到patch
命令,方式和第一部分中添加Path
環(huán)境變量類似饵骨。首先在cmd中通過where git
找到git的安裝目錄翘悉,如D:\Program Files\Git\cmd\git.exe
,然后創(chuàng)建一個新的用戶環(huán)境變量MS_PATCH_PATH
,賦值為D:\Program Files\Git\usr\bin
居触。最后在cmd 輸入 refreshenv
完成環(huán)境變量刷新妖混。
MindSpore代碼倉根目錄下的build.bat
是啟動編譯的批處理腳本,腳本中有兩處變量會影響到編譯的效率:
-
SET threads=8
:設(shè)置并行編譯的線程數(shù)饼煞,默認為8源葫。如果你的處理器支持的線程數(shù)更高,可以修改為更大的數(shù)字砖瞧,比如我的CPU是8核16線程息堂,這個地方我就改成了16; -
SET ENABLE_GITEE=ON
:是否通過gitee下載三方庫的壓縮包,默認從github下載块促。如果網(wǎng)絡(luò)訪問外網(wǎng)環(huán)境不太好荣堰,可以選擇修改為ON
,加快下載速度竭翠;
這些準備完成后振坚,就可以在cmd中執(zhí)行call build.bat
開始編譯,正常大約1小時左右就可以完成編譯斋扰,生成mindspore的whl包渡八。
3. 安裝編譯版本并檢查
MindSpore的編譯好的whl包路徑在build\package\
下,切換到該目錄下传货,使用pip install mindspore-1.6.1-cp39-cp39-win_amd64.whl
屎鳍,執(zhí)行運行檢查:
D:\Workspace\mindspore\build\package>python -c "import mindspore;mindspore.run_check()"
MindSpore version: 1.6.1
The result of multiplication calculation is correct, MindSpore has been installed successfully!
可以運行,表明編譯成功。
發(fā)現(xiàn)的問題/改進點
如果一切順利,整個的編譯時間大概在一小時多一點挺智,但實際上我花了大約1天的時間钦奋,原因是在過程中碰到了一些列的問題。
- 使用conda的Python環(huán)境,編譯Protobuf失敗。如果你的Python環(huán)境是通過conda去做管理的,在編譯Protobuf三方庫會遇到這樣的錯誤:
-- 3.13.0.0
-- Looking for pthread.h
-- Looking for pthread.h - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Found ZLIB: C:/Users/lenovo/.conda/envs/py39/Library/lib/z.lib (found version "1.2.11")
-- Performing Test protobuf_HAVE_BUILTIN_ATOMICS
-- Performing Test protobuf_HAVE_BUILTIN_ATOMICS - Success
-- Configuring done
-- Generating done
-- Build files have been written to: D:/Workspace/mindspore/build/mindspore/_deps/protobuf-src/_build
Scanning dependencies of target libprotobuf-lite
In file included from D:\Workspace\mindspore\build\mindspore\_deps\protobuf-src\src\google\protobuf\arena.cc:37:0:
C:/Users/lenovo/.conda/envs/py39/Library/include/google/protobuf/stubs/mutex.h: In constructor 'constexpr google::protobuf::internal::WrappedMutex::WrappedMutex()':
C:/Users/lenovo/.conda/envs/py39/Library/include/google/protobuf/stubs/mutex.h:124:29: error: temporary of non-literal type 'google::protobuf::internal::CallOnceInitializedMutex<std::mutex>' in a constant expression
constexpr WrappedMutex() {}
^
……
在protobuf.cmake
中用-Dprotobuf_WITH_ZLIB=OFF
屏蔽zlib后可以完成編譯忧饭,但具體影響的功能不祥。
mindspore_add_pkg(protobuf
VER 3.13.0
LIBS protobuf
EXE protoc
URL ${REQ_URL}
MD5 ${MD5}
CMAKE_PATH cmake/
CMAKE_OPTION -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -DCMAKE_BUILD_TYPE=Release -Dprotobuf_WITH_ZLIB=OFF
PATCHES ${PROTOBUF_PATCH_ROOT}/CVE-2021-22570.patch)
通過上面的日志發(fā)現(xiàn)編譯時用到了conda的zlib秉氧、protobuf頭文件眷昆,并非框架下載zlib和protobuf,推測根源的問題在這里。檢查系統(tǒng)環(huán)境變量亚斋,發(fā)現(xiàn)miniconda在安裝時自動的在Path環(huán)境變量中添加了mingw的類庫路徑作媚,而這個路徑下包含了編譯框架需要的zlib、protobuf的一些頭文件帅刊,版本不一致導致了protobuf的編譯錯誤纸泡。將下圖中包含Library
路徑從Path變量中去掉后,在不修改protobuf.cmake
的情況下也可以正常編譯赖瞒。
- master分支編譯完成安裝后出現(xiàn)導入錯誤女揭。具體的錯誤信息如下:
(py39) D:\Workspace\mindspore\build\package>python -c "import mindspore;mindspore.run_check()"
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "D:\Workspace\mindspore\build\package\mindspore\__init__.py", line 29, in <module>
from .rewrite import *
ModuleNotFoundError: No module named 'mindspore.rewrite'
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "D:\Workspace\mindspore\build\package\mindspore\__init__.py", line 29, in <module>
from .rewrite import *
ModuleNotFoundError: No module named 'mindspore.rewrite'
屏蔽對應(yīng)的代碼行可以正常運行,但這個錯誤不應(yīng)該出現(xiàn)栏饮,master上合入的代碼應(yīng)該保證基本的功能吧兔,這里的自動化測試環(huán)節(jié)沒有能照顧到這個基礎(chǔ)的健康檢查。這也是為什么上面的編譯使用了1.6版本的分支而非master的原因袍嬉。
- 是否有必要引入
perl
這個依賴境蔼。我檢查了MindSpore代碼倉中對于perl
的使用,結(jié)果發(fā)現(xiàn)Windows下只有protobuf
的cmake有使用伺通,
if(WIN32)
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/proto/${file_name}.pb.cc"
"${CMAKE_BINARY_DIR}/proto/${file_name}.pb.h"
"${CMAKE_BINARY_DIR}/proto/${file_name}_pb2.py"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
...
COMMAND perl -pi.bak -e "s/import (.+_pb2.*)/from . import \\1/"
"${CMAKE_BINARY_DIR}/proto/${file_name}_pb2.py"
...
COMMENT "Running C++ protocol buffer compiler on ${file}" VERBATIM)
這里perl命令的作用是把所有*_pb2.py
的python文件中的import xxx as xxx
替換為 from . import xxx as xxx
箍土。如果沒有其它的庫依賴perl,這里可以考慮用inline的python命令罐监、cmd命令行工具或者sed(for windows)來替換吴藻,最優(yōu)的情況下可以在安裝和編譯的過程中減少一個依賴,提升使用體驗弓柱。
總結(jié)
本次的MindSpore CPU版本編譯過程中發(fā)現(xiàn)了3個問題:conda管理的python環(huán)境編譯沟堡、master編譯后的執(zhí)行錯誤以及編譯依賴perl
的問題,針對這幾個問題矢空,我在gitee的代碼倉中創(chuàng)建了issue并添加kind/bug
和comp/build-install
標簽弦叶,方便負責相應(yīng)領(lǐng)域的開發(fā)人員進行分析和解決問題。
編譯的過程中出現(xiàn)了大量的三方庫以及模塊的編譯過程妇多,要理解MindSpore的編譯,首先得理清楚過程中都依賴了什么燕侠,編譯了那些模塊者祖,功能和作用是什么,這也是下一步需要分析和完成的內(nèi)容绢彤。