matlab计算遇到了瓶颈,但想要提高计算效率,就要结合其他语言编程,Fortran语言是一个不错的选择。然而,matlab配置Fortran过程中遇到了很多问题,好在最终也成功了,现在分享一下心得。本人使用的是Matlab2021b和Intel API2024+visual studio 2019
Visual Studio 2019安装
首先是安装visual studio。 我一开始使用的是visual studio 2022版的,但是后来发现这个版本问题太多了,始终实现不了matlab和Fortran进行配置,于是尝试选用2019版本的,结果成功了。2019版本的下载地址如下:Visual Studio 2019 版本 16.11 发行说明 | Microsoft Learn
我是下载community版的。然后具体安装过程可以参考这个大佬的:visual studio 2019安装教程(详细的很)_vs2019安装教程-CSDN博客
注意:visual studio2019安装过程中,一定要勾选使用C++桌面开发,不然安装了Intel API2024后还是看不到Fortran语言一栏
Intel API2024 安装
接下来是Intel API2024的安装,可以参考下面这位博主的:
Windows11安装oneAPI和Visual Studio 2022配置Fortran并行环境_visual studio fortran-CSDN博客
下载地址如下:
Download the Intel® oneAPI Base Toolkit和Download the Intel® HPC Toolkit
最后打开Visual Studio 2019,可以看到Fortran一项。
注意:先装 Visual Studio 2019后装Intel API2024
matlab配置Fortran
Matlab利用mex -setup FORTRAN语句配置FORTRAN编译器
但是也遇到了下面这位博主的情况:
他的思路给了我很大的启发:那就是添加 intel_fortran_22_vs2022.xml文件。但是我是用的是Intel API2024+visual studio 2019,所以需要找到 intel_fortran_24_vs2019.xml文件,这个文件matlab2021b是没有的。具体长这样:
<?xml version="1.0" encoding="UTF-8" ?>
<config
Name="Intel oneAPI 2024 for Fortran with Microsoft Visual Studio 2019"
ShortName="INTELF24MSVS2019"
Manufacturer="Intel"
Version="24.0"
Language="FORTRAN"
Priority="X"
Location="$FORTRANROOT" >
<Details
CompilerExecutable="$COMPILER"
CompilerDefines="$COMPDEFINES"
CompilerFlags="$COMPFLAGS"
OptimizationFlags="$OPTIMFLAGS"
DebugFlags="$DEBUGFLAGS"
IncludeFlags="$INCLUDE"
LinkerExecutable="$LINKER"
LinkerFlags="$LINKFLAGS"
LinkerLibraries="$LINKLIBS"
LinkerDebugFlags="$LINKDEBUGFLAGS"
LinkerOptimizationFlags="$LINKOPTIMFLAGS"
CommandLineShell="$FORTRANROOT\env\vars.bat "
CommandLineShellArg="intel64"
CompilerDefineFormatter="/D%s"
LinkerLibrarySwitchFormatter="lib%s.lib;%s.lib"
LinkerPathFormatter="/LIBPATH:%s"
LibrarySearchPath="$$LIB;$$LIBPATH;$$PATH;$$INCLUDE;$MATLABROOT\extern\lib\$ARCH\microsoft"
/>
<!-- Switch guide: http://msdn.microsoft.com/en-us/library/fwkeyyhe(v=vs.71).aspx -->
<vars
CMDLINE100="$COMPILER /c $COMPFLAGS $OPTIM $SRC /Fo$OBJ"
CMDLINE200="$LINKER $LINKFLAGS $LINKTYPE $LINKOPTIM $LINKEXPORTVER $OBJS $LINKLIBS /out:$EXE"
CMDLINE300="del $EXP $LIB $ILK"
FORTRANROOT="$ONE_API_ROOT/compiler/$ONE_API_VERSION"
COMPILER="ifx.exe"
COMPFLAGS="/nologo /fpp /fixed /MD /fp:source /assume:bscc $INCLUDE $COMPDEFINES"
COMPDEFINES="/DMATLAB_MEX_FILE"
MATLABMEX=" /DMATLAB_MEX_FILE"
OPTIMFLAGS="/O2 /DNDEBUG"
INCLUDE="-I"$MATLABROOT\extern\include""
DEBUGFLAGS="/Z7"
LINKER="link"
LINKFLAGS=" /nologo /INCREMENTAL:NO"
LINKTYPE="/DLL"
LINKEXPORT="/EXPORT:MEXFUNCTION"
LINKEXPORTVER="/EXPORT:MEXFUNCTION /EXPORT:MEXFILEREQUIREDAPIVERSION"
LINKLIBS="/LIBPATH:"$MATLABROOT\extern\lib\$ARCH\microsoft" libmx.lib libmex.lib libmat.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib"
LINKDEBUGFLAGS="/debug /PDB:"$TEMPNAME$LDEXT.pdb""
LINKOPTIMFLAGS=""
OBJEXT=".obj"
LDEXT=".mexw64"
SETENV="set COMPILER=$COMPILER
set COMPFLAGS=/c $COMPFLAGS $COMPDEFINES $MATLABMEX
set OPTIMFLAGS=$OPTIMFLAGS
set DEBUGFLAGS=$DEBUGFLAGS
set LINKER=$LINKER
set LINKFLAGS=$LINKFLAGS /export:%ENTRYPOINT% $LINKTYPE $LINKLIBS $LINKEXPORT
set LINKDEBUGFLAGS=/debug /PDB:"%OUTDIR%%MEX_NAME%$LDEXT.pdb"
set NAME_OUTPUT=/out:"%OUTDIR%%MEX_NAME%%MEX_EXT%""
/>
<client>
<engine
CMDLINE300="if exist $ILK del $ILK"
LINKLIBS="$LINKLIBS libeng.lib"
LINKEXPORT="/subsystem:console"
LINKEXPORTVER="/subsystem:console"
LDEXT=".exe"
LINKTYPE=""
MATLABMEX=""
/>
</client>
<locationFinder>
<ONE_API_ROOT>
<envVarExists name="ONEAPI_ROOT" />
</ONE_API_ROOT>
<ONE_API_VERSION>
<and>
<envVarExists name="ONEAPI_ROOT" />
<cmdReturns name ="echo off & (for /f %a IN ('dir "$$\compiler\2024*" /b /ad /on') do (@if exist "$$\compiler\%a\bin\ifx.exe" set "oneapiVer=%a")) & (@if defined oneapiVer call echo %oneapiVer%)"/>
</and>
</ONE_API_VERSION>
<VCROOT>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%" />
</and>
</or>
</VCROOT>
<SDKROOT>
<or>
<hklmExists path="SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
<hkcuExists path="SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
<hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
<hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v10.0" name="InstallationFolder" />
</or>
</SDKROOT>
<VSINSTALLDIR>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
</and>
</or>
</VSINSTALLDIR>
<VCINSTALLDIR>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
<cmdReturns name="set "vcroot=$$"&for /f "delims= " %a in ('type "$$\VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"') do @if exist "$$\VC\Tools\MSVC\%a\bin\HostX64\x64\cl.exe" call echo %vcroot%\VC\Tools\MSVC\%a" />
</and>
</or>
</VCINSTALLDIR>
<VCVARSALLDIR>
<or>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Enterprise -property installationPath -format value" />
<fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
<dirExists name="$$"/>
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Professional -property installationPath -format value" />
<fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
<dirExists name="$$"/>
</and>
<and>
<envVarExists name="ProgramFiles(x86)" />
<fileExists name="$$\Microsoft Visual Studio\Installer\vswhere.exe" />
<cmdReturns name=""$$\\vswhere.exe" -version "[16.0,17.0)" -products Microsoft.VisualStudio.Product.Community -property installationPath -format value" />
<fileExists name="$$\VC\Auxiliary\Build\vcvarsall.bat" />
<dirExists name="$$"/>
</and>
</or>
</VCVARSALLDIR>
<KITSROOT>
<or>
<hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hklmExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
</or>
</KITSROOT>
<SDKVERSION>
<and>
<or>
<hklmExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Wow6432Node\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hklmExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
<hkcuExists path="SOFTWARE\Microsoft\Windows Kits\Installed Roots" name="KitsRoot10" />
</or>
<!-- For each folder inside '<KITSROOT>\include' check for 'ucrt' and if exists return that folder name -->
<cmdReturns name="echo off&set "sdkversion="&(for /f %a IN ('dir "$$\include\" /b /ad-h /on') do ( @if exist "$$\include\%a\ucrt\" set "sdkversion=%a" ))&call echo %sdkversion%" />
</and>
</SDKVERSION>
</locationFinder>
<env
PATH="$FORTRANROOT\bin;$VCINSTALLDIR\bin\HostX64\x64\;$VCROOT\Common7\IDE\VC\vcpackages;$VCROOT\Common7\IDE;$VCROOT\Common7\Tools;$SDKROOT\Bin\$SDKVERSION\x64;$SDKROOT\Bin\$SDKVERSION\x86;$SDKROOT\Bin\x64;$SDKROOT\Bin\x86;"
INCLUDE="$FORTRANROOT\include;$VCINSTALLDIR\include;$VCINSTALLDIR\atlmfc\include;$KITSROOT\include\$SDKVERSION\ucrt;$KITSROOT\include\$SDKVERSION\shared;$KITSROOT\include\$SDKVERSION\um;$KITSROOT\include\$SDKVERSION\winrt;$MATLABROOT\extern\include"
LIB="$FORTRANROOT\lib;$VCINSTALLDIR\lib\x64;$VCINSTALLDIR\atlmfc\lib\x64;$KITSROOT\Lib\$SDKVERSION\ucrt\x64;$KITSROOT\lib\$SDKVERSION\um\x64;$MATLABROOT\lib\$ARCH"
LIBPATH="$FORTRANROOT\lib;$VCINSTALLDIR\lib\x64;$VCINSTALLDIR\atlmfc\lib\x64"
/>
</config>
将这段代码复制到文本文档中,然后再更改后缀名txt为xml。
最后是环境变量设置
在账户环境变量新建变量
注意变量值是你安装oneAPI地址
重启电脑,打开matlab,输入mex -setup FORTRAN,配置成功。
此外,编译器编译的是固定格式的fortran,我用的Fortran格式是自由格式的,于是我修改了mex_FORTRAN_win64.xml,删掉了其中的fixed,该文件具体位于C:\Users\用户名\AppData\Roaming\MathWorks\MATLAB\R2021b ,具体过程参考一下这篇文章Matlab与fortran90混合编程 - 知乎 (zhihu.com)