10

I am trying to apply openmp and mpi techniques to an open source C program which requires "cmake . && make" to be built. I already found at How to set linker flags for OpenMP in CMake's try_compile function how to include the -fopenmp flags but still confused about mpi. What can I do about that?

Community
  • 1
  • 1
user3403765
  • 129
  • 1
  • 1
  • 8
  • 1
    OpenMP and MPI are two different concepts. OpenMP works with compiler directives, while MPI is merely a library to link against. However, to ease the linking there are typically compiler wrappers used, when compiling with MPI. Usually these are called mpicc or the like. Setting your CC to point to that wrapper might help. – haraldkl Apr 19 '14 at 03:26

3 Answers3

22

OpenMP

Is this a question about OpenMP? Then all you have to do is compile with -fopenmp which you can do by appending it to CMAKE_C_FLAGS, for example:

SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp)

MPI

For MPI, you have to find mpi first

find_package(MPI) #make it REQUIRED, if you want

then add it's header files to your search path

include_directories(SYSTEM ${MPI_INCLUDE_PATH})

and finally link your program(s) (which is my_mpi_target in my case)

 target_link_libraries(my_mpi_target ${MPI_C_LIBRARIES})
niklasfi
  • 15,245
  • 7
  • 40
  • 54
19

In modern CMake 3.X which is target based, the CMakeLists.txt should look like this:

cmake_minimum_required(VERSION 3.0)

project(main)

find_package(MPI REQUIRED)
# add this line only when you are using openmpi which has a different c++ bindings
add_definitions(-DOMPI_SKIP_MPICXX)

# Use imported targets would make things much eazier. Thanks Levi for pointing it out.
add_executable(main main.cpp)
target_link_libraries(main
  PRIVATE
  MPI_C)

# Old way.
#target_link_libraries(main
# PRIVATE
# ${MPI_C_LIBRARIES})

#target_include_directories(main
# PRIVATE
# ${MPI_C_INCLUDE_PATH}) 
Liu Hao Cheng
  • 669
  • 6
  • 6
  • 1
    What about `MPI__COMPILE/LINK_FLAGS`? also does C++ also link to C libraries? – dashesy May 10 '18 at 21:30
  • 1
    @dashesy Yes, Modern CMake would find these variables for you(I verified it on my Ubuntu 16.04 + CMake 3.9 environment). See more variables and details in [FindMPI.cmake](https://gitlab.kitware.com/cmake/cmake/blob/master/Modules/FindMPI.cmake). That being said, it also depends on the CMake version you are using. Check the official doc for info about the version you are using. – Liu Hao Cheng May 11 '18 at 02:02
  • 7
    In CMake 3.9 and up you can use this instead: `target_link_libraries(main PRIVATE MPI::MPI_C)`. Much nicer to use the imported target. – Levi Morrison Jul 20 '18 at 21:07
8

OpenMP and MPI together

For those who would like to use both OpenMP and MPI within a single CMake file:

cmake_minimum_required(VERSION 3.9.1)
project(parallel_task)

set(CMAKE_CXX_STANDARD 14)
set(GCC_COVERAGE_COMPILE_FLAGS "-Wall -pedantic -lm -O3 -funroll-loops")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")

add_executable(parallel_task example.cpp example.h)

# OpenMP
find_package(OpenMP)
if(OpenMP_CXX_FOUND)
    target_link_libraries(parallel_task PUBLIC OpenMP::OpenMP_CXX)
endif()

# MPI
find_package(MPI REQUIRED)
target_link_libraries(parallel_task PUBLIC MPI::MPI_CXX)

or even simpler:

cmake_minimum_required(VERSION 3.9.1)
project(parallel_task)

set(CMAKE_CXX_STANDARD 14)

# -fopenmp flag (enables OpenMP)
set(GCC_COVERAGE_COMPILE_FLAGS "-Wall -pedantic -lm -O3 -funroll-loops -fopenmp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}")

add_executable(parallel_task example.cpp example.h)

# MPI
find_package(MPI REQUIRED)
target_link_libraries(parallel_task PUBLIC MPI::MPI_CXX)

If you want to run your program directly from CLion (with a specified number of processes), check also this answer: https://stackoverflow.com/a/66992251/9723204

Hawklike
  • 952
  • 16
  • 23