diff --git a/CMakeExt/Code/test_compatible_ompi.c b/CMakeExt/Code/test_compatible_ompi.c new file mode 100644 index 000000000..526469ed7 --- /dev/null +++ b/CMakeExt/Code/test_compatible_ompi.c @@ -0,0 +1,17 @@ +#include + +int main() +{ + +#if defined(OMPI_MAJOR_VERSION) \ + && OMPI_MAJOR_VERSION > 2 \ + || ( OMPI_MAJOR_VERSION == 2 \ + && OMPI_MINOR_VERSION >= 1 \ + && OMPI_RELEASE_VERSION >= 1) + // Open MPI >=2.1.1 is fine + return 0; +#else +#error "Open MPI version with broken alignment of shared memory windows detected!" +#endif +} + diff --git a/CMakeExt/Code/test_mpi_support.c b/CMakeExt/Code/test_mpi_support.c new file mode 100644 index 000000000..af6bb2011 --- /dev/null +++ b/CMakeExt/Code/test_mpi_support.c @@ -0,0 +1,12 @@ +#include + +int main() +{ + +#if MPI_VERSION >= 3 + return 0; +#else +#error "Support for at least MPI 3.0 required!" +#endif +} + diff --git a/CMakeExt/HDF5.cmake b/CMakeExt/HDF5.cmake index 2a80c6851..7f4fbd129 100644 --- a/CMakeExt/HDF5.cmake +++ b/CMakeExt/HDF5.cmake @@ -63,7 +63,7 @@ if(HDF5_FOUND) check_symbol_exists(H5_HAVE_PARALLEL "H5pubconf.h" HAVE_H5_PARALLEL) cmake_pop_check_state() - if(NOT HAVE_H5_PARALLEL) + if(NOT HAVE_H5_PARALLEL OR "${MPI_IMPL_ID}" STREQUAL "") message(STATUS "HDF5 provides only serial version") set(HDF5_FOUND OFF CACHE BOOL "HDF5_FOUND" FORCE) unset(HDF5_LIBRARIES) diff --git a/CMakeExt/MPI.cmake b/CMakeExt/MPI.cmake index fc2eaf00a..c1e4a33e5 100644 --- a/CMakeExt/MPI.cmake +++ b/CMakeExt/MPI.cmake @@ -1,57 +1,156 @@ INCLUDE (CheckSymbolExists) INCLUDE (CMakePushCheckState) -if (NOT $ENV{MPI_C_COMPILER} STREQUAL "") - set(MPI_C_COMPILER $ENV{MPI_C_COMPILER} - CACHE STRING "MPI C compiler") -endif() -if (NOT $ENV{MPI_CXX_COMPILER} STREQUAL "") - set(MPI_CXX_COMPILER $ENV{MPI_CXX_COMPILER} - CACHE STRING "MPI C++ compiler") -endif() - -find_package(MPI) - -if (MPI_INCLUDE_PATH AND MPI_LIBRARY) - set(MPI_FOUND TRUE CACHE BOOL "Found the MPI library") - if ("${MPI_INCLUDE_PATH}" MATCHES "mpich") - set(MPI_IMPL_IS_MPICH TRUE CACHE BOOL "MPICH detected") - set(MPI_IMPL_ID "mpich" CACHE STRING "MPI implementation identifier") - elseif ("${MPI_INCLUDE_PATH}" MATCHES "cray") - set(MPI_IMPL_IS_CRAY TRUE CACHE BOOL "CrayMPI detected") - set(MPI_IMPL_ID "craympi" CACHE STRING "MPI implementation identifier") - elseif ("${MPI_INCLUDE_PATH}" MATCHES "mvapich") - set(MPI_IMPL_IS_MVAPICH TRUE CACHE BOOL "MVAPICH detected") - set(MPI_IMPL_ID "mvapich" CACHE STRING "MPI implementation identifier") - elseif ("${MPI_INCLUDE_PATH}" MATCHES "impi" - OR "${MPI_INCLUDE_PATH}" MATCHES "intel") - set(MPI_IMPL_IS_INTEL TRUE CACHE BOOL "IntelMPI detected") - set(MPI_IMPL_ID "intelmpi" CACHE STRING "MPI implementation identifier") - elseif ("${MPI_INCLUDE_PATH}" MATCHES "openmpi") - set(MPI_IMPL_IS_OPENMPI TRUE CACHE BOOL "OpenMPI detected") - set(MPI_IMPL_ID "openmpi" CACHE STRING "MPI implementation identifier") - # temporarily disable shared memory windows due to alignment problems - set(ENABLE_SHARED_WINDOWS OFF) - message(WARNING "MPI shared windows disabled due to defective allocation in OpenMPI") +if (NOT DEFINED MPI_IMPL_ID) + + if (NOT $ENV{MPI_C_COMPILER} STREQUAL "") + set(MPI_C_COMPILER $ENV{MPI_C_COMPILER} + CACHE STRING "MPI C compiler") + endif() + if (NOT $ENV{MPI_CXX_COMPILER} STREQUAL "") + set(MPI_CXX_COMPILER $ENV{MPI_CXX_COMPILER} + CACHE STRING "MPI C++ compiler") + endif() + + # find MPI environment + find_package(MPI) + + # helper function that executes the MPI compiler + # on the given source file and sets + # resvar to true if the compile step succeeded + function (check_mpi_compile sourcefile resvar) + + # check for MPI-3 + get_filename_component(filename ${sourcefile} NAME) + execute_process( + COMMAND "${MPI_C_COMPILER}" -c "${sourcefile}" -o "${CMAKE_BINARY_DIR}/${filename}.o" + RESULT_VARIABLE RETURN_VAL + OUTPUT_VARIABLE OUTPUT + ERROR_VARIABLE OUTPUT + ) + + if (RETURN_VAL EQUAL 0) + set (${resvar} TRUE PARENT_SCOPE) + else () + set (${resvar} FALSE PARENT_SCOPE) + message (STATUS "Failed to execute MPI compiler: \n${OUTPUT}") + endif () + + endfunction () + + + # Determine MPI implementation + + # save current state + cmake_push_check_state() + set (CMAKE_REQUIRED_INCLUDES ${MPI_INCLUDE_PATH}) + + # check for Open MPI + check_symbol_exists( + OMPI_MAJOR_VERSION + mpi.h + HAVE_OPEN_MPI + ) + if (HAVE_OPEN_MPI) + set (MPI_IMPL_IS_OPENMPI TRUE CACHE BOOL "OpenMPI detected") + set (MPI_IMPL_ID "openmpi" CACHE STRING "MPI implementation identifier") + check_mpi_compile(${CMAKE_SOURCE_DIR}/CMakeExt/Code/test_compatible_ompi.c OMPI_OK) + if (NOT OMPI_OK) + message(WARNING + "Disabling shared memory window support due to defective allocation " + "in OpenMPI <2.1.1") + set (ENABLE_SHARED_WINDOWS OFF) + endif() + endif() + + # order matters: all of the following + # implementations also define MPICH + if (NOT DEFINED MPI_IMPL_ID) + # check for Intel MPI + check_symbol_exists( + I_MPI_VERSION + mpi.h + HAVE_I_MPI + ) + if (HAVE_I_MPI) + set (MPI_IMPL_IS_INTEL TRUE CACHE BOOL "IntelMPI detected") + set (MPI_IMPL_ID "intelmpi" CACHE STRING "MPI implementation identifier") + endif () + endif () + + if (NOT DEFINED MPI_IMPL_ID) + # check for MVAPICH + check_symbol_exists( + MVAPICH2_VERSION + mpi.h + HAVE_MVAPICH + ) + if (HAVE_MVAPICH) + set (MPI_IMPL_IS_MVAPICH TRUE CACHE BOOL "MVAPICH detected") + set (MPI_IMPL_ID "mvapich" CACHE STRING "MPI implementation identifier") + endif () + endif () + + if (NOT DEFINED MPI_IMPL_ID) + # check for Cray MPI + check_symbol_exists( + CRAY_MPICH_VERSION + mpi.h + HAVE_CRAY_MPI + ) + if (NOT HAVE_CRAY_MPI) + # fall-back for versions prior to MPT 7.6.0 + # MPIX_PortName_Backlog is a Cray extension + check_symbol_exists( + MPIX_PortName_Backlog + mpi.h + HAVE_CRAY_MPI + ) + endif() + if (HAVE_CRAY_MPI) + set(MPI_IMPL_IS_CRAY TRUE CACHE BOOL "CrayMPI detected") + set(MPI_IMPL_ID "craympi" CACHE STRING "MPI implementation identifier") + endif () + endif () + + if (NOT DEFINED MPI_IMPL_ID) + # check for MVAPICH + check_symbol_exists( + MPICH + mpi.h + HAVE_MPICH + ) + if (HAVE_MPICH) + set (MPI_IMPL_IS_MPICH TRUE CACHE BOOL "MPICH detected") + set (MPI_IMPL_ID "mpich" CACHE STRING "MPI implementation identifier") + endif () + endif () + + # restore state + cmake_pop_check_state() + + if (NOT DEFINED MPI_IMPL_ID) + set (MPI_IMPL_ID "UNKNOWN" CACHE STRING "MPI implementation identifier") endif() -else (MPI_INCLUDE_PATH AND MPI_LIBRARY) - set(MPI_FOUND FALSE CACHE BOOL "Did not find the MPI library") -endif (MPI_INCLUDE_PATH AND MPI_LIBRARY) + message(STATUS "Detected MPI implementation: ${MPI_IMPL_ID}") + message(STATUS "Detected MPI C compiler: ${MPI_C_COMPILER}") -# check for MPI-3 + check_mpi_compile(${CMAKE_SOURCE_DIR}/CMakeExt/Code/test_mpi_support.c HAVE_MPI3) -# save current state -cmake_push_check_state() -set(CMAKE_REQUIRED_INCLUDES ${MPI_INCLUDE_PATH}) -check_symbol_exists( - MPI_NO_OP - mpi.h - HAVE_MPI_NO_OP -) -cmake_pop_check_state() + if (NOT HAVE_MPI3) + message(${OUTPUT}) + set(MPI_IS_DART_COMPATIBLE FALSE CACHE BOOL + "MPI LIB has support for MPI-3") + message (WARNING + "Detected MPI implementation (${MPI_IMPL_ID}) does not support MPI-3") + message (STATUS "${OUTPUT}") + unset (MPI_IMPL_ID CACHE) + else() + set(MPI_IS_DART_COMPATIBLE TRUE CACHE BOOL + "MPI LIB has support for MPI-3") + endif() -if (NOT HAVE_MPI_NO_OP) - message(FATAL_ERROR "Detected MPI library does not support MPI-3.") -endif() + set (CMAKE_C_COMPILER ${CMAKE_C_COMPILER_SAFE}) +endif(NOT DEFINED MPI_IMPL_ID) diff --git a/CMakeLists.txt b/CMakeLists.txt index c061850a8..cada2dccc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,7 +305,7 @@ message(INFO "Enabled DART backends: (DART_IMPLEMENTATIONS) " ${DART_IMPLEMENTATIONS}) message(INFO "C compiler id: ${CMAKE_C_COMPILER_ID}") message(INFO "C++ compiler id: ${CMAKE_CXX_COMPILER_ID}") -if (MPI_FOUND) +if (DEFINED MPI_IMPL_ID) message(INFO "MPI implementation: " ${MPI_IMPL_ID}) endif() diff --git a/dart-impl/CMakeLists.txt b/dart-impl/CMakeLists.txt index bce84fba4..29ea3b986 100644 --- a/dart-impl/CMakeLists.txt +++ b/dart-impl/CMakeLists.txt @@ -4,6 +4,7 @@ set(DART_IMPLEMENTATIONS_LIST ${DART_IMPLEMENTATIONS_LIST} set(ENABLE_THREADSUPPORT ${ENABLE_THREADSUPPORT} PARENT_SCOPE) + if (ENABLE_THREADSUPPORT) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDART_ENABLE_THREADSUPPORT") @@ -28,6 +29,9 @@ add_subdirectory(base) # DART implementation of every enabled DART variant: if (";${DART_IMPLEMENTATIONS_LIST};" MATCHES ";mpi;") + if(NOT MPI_IS_DART_COMPATIBLE) + message(FATAL_ERROR "Detected MPI library does not support MPI-3.") + endif() set(DART_IMPLEMENTATION_MPI_ENABLED ON CACHE BOOL INTERNAL FORCE) add_subdirectory(mpi) diff --git a/dash/include/dash/io/hdf5/StorageDriver.h b/dash/include/dash/io/hdf5/StorageDriver.h index 47c2ffbc7..2fc98a137 100644 --- a/dash/include/dash/io/hdf5/StorageDriver.h +++ b/dash/include/dash/io/hdf5/StorageDriver.h @@ -5,6 +5,10 @@ #ifdef DASH_ENABLE_HDF5 +#ifndef MPI_IMPL_ID +#pragma error "HDF5 module requires dart-mpi" +#endif + #include #include #include @@ -28,10 +32,6 @@ #include #include -#ifndef MPI_IMPL_ID -#pragma error "HDF5 module requires dart-mpi" -#endif - #include namespace dash {