windows下intel oneapi hpc 套件使用命令行、bat脚本、cmake、nmake编译fortran程序和c++程序
1. 引言
Intel 编译器一直是比较好的编译器,支持特性多,兼容性也强。从早期的单个编译器,编译器组合,到parallel xe,再到现在的one api,无论是windows下还是在linux下是科学计算编程的良好工具。one api 套装虽然不开源,不需要激活也可以使用,所以也很方便使用。
本文介绍一下在windows下怎么使用one api 套件编译fortran和c++程序,仅以fortran为例,c++是类似的。需要注意的是这是传统c++或fortran的编译,而不是适用于DPC++的编译,后者将在后面的文章中介绍。
2. 环境准备
系统环境条件参考:【Intel® oneAPI Base Toolkit System Requirements】
一般的软硬件通常是具备的,主要是完成如下软件准备。
visual studio 或 microsoft visual studio build tools
windows下使用安装和使用intel oneapi kit 需要先安装vs 或 microsoft visual studio build tools。
若使用vs build tools那么只能通过命令行进行编译,没有界面。若需要界面则需要使用visual studio。
vs build tools 从下面这里【vs build tools】 下载。
安装没有什么注意事项,正常安装即可。
intel one api
intel one api 提供的套件,直接在这里
【intel one api】
下载即可。
注意:需要下载 Intel® oneAPI HPC Toolkit 完整包,包括base kit 和hpc kit。
安装根据提示选择全部安装即可,若360安全卫士提示一些权限选择,选择允许执行即可,若需安静安装,最好暂时关闭卫士。
cmake
cmake 是一个跨平台的方便的编译集成工具,可以用于编译。
从这里【cmake】 下载。正常安装即可,需将其路径加入系统path。
上述软件安装完毕,则环境就准备完毕了。
3. 程序准备
由于fortran程序相比c++程序稍复杂,所以这里以fortran程序编译举例,并说明c++程序编译的差异。
这里准备两个简单程序,一个是串行的,另一个是mpi并行的。
串行程序
使用一个简单的fortran串行程序 main.f90 :
program test
integer i;
write(*,*) 'test-hello'
do i=1,6
print *,'i=',i
end do
end program
mpi并行程序
使用一个简单的mpi并行程序 testmpi.F90(这是intel 提供的示例):
program main
use mpi
implicit none
integer i, size, rank, namelen, ierr
character (len=MPI_MAX_PROCESSOR_NAME) :: name
integer stat(MPI_STATUS_SIZE)
call MPI_INIT (ierr)
call MPI_COMM_SIZE (MPI_COMM_WORLD, size, ierr)
call MPI_COMM_RANK (MPI_COMM_WORLD, rank, ierr)
call MPI_GET_PROCESSOR_NAME (name, namelen, ierr)
if (rank.eq.0) then
print *, 'Hello world: rank ', rank, ' of ', size, ' running on ', name
do i = 1, size - 1
call MPI_RECV (rank, 1, MPI_INTEGER, i, 1, MPI_COMM_WORLD, stat, ierr)
call MPI_RECV (size, 1, MPI_INTEGER, i, 1, MPI_COMM_WORLD, stat, ierr)
call MPI_RECV (namelen, 1, MPI_INTEGER, i, 1, MPI_COMM_WORLD, stat, ierr)
name = ''
call MPI_RECV (name, namelen, MPI_CHARACTER, i, 1, MPI_COMM_WORLD, stat, ierr)
print *, 'Hello world: rank ', rank, ' of ', size, ' running on ', name
enddo
else
call MPI_SEND (rank, 1, MPI_INTEGER, 0, 1, MPI_COMM_WORLD, ierr)
call MPI_SEND (size, 1, MPI_INTEGER, 0, 1, MPI_COMM_WORLD, ierr)
call MPI_SEND (namelen, 1, MPI_INTEGER, 0, 1, MPI_COMM_WORLD, ierr)
call MPI_SEND (name, namelen, MPI_CHARACTER, 0, 1, MPI_COMM_WORLD, ierr)
endif
call MPI_FINALIZE (ierr)
end
4. 四种编译方法
程序的编译实质是利用编译器将源代码转换为可执行程序或者库文件。
4.1命令行编译
命令行编译是最清楚,自己能够知道和控制所需要的工具、库、选项。
首先从开始菜单的程序中选择intel oneapi 2022下的intel oneapi command promopt,进入命令行,如此所有的编译环境就已经设置好了。其显示如下:
编译串行程序:
ifort main.f90
可以加上 -O3 等等选项。
执行用:
main.EXE
结果为:
编译mpi并行程序:
ifort testmpi.f90 impi.lib
或者
mpiifort testmpi.f90
可以加上 -O3 等等选项。
执行用:
mpiexec -n 3 testmpi.exe
结果为:
c++程序编译用命令:icl,mpicxx,方法是类似的,只是把源程序换成c++的。
4.2 脚本编译
脚本编译就是写一个bat文件来执行编译。需要注意的是需要在bat文件中调用intel oneapi提供的环境配置。
后面的编译操作与命令行是类似的。
编写一个脚本如下:
@echo off
@call "D:\Program Files\intel\setvars.bat" intel64 vs2019
:: title
title intel one api WD:%cd% %date% %time%
rem :如果没有输入则提示错误
SET srcfile=%1
SET ppn=%2
if "%ppn%" =="" (
echo 错误:没有输入参数,请重新输入!!!
goto endcmd
) else (
:: echo ppn=%ppn%
goto dealfile
)
rem :处理输入参数
:dealfile
rem :当源文件为f90或for结尾时直接去1~倒数第4个字符即去掉.F90或.for
set exefile=%srcfile:~0,-4%.exe
rem :当源文件为f结尾时直接取1~倒数第2个字符即去掉.F
if %srcfile%==%srcfile:~0,-1%f set exefile=%srcfile:~0,-2%.exe
rem :多文件输入情况处理
rem :多文件输入时fortran编译出来的exe以第一个文件的文件名为exe文件名
rem :因此exe文件名无需继续处理只要处理源文件和进程数就足够
:loopread
shift
set judge=%2
if "%judge%" =="" (
goto compile
) else (
set srcfile=%srcfile% %1
SET ppn=%2
rem echo %srcfile% %ppn%
rem pause
goto loopread
)
rem :对源文件进行编译,若使用mpiifort则会跳出后面的执行内容。
:compile
echo =========================================================
echo Compile the fortran file
echo =========================================================if /i %ppn% equ 0 (
ifort %srcfile% /O3 /F0x1000000
) else (
if /i %ppn% equ 1 (
ifort %srcfile% /O3 /F0x1000000
) else (
ifort %srcfile% impi.lib /O3 /F0x1000000
)
)
goto runexe
:runexe
rem :执行exe文件
echo.
echo =========================================================
echo Run the executable file
echo =========================================================
if /i %ppn% equ 0 (
%exefile%
) else (
if /i %ppn% equ 1 (
%exefile%
) else (
mpiexec -n %ppn% %exefile%
)
)
rem :删除编译过程文件
if exist *.mod del *.mod /Q
if exist *.obj del *.obj /Q
rem :暂停敲任意键结束
:endcmd
pause
将其命名为ivfm.bat,放到系统path所能找到的路径里面。
那么就可以使用如下方式编译并执行程序了:
对于串行程序:
ivfm main.f90 1
结果为:
对于并行程序:
ivfm main.f90 3
结果为:
4.3 nmake 编译
使用nmake编译就是利用intel 提供的 nmake 工具进行编译,其工作方式类似于gnu的make。
需要编写一个Makefile文件来告诉nmake执行不同命令需要的资源。
CXX = ifort
CXXMPI = mpiifort
CXXFLAGS = /O3
LDFLAGS =
EXE_NAME = main.exe
SOURCES = main.f90
EXE_NAMEMPI = testmpi.exe
SOURCESMPI = testmpi.f90
PPN=3
all: main testmpi
main:
$(CXX) $(CXXFLAGS) -o $(EXE_NAME) $(SOURCES) $(LDFLAGS)
testmpi:
$(CXXMPI) $(CXXFLAGS) -o $(EXE_NAMEMPI) $(SOURCESMPI) $(LDFLAGS)
run:
$(EXE_NAME)
runmpi:
mpiexec -n $(PPN) $(EXE_NAMEMPI)
clean:
del /F /Q *.obj *.exe $(EXE_NAME)
由intel oneapi command promopt 进入命令行,同时编译串行和并行程序,使用命令:
nmake
结果为:
测试串行程序
nmake run
测试串行程序
nmake runmpi
结果为:
4.4 cmake 编译
cmake 则是另一种集成编译工具,只要设定高层的编译逻辑,那么就能自动的完成工具的调用,实现编译。其工作方式于latex中latexmk类似。
其核心是设定CMakeLists.txt文件,其中包含比较自然的编译逻辑。
cmake_minimum_required(VERSION 3.10)
enable_language(Fortran)
# set the project name
project(main)
# add the executable
add_executable(main main.f90)
add_executable(testmpi testmpi.f90)
target_link_libraries(testmpi impi.lib)
enable_testing()
add_test(NAME test_serial COMMAND main)
add_test(NAME test_paralle COMMAND mpiexec -n 2 testmpi)
其中enable_language(Fortran)是启动fortran语言的支持,若是c++程序,则去掉即可。
对于编译命令,intel 网站上面doc【Configuring CMake* and Microsoft Visual Studio* 2019 for Use with Intel® Compilers】 中提供了一个示例。
由intel oneapi command promopt 进入命令行后:
对于c++程序,使用如下命令是没有问题的。
cmake -T "Intel C++ Compiler 2022" -DCMAKE_CXX_COMPILER="icl" .
cmake --build .
但是fortran程序使用:
cmake -DCMAKE_Fortran_COMPILER="ifort" .
是不行的,即使加上路径:
cmake -DCMAKE_Fortran_COMPILER="ifort" -DCMAKE_Fortran_COMPILER:FILEPATH="d:/Program Files/intel/compiler/latest/windows/bin/intel64/ifort" .
也不行。
于是我们换一种方法来编译,即使用cmake提供的-G选项。
cmake -G "NMake Makefiles"
完成设置。
结果为:
命令:
cmake --build .
完成编译。
结果为:
命令:
ctest -VV
完成测试。其中选项-VV
用于显示程序运行结果,而不仅仅是测试的结果。
结果为:
5. 小结
本文初步介绍了intel one api 的套件中 fortran 和 c++程序的四种编译方式,并提供了代码示例,
为intel one api 编译器的简单使用提供了示范。
后面会有项目工程(project)的编译、利用c++和fortran混合编程cmake编译,dpc++编译,openmp并行的编译等的介绍。
6. 参考
-
https://www.intel.com/content/www/us/en/develop/documentation/get-started-with-intel-oneapi-hpc-windows/top.html
-
https://cmake.org/cmake/help/latest/
-
https://www.cnblogs.com/lidabo/p/7359422.html
-
https://blog.csdn.net/baidu_29950065/article/details/72716650
-
https://blog.csdn.net/huyanjie0327/article/details/46652313