對于大規模重複的運算,為了提高運算速度,可以将部分核心代碼用C++來實作,用編譯器編譯成動态可執行檔案(mex檔案),在MATLAB中直接調用。
個人親曆,有一段Monte-Carlo仿真的MATLAB代碼,在Intel 8700K+32G的機器上,運作時間在1周左右,經過C++重構核心代碼後,可以在2天内完成。同時,由于記憶體的占用降低,可以進行更大規模的仿真。
MATLAB版本:R2018b;C++編譯器:Visual Studio 2015 Professional;
關于不同版本MATLAB支援的編譯器,參考官網連結。
一、在Visual Studio中編寫C++檔案。
1.1 建立一個win32項目
項目名最好與函數名一緻,注意應用程式類型設定為DLL。
1.2 配置項目屬性。
- 在項目名稱上右鍵 -> 屬性即可打開項目屬性頁。
- 配置屬性->配置管理器->活動平台解決方案 -> 建立解決方案平台 -> x64;
- 配置屬性->C++ ->附加包含目錄,加入MATLAB目錄下的externinclude 路徑,預設為C:Program FilesMATLABR2018bexterninclude;
- 配置屬性->連結器->附加庫目錄,加入MATLAB目錄下的externlibwin64microsoft路徑,預設為C:Program FilesMATLABR2018bexternlibwin64microsoft;
- 配置屬性->連結器->輸入->附加依賴項, 添加libmx.lib,libeng.lib,libmat.lib,libmex.lib這四個lib檔案;
- 配置屬性->連結器->正常->輸出檔案,改為x64Debugvlda.mexw64 (vlda為項目名稱);
- 配置屬性->配置屬性->正常->目标檔案擴充名,改為.mexw64;
- 建立子產品定義檔案,vlda.def,内容為
LIBRARY
- 配置屬性->連結器->輸入->子產品定義檔案,vlda.def;
1.3 編寫函數檔案
在源檔案裡面已有vlda.cpp(vlda為項目名稱),在vlda.cpp中編寫MEX函數檔案。
mex函數的編寫注意事項:
- 注意檢查輸入的參數類型,參數數目,MATLAB預設的資料類型為double,一旦不比對,MATLAB調用時會直接崩潰;
- 注意記憶體洩漏,配置設定的記憶體,記得釋放掉;
- MATLAB 中的parfor可以在C++ 中輕松使用OpenMP實作,具體為添加庫檔案
# include "omp.h"
同時,在for循環前加上如下預編譯指令
#pragma omp parallel for
- 使用OpenMP時,配置屬性->C++ ->語言->OpenMP支援,選為"是";
1.4 生成解決方案
編寫好mex函數後,在項目名稱上右鍵->生成,進而進行編譯,生成.mex64檔案。
二、調試
- 将生成的.mexw64拷貝到MATLAB目前目錄。
- 菜單欄:調試->附加到程序->選擇MATLAB程序,附加到程序後,會經曆較長時間的符号加載過程;
- 如果符号加載時間過長,可以通過設定符号位置來解決,菜單欄:調試->選項->符号->勾選Microsoft符号伺服器;
- 在源代碼vlda.cpp中設定斷點;
- 在MATLAB中調用.mex64檔案,會跳轉到VS 2015 中的斷點,F10可單步執行;
- 調試過程中修改vlda.cpp,重新生成解決方案,将新生成的mexw64檔案拷貝到MATLAB目前目錄,此時,需要在matlab中clear掉原來的mexw64檔案,即運作指令
clear
三、釋出
對于比較簡單的程式,直接用Debug版本的也沒什麼問題,但最好還是使用Release版本。
- 配置屬性->配置管理器->活動解決方案配置->Release ,其他設定參照1.2配置項目屬性設定。
- 如果mexw64檔案需要拷貝到别的電腦上運作,可以考慮采用靜态編譯。配置屬性->C++ ->代碼生成->運作庫:多線程(/MT);配置屬性->正常->MFC的使用:在靜态庫中使用MFC。
四、總結
将部分核心代碼用C++實作後,能夠極大的提高運算速度,同時降低記憶體的使用。另一方面,借助于OpenMP,可以很友善的實作并行計算,将多核CPU的使用率維持在100%。
易夕:MATLAB Tricks 專欄目錄zhuanlan.zhihu.com