您当前的位置: 首页 > 
  • 0浏览

    0关注

    483博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

一个完整的CMake+OpenMPI编译链接hello-world过程

高精度计算机视觉 发布时间:2019-01-30 15:07:33 ,浏览量:0

前面写了一个关于《一个完整的cmake+clang+llvm编译链接hello-world过程》,感觉写这个的时候有点多余,因为大多数都是依葫葫芦画瓢,不过刚刚碰到一些MPI的问题,在网上找了一圈,发现太多关于MPI的误人子弟的贴子(我想主要原因可能是因为这些帖子太老了,不适用,软件都已经更新了好几代了),所以在这里写个简单的hello-world澄清一下。

比如MPI入门级的大量的报错, Linking Error: undefined reference to `MPI_Init' 网上多数贴子的理由五花八门,比如说要用mpi++而不是mpicc啦,gcc语法不对啦,其实最根本的原因是因为没有找到链接MPI的库文件,下面我们详细说明,知其然,知其所以然。

源码

mpich学习的源码部分可参考https://github.com/wesleykendall/mpitutorial (克隆命令:git clone https://github.com/wesleykendall/mpitutorial.git) 我取其中最简单那个做个示范,我安装的是OpenMPI,这主要是因为我用到的项目大多依赖OpenMPI而不是MPICH。

目录结构是这样的 ~/devc/mpitutorial/tutorials/mpi-hello-world mpi-hello-world |__linux.toolchain.cmake |__CMakeLists.txt |__src         |__CMakeLists.txt         |__mpi_hello_world.c |__build         |_(在此执行cmake+make操作)

内容如下,

mpi-hello-world / linux.toolchain.cmake

cmake_minimum_required( VERSION 2.6.3 )
set(CMAKE_SYSTEM_NAME Linux )

SET (CMAKE_C_COMPILER             "/usr/bin/clang")
SET (CMAKE_C_FLAGS                "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG          "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE        "-O4 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")

SET (CMAKE_CXX_COMPILER             "/usr/bin/clang++")
SET (CMAKE_CXX_FLAGS                "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG          "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

SET (CMAKE_AR      "/usr/bin/llvm-ar")
SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
SET (CMAKE_NM      "/usr/bin/llvm-nm")
SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

mpi-hello-world / CMakeLists.txt

cmake_minimum_required(VERSION 3.7.1)
project(hello)
add_subdirectory(src)

mpi-hello-world / src / CMakeLists.txt

cmake_minimum_required(VERSION 3.7.1)

project(hello-world)

find_package(LLVM REQUIRED CONFIG)
find_package(MPI REQUIRED)


set(SOURCE_FILES mpi_hello_world.c)

message(STATUS "This is BINARY dir " ${PROJECT_BINARY_DIR})
message(STATUS "This is SOURCE dir " ${PROJECT_SOURCE_DIR})

message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
message(STATUS "Using LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}")
message(STATUS "Using LLVM_DEFINITIONS: ${LLVM_DEFINITIONS}")
message(STATUS "Using MPI_INCLUDE_PATH: ${MPI_INCLUDE_PATH}")
message(STATUS "Using MPI_C_LIBRARIES: ${MPI_C_LIBRARIES}")

#/usr/lib/x86_64-linux-gnu/openmpi/include
include_directories(SYSTEM ${MPI_INCLUDE_PATH})
include_directories(${LLVM_INCLUDE_DIRS} )
add_definitions(${LLVM_DEFINITIONS})

add_executable(hello ${SOURCE_FILES})

llvm_map_components_to_libnames(llvm_libs support core irreader)

target_link_libraries(hello ${llvm_libs} ${MPI_C_LIBRARIES})

mpi-hello-world / src / mpi-hello-world.c

// Author: Wes Kendall
// Copyright 2011 www.mpitutorial.com
// This code is provided freely with the tutorials on mpitutorial.com. Feel
// free to modify it for your own use. Any distribution of the code must
// either provide a link to www.mpitutorial.com or keep this header intact.
//
// An intro MPI hello world program that uses MPI_Init, MPI_Comm_size,
// MPI_Comm_rank, MPI_Finalize, and MPI_Get_processor_name.
//
#include 
#include 

int main(int argc, char** argv) {
  // Initialize the MPI environment. The two arguments to MPI Init are not
  // currently used by MPI implementations, but are there in case future
  // implementations might need the arguments.
  MPI_Init(NULL, NULL);

  // Get the number of processes
  int world_size;
  MPI_Comm_size(MPI_COMM_WORLD, &world_size);

  // Get the rank of the process
  int world_rank;
  MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

  // Get the name of the processor
  char processor_name[MPI_MAX_PROCESSOR_NAME];
  int name_len;
  MPI_Get_processor_name(processor_name, &name_len);

  // Print off a hello world message
  printf("Hello world from processor %s, rank %d out of %d processors\n",
         processor_name, world_rank, world_size);

  // Finalize the MPI environment. No more MPI calls can be made after this
  MPI_Finalize();
}
编译源码并运行

注意我在CMakeLists.txt中加了相当多的调试信息,切换到build目录下后,执行,

$ cmake  -DCMAKE_TOOLCHAIN_FILE=../linux.toolchain.cmake  ..
$ make VERBOSE=1

就可得到详细的运行信息,如下

$ cmake  -DCMAKE_TOOLCHAIN_FILE=../linux.toolchain.cmake  ..
-- The C compiler identification is Clang 6.0.0
-- The CXX compiler identification is Clang 6.0.0
-- Check for working C compiler: /usr/bin/clang
-- Check for working C compiler: /usr/bin/clang -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/clang++
-- Check for working CXX compiler: /usr/bin/clang++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found MPI_C: /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so (found version "3.1") 
-- Found MPI_CXX: /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi_cxx.so (found version "3.1") 
-- Found MPI: TRUE (found version "3.1")  
-- This is BINARY dir /home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build/src
-- This is SOURCE dir /home/user01/devc/mpitutorial/tutorials/mpi-hello-world/src
-- Found LLVM 6.0.0
-- Using LLVMConfig.cmake in: /usr/lib/llvm-6.0/cmake
-- Using LLVM_INCLUDE_DIRS: /usr/lib/llvm-6.0/include
-- Using LLVM_DEFINITIONS: -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS 
-D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS
-- Using MPI_INCLUDE_PATH: /usr/lib/x86_64-linux-gnu/openmpi/include/openmpi;
/usr/lib/x86_64-linux-gnu/openmpi/include/openmpi/opal/mca/event/libevent2022/libevent;
/usr/lib/x86_64-linux-gnu/openmpi/include/openmpi/opal/mca/event/libevent2022/libevent/include;
/usr/lib/x86_64-linux-gnu/openmpi/include
-- Using MPI_C_LIBRARIES: /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so
-- Configuring done
-- Generating done
-- Build files have been written to: /home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build


$ make VERBOSE=1
/usr/bin/cmake -H/home/user01/devc/mpitutorial/tutorials/mpi-hello-world 
-B/home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build 
--check-build-system CMakeFiles/Makefile.cmake 0
/usr/bin/cmake -E cmake_progress_start 
/home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build/CMakeFiles 
/home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build/CMakeFiles/progress.marks
make -f CMakeFiles/Makefile2 all
......
Scanning dependencies of target hello
......
make[2]: 离开目录“/home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build”
[100%] Built target hello
make[1]: 离开目录“/home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build”
/usr/bin/cmake -E cmake_progress_start 
/home/user01/devc/mpitutorial/tutorials/mpi-hello-world/build/CMakeFiles 0

最后生成的可执行文件在 mpi-hello-world / build / src / hello。

关于MPI宏定义: MPI_C_LIBRARIES和MPI_C_INCLUDE_PATH

LLVM相关的宏定义都在文件LLVMConfig.cmake中,一般情况下默认的路径如下所示  /usr/lib/llvm-6.0/cmake/LLVMConfig.cmake

CMake中的module findMPI.cmake在如下路径, /usr/share/cmake-3.10/Modules   /usr/share/cmake-3.13/Modules 如果你对findMPI感兴趣,可以详细阅读一下源码,其中有定义MPI_C_LIBRARIES和MPI_C_INCLUDE_PATH 注意:MPI_C_INCLUDE_PATH和MPI_INCLUDE_PATH的效力是一样的,这一点cmake官方文档中有详细说明,可参考:https://cmake.org/cmake/help/v3.13/module/FindMPI.html 链接库在这里target_link_libraries(hello ${llvm_libs} ${MPI_C_LIBRARIES})从调试输出部分也可以看到,MPI_C_LIBRARIES相当于链接到了这个库 /usr/lib/x86_64-linux-gnu/openmpi/lib/libmpi.so

总结

总结一下MPI编程的基本步骤

step.1: 对于 MPI ,首先你必须先找到MPI find_package(MPI) #必需的

step.2: 然后将其添加的头文件到您的搜索路径 include_directories(SYSTEM $ {} MPI_INCLUDE_PATH)

step.3:和最后链接程序 target_link_libraries(target ${MPI_C_LIBRARIES})

 

参考资料

https://cmake.org/cmake/help/v3.13/module/FindMPI.htmlhttps://github.com/wesleykendall/mpitutorial

关注
打赏
1661664439
查看更多评论
立即登录/注册

微信扫码登录

0.0361s