我正在开发一个MPI应用程序,它需要运行MPI的特定实现(让我们称之为MPIvA)。在我的工作站上,安装了MPI的另一个实现(让它称之为MPIvB)。
我的应用程序是使用CMake构建的,find_library(MPI)
显然指向MPIvB。它编译和运行没有麻烦。
我在工作站上编译了MPIvA。如何让CMake使用这些标题和二进制文件?
答案 0 :(得分:5)
CMake附带一个FindMPI模块,可以为您完成所有繁重的工作。
在您的CMakeLists.txt中,请使用find_library(MPI)
,而不是调用find_package
:
#### MPI
find_package(MPI REQUIRED)
if (MPI_FOUND)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
else (MPI_FOUND)
message(SEND_ERROR "This application cannot compile without MPI")
endif (MPI_FOUND)
然后,无论您将应用程序链接到哪里,都会链接到${MPI_LIBRARIES}
:
target_link_libraries(example-app ${MPI_LIBRARIES})
现在,cmake将自动在您的系统中找到 MPI实现。如果您有多个不同的MPI版本,并且想要指定要编译的版本,可以将MPI_C_COMPILER
和MPI_CXX_COMPILER
变量设置为相应的mpicc
和mpicxx
编译器包装器。然后,CMake模块将使用它们来确定所有必需的编译器和链接器标志本身。
示例:
cmake -DMPI_C_COMPILER=/usr/share/mvapich/bin/mpicc your-project-dir
要确保cmake使用正确的MPI,请从新的空构建目录开始。
有关FindMPI模块的更多信息,请访问:https://cmake.org/cmake/help/v3.0/module/FindMPI.html
答案 1 :(得分:1)
为了在工作站上针对MPIvA进行编译,您需要先使用CMake查找这些标头和二进制文件。以下链接介绍了CMake的find_library搜索顺序的工作原理:https://cmake.org/cmake/help/v3.0/command/find_library.html
我建议将MPIvA添加到CMAKE_LIBRARY_PATH。有关示例,请参阅以下问题的最佳答案: How do I instruct CMake to look for libraries installed by MacPorts?
答案 2 :(得分:0)
内置的cmake会经常干扰你想要的库,特别是如果你使用不同的集群,因为通常默认的编译器不是你可能需要的最新版本,解决这个问题的方法是拥有你自己的FindMYMPI.cmake并采取控制。 否则,命令行选项或使用ccmake GUI更改它也是上述答案中提供的可能性。
答案 3 :(得分:0)
在这种情况下,我成功使用了以下环境变量:
export MPI_HOME=/your/path/to/prefix
请使用cmake在之前进行设置,或清空构建目录。
答案 4 :(得分:0)
好吧,这不是新文章,但将来可能对其他人有用。
即使前面的答案也可以,但我认为更好的方法是使用 CMAKE_PREFIX_PATH 选项,例如
CMAKE_PREFIX_PATH=~/my-libs-install-path ccmake ..
现在,其他一些评论:
所有MPI库都应该可互换,即使用MPI规范的代码应编译并与任何MPI实现一起运行(例如,我假设是intelmpi,openmpi或mpich的MPIvA和MPIvB)。
关于这个答案(我的名声不允许我发表评论,所以我在这里回复):
find_package(MPI REQUIRED)
if (MPI_FOUND)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
else (MPI_FOUND)
message(SEND_ERROR "This application cannot compile without MPI")
endif (MPI_FOUND)
即使该功能大部分与预期的一样,但以下功能等效:
find_package(MPI REQUIRED)
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
findpackage(需要MPI)命令中的 REQUIRED 部分将导致该命令在未找到MPI的情况下失败,因此 if(MPI_FOUND)< / strong>部分没有用,else子句实际上永远不会执行。
最后,关于 include_directories 命令,如果您使用目标(例如
),则在我的测试中不需要target_link_libraries(my_app PUBLIC MPI :: C)
足够了。