Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add miniapps as tests #1112

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a4f9fae
Add miniapps as tests
msimberg Mar 19, 2024
d24895e
TEMP
msimberg Mar 21, 2024
0f5a552
Update TEST_BINARIES filter to ignore everything but full paths
msimberg Mar 20, 2024
f9a95c7
Move DLAF_PIKATEST_EXTRA_ARGS variable to DLAF_AddTest.cmake
msimberg Mar 20, 2024
972aa37
Move CMake test options to main CMakeLists.txt to make available for …
msimberg Mar 20, 2024
8b5067b
Add category label to unit tests
msimberg Apr 8, 2024
01218fb
Fix TEST_BINARIES variable in codecov CI configuration
msimberg Apr 9, 2024
ff5bc61
Fix gtest linking for tests
msimberg Apr 9, 2024
e754585
Use pika::wait instead of waitLocalTiles in miniapps
msimberg Apr 10, 2024
944e6bd
Update GitLab CI test job names to exclude CATEGORY_ prefix
msimberg Apr 23, 2024
f081e0e
Revert "Use pika::wait instead of waitLocalTiles in miniapps"
msimberg May 27, 2024
c5daa65
Wait for all communicators in miniapp_cholesky
msimberg May 27, 2024
63eb150
Wait for all communicators in miniapp_reduction_to_band
msimberg May 27, 2024
bf6ee7b
Wait for all communicators in miniapp_eigensolver
msimberg May 27, 2024
fb29737
Wait for all communicators in miniapp_gen_eigensolver
msimberg May 27, 2024
0abe465
Wait for all communicators in miniapp_triangular_multiplication
msimberg May 28, 2024
eee19fd
Add helper member function for waiting for all communication to compl…
msimberg Sep 25, 2024
9b71b31
Simplify check for no tests in ctest_to_gitlab.sh
msimberg Sep 25, 2024
a49c151
Remove unused using sync_wait
msimberg Sep 27, 2024
98b1729
Merge remote-tracking branch 'origin/master' into miniapps-as-tests
msimberg Oct 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .cmake-format.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@
"ARGUMENTS": '*',
"USE_MAIN": '1',
"MPIRANKS": '1',
"CATEGORY": '1',
}
},
"DLAF_addTargetTest": {
"pargs": 1,
"flags": [],
"kwargs": {
"ARGUMENTS": '*',
"USE_MAIN": '1',
"MPIRANKS": '1',
"CATEGORY": '1',
}
},
"DLAF_addMiniapp": {
Expand Down
22 changes: 22 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,28 @@ add_subdirectory(external)
# ---------------------------------------------------------------------------
add_subdirectory(src)

# ---------------------------------------------------------------------------
# Test options (apply to unit tests and miniapps as tests)
# ---------------------------------------------------------------------------
set(DLAF_PRESET_OPTIONS "plain-mpi" "slurm" "custom")
set(DLAF_MPI_PRESET "plain-mpi" CACHE STRING "Select a preset to use")
set_property(CACHE DLAF_MPI_PRESET PROPERTY STRINGS ${DLAF_PRESET_OPTIONS})
option(
DLAF_CI_RUNNER_USES_MPIRUN
"Remove mpiexec command for tests executed by ctest. This option is to be used if the CI runner executes the tests with <mpiexec + options> ctest -L RANK_<spawned MPI ranks>"
OFF
)

# On some machines, tests using multiple ranks + oversubscribing run
# significantly faster when threads are not pinned.
option(DLAF_TEST_THREAD_BINDING_ENABLED "If OFF disables pika thread binding." ON)

# If DLAF_CI_RUNNER_USES_MPIRUN=on we don't want to use any preset, so we just go for the custom one
# without setting any variable.
if(DLAF_CI_RUNNER_USES_MPIRUN)
set(DLAF_MPI_PRESET "custom" CACHE STRING "" FORCE)
endif()

# ---------------------------------------------------------------------------
# mini Apps
# ---------------------------------------------------------------------------
Expand Down
36 changes: 23 additions & 13 deletions ci/ctest_to_gitlab.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ upload_reports:
"
JOB_TEMPLATE="

{{LABEL}}:
{{CATEGORY_LABEL_NOPREFIX}}_{{RANK_LABEL}}:
stage: test
extends: .daint
variables:
Expand All @@ -61,7 +61,7 @@ JOB_TEMPLATE="
USE_MPI: 'YES'
DISABLE_AFTER_SCRIPT: 'YES'
DLAF_HDF5_TEST_OUTPUT_PATH: \$CI_PROJECT_DIR
script: mpi-ctest -L {{LABEL}}
script: mpi-ctest -L {{CATEGORY_LABEL}} -L {{RANK_LABEL}}
artifacts:
paths:
- codecov-reports/"
Expand All @@ -87,7 +87,7 @@ variables:
"

JOB_TEMPLATE="
{{LABEL}}:
{{CATEGORY_LABEL_NOPREFIX}}_{{RANK_LABEL}}:
stage: test
extends: .daint
variables:
Expand All @@ -100,20 +100,30 @@ JOB_TEMPLATE="
USE_MPI: 'YES'
DISABLE_AFTER_SCRIPT: 'YES'
DLAF_HDF5_TEST_OUTPUT_PATH: \$CI_PROJECT_DIR
script: mpi-ctest -L {{LABEL}}"
script: mpi-ctest -L {{CATEGORY_LABEL}} -L {{RANK_LABEL}}"
fi

JOBS=""

for label in `ctest --print-labels | egrep -o "RANK_[1-9][0-9]?"`; do
N=`echo "$label" | sed "s/RANK_//"`
C=$(( THREADS_PER_NODE / N ))

JOB=`echo "$JOB_TEMPLATE" | sed "s|{{LABEL}}|$label|g" \
| sed "s|{{NTASKS}}|$N|g" \
| sed "s|{{CPUS_PER_TASK}}|$C|g"`

JOBS="$JOBS$JOB"
for rank_label in `ctest --print-labels | egrep -o "RANK_[1-9][0-9]?"`; do
for category_label in `ctest --print-labels | egrep -o "CATEGORY_[A-Z]+"`; do
N=`echo "$rank_label" | sed "s/RANK_//"`
C=$(( THREADS_PER_NODE / N ))

# Skip label combinations that match no tests
if [[ "$(ctest -N -L $category_label -L $rank_label | tail -n1)" == "Total Tests: 0" ]]; then
continue
fi

category_label_noprefix=`echo "$category_label" | sed "s/CATEGORY_//"`
JOB=`echo "$JOB_TEMPLATE" | sed "s|{{CATEGORY_LABEL_NOPREFIX}}|$category_label_noprefix|g" \
| sed "s|{{CATEGORY_LABEL}}|$category_label|g" \
| sed "s|{{RANK_LABEL}}|$rank_label|g" \
| sed "s|{{NTASKS}}|$N|g" \
| sed "s|{{CPUS_PER_TASK}}|$C|g"`

JOBS="$JOBS$JOB"
done
done

echo "${BASE_TEMPLATE/'{{JOBS}}'/$JOBS}"
130 changes: 88 additions & 42 deletions cmake/DLAF_AddTest.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# [LIBRARIES <arguments for target_link_libraries>]
# [MPIRANKS <number of rank>]
# [USE_MAIN {PLAIN | PIKA | MPI | MPIPIKA}]
# [CATEGORY <category>]
# )
#
# At least one source file has to be specified, while other parameters are optional.
Expand Down Expand Up @@ -45,6 +46,8 @@
# include/
# )

set(DLAF_PIKATEST_EXTRA_ARGS "" CACHE STRING "Extra arguments for tests with pika")

# Check if LIST_NAME contains at least an element that matches ELEMENT_REGEX. If not, add FALLBACK
# to the list.
function(_set_element_to_fallback_value LIST_NAME ELEMENT_REGEX FALLBACK)
Expand All @@ -57,72 +60,70 @@ function(_set_element_to_fallback_value LIST_NAME ELEMENT_REGEX FALLBACK)
endif()
endfunction()

function(DLAF_addTest test_target_name)
function(DLAF_addTargetTest test_target_name)
set(options "")
set(oneValueArgs MPIRANKS USE_MAIN)
set(multiValueArgs SOURCES COMPILE_DEFINITIONS INCLUDE_DIRS LIBRARIES ARGUMENTS)
cmake_parse_arguments(DLAF_AT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(oneValueArgs CATEGORY MPIRANKS USE_MAIN)
set(multiValueArgs ARGUMENTS)
cmake_parse_arguments(DLAF_ATT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

### Checks
if(DLAF_AT_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown arguments ${DLAF_AT_UNPARSED_ARGUMENTS}")
endif()

if(NOT DLAF_AT_SOURCES)
message(FATAL_ERROR "No sources specified for this test")
if(DLAF_ATT_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown arguments ${DLAF_ATT_UNPARSED_ARGUMENTS}")
endif()

set(IS_AN_MPI_TEST FALSE)
set(IS_AN_PIKA_TEST FALSE)
if(NOT DLAF_AT_USE_MAIN)
set(_gtest_tgt gtest)
elseif(DLAF_AT_USE_MAIN STREQUAL PLAIN)
set(_gtest_tgt gtest_main)
elseif(DLAF_AT_USE_MAIN STREQUAL PIKA)
set(_gtest_tgt DLAF_gtest_pika_main)
if(NOT DLAF_ATT_USE_MAIN OR DLAF_ATT_USE_MAIN STREQUAL PLAIN)

elseif(DLAF_ATT_USE_MAIN STREQUAL PIKA)
set(IS_AN_PIKA_TEST TRUE)
elseif(DLAF_AT_USE_MAIN STREQUAL MPI)
set(_gtest_tgt DLAF_gtest_mpi_main)
elseif(DLAF_ATT_USE_MAIN STREQUAL MPI)
set(IS_AN_MPI_TEST TRUE)
elseif(DLAF_AT_USE_MAIN STREQUAL MPIPIKA)
set(_gtest_tgt DLAF_gtest_mpipika_main)
elseif(DLAF_ATT_USE_MAIN STREQUAL MPIPIKA)
set(IS_AN_MPI_TEST TRUE)
set(IS_AN_PIKA_TEST TRUE)
elseif(DLAF_AT_USE_MAIN STREQUAL CAPI)
set(_gtest_tgt DLAF_gtest_mpi_main)
elseif(DLAF_ATT_USE_MAIN STREQUAL CAPI)
set(IS_AN_MPI_TEST TRUE)
else()
message(FATAL_ERROR "USE_MAIN=${DLAF_AT_USE_MAIN} is not a supported option")
message(FATAL_ERROR "USE_MAIN=${DLAF_ATT_USE_MAIN} is not a supported option")
endif()

set(_TEST_LABELS)

if(NOT DLAF_ATT_CATEGORY)
set(DLAF_ATT_CATEGORY "UNIT")
endif()

list(APPEND _TEST_LABELS "CATEGORY_${DLAF_ATT_CATEGORY}")

if(IS_AN_MPI_TEST)
if(NOT DLAF_AT_MPIRANKS)
if(NOT DLAF_ATT_MPIRANKS)
message(FATAL_ERROR "You are asking for an MPI external main without specifying MPIRANKS")
endif()
if(NOT DLAF_AT_MPIRANKS GREATER 0)
message(FATAL_ERROR "Wrong MPIRANKS number ${DLAF_AT_MPIRANKS}")
if(NOT DLAF_ATT_MPIRANKS GREATER 0)
message(FATAL_ERROR "Wrong MPIRANKS number ${DLAF_ATT_MPIRANKS}")
endif()
if(DLAF_AT_MPIRANKS GREATER MPIEXEC_MAX_NUMPROCS)
if(DLAF_ATT_MPIRANKS GREATER MPIEXEC_MAX_NUMPROCS)
message(
WARNING
"\
YOU ARE ASKING FOR ${DLAF_AT_MPIRANKS} RANKS, BUT THERE ARE JUST ${MPIEXEC_MAX_NUMPROCS} CORES.
YOU ARE ASKING FOR ${DLAF_ATT_MPIRANKS} RANKS, BUT THERE ARE JUST ${MPIEXEC_MAX_NUMPROCS} CORES.
You can adjust MPIEXEC_MAX_NUMPROCS value to suppress this warning.
Using OpenMPI may require to set the environment variable OMPI_MCA_rmaps_base_oversubscribe=1."
)
endif()
else()
if(DLAF_AT_MPIRANKS)
if(DLAF_ATT_MPIRANKS)
message(FATAL_ERROR "You specified MPIRANKS and asked for an external main without MPI")
else()
set(DLAF_AT_MPIRANKS 1)
set(DLAF_ATT_MPIRANKS 1)
endif()
endif()

### Test target
set(DLAF_TEST_RUNALL_WITH_MPIEXEC OFF CACHE BOOL "Run all tests using the workload manager.")

set(_TEST_ARGUMENTS ${DLAF_AT_ARGUMENTS})
set(_TEST_ARGUMENTS ${DLAF_ATT_ARGUMENTS})

if(DLAF_TEST_RUNALL_WITH_MPIEXEC OR IS_AN_MPI_TEST)
if(MPIEXEC_NUMCORE_FLAG)
Expand All @@ -132,7 +133,7 @@ function(DLAF_addTest test_target_name)
set(_CORES_PER_RANK 1)
endif()

math(EXPR DLAF_CORE_PER_RANK "${_CORES_PER_RANK}/${DLAF_AT_MPIRANKS}")
math(EXPR DLAF_CORE_PER_RANK "${_CORES_PER_RANK}/${DLAF_ATT_MPIRANKS}")

if(NOT DLAF_CORE_PER_RANK)
set(DLAF_CORE_PER_RANK 1)
Expand All @@ -148,29 +149,29 @@ function(DLAF_addTest test_target_name)
else()
separate_arguments(MPIEXEC_PREFLAGS)
set(_TEST_COMMAND
${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${DLAF_AT_MPIRANKS} ${_MPI_CORE_ARGS}
${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${DLAF_ATT_MPIRANKS} ${_MPI_CORE_ARGS}
${MPIEXEC_PREFLAGS} ${DLAF_TEST_PREFLAGS} $<TARGET_FILE:${test_target_name}>
${DLAF_TEST_POSTFLAGS} ${MPIEXEC_POSTFLAGS}
)
endif()
set(_TEST_LABEL "RANK_${DLAF_AT_MPIRANKS}")
list(APPEND _TEST_LABELS "RANK_${DLAF_ATT_MPIRANKS}")

else()
# ----- Classic test
set(_TEST_COMMAND ${DLAF_TEST_PREFLAGS} $<TARGET_FILE:${test_target_name}> ${DLAF_TEST_POSTFLAGS})
set(_TEST_LABEL "RANK_1")
list(APPEND _TEST_LABELS "RANK_1")
endif()

if(IS_AN_PIKA_TEST)
separate_arguments(_PIKA_EXTRA_ARGS_LIST UNIX_COMMAND ${DLAF_PIKATEST_EXTRA_ARGS})

# --pika:bind=none is useful just in case more ranks are going to be allocated on the same node.
if(IS_AN_MPI_TEST AND (DLAF_AT_MPIRANKS GREATER 1) AND (NOT DLAF_TEST_THREAD_BINDING_ENABLED))
if(IS_AN_MPI_TEST AND (DLAF_ATT_MPIRANKS GREATER 1) AND (NOT DLAF_TEST_THREAD_BINDING_ENABLED))
_set_element_to_fallback_value(_PIKA_EXTRA_ARGS_LIST "--pika:bind" "--pika:bind=none")
endif()

if(IS_AN_MPI_TEST AND DLAF_MPI_PRESET STREQUAL "plain-mpi")
math(EXPR _DLAF_PIKA_THREADS "${MPIEXEC_MAX_NUMPROCS}/${DLAF_AT_MPIRANKS}")
math(EXPR _DLAF_PIKA_THREADS "${MPIEXEC_MAX_NUMPROCS}/${DLAF_ATT_MPIRANKS}")

if(_DLAF_PIKA_THREADS LESS 2)
set(_DLAF_PIKA_THREADS 2)
Expand All @@ -186,16 +187,16 @@ function(DLAF_addTest test_target_name)

# Special treatment for C API tests
# C API tests require pika arguments to be hard-coded in the test file
if(DLAF_AT_USE_MAIN STREQUAL CAPI)
if(DLAF_ATT_USE_MAIN STREQUAL CAPI)
separate_arguments(_PIKA_EXTRA_ARGS_LIST_CAPI UNIX_COMMAND ${DLAF_PIKATEST_EXTRA_ARGS})

# --pika:bind=none is useful just in case more ranks are going to be allocated on the same node.
if((DLAF_AT_MPIRANKS GREATER 1) AND (NOT DLAF_TEST_THREAD_BINDING_ENABLED))
if((DLAF_ATT_MPIRANKS GREATER 1) AND (NOT DLAF_TEST_THREAD_BINDING_ENABLED))
_set_element_to_fallback_value(_PIKA_EXTRA_ARGS_LIST_CAPI "--pika:bind" "--pika:bind=none")
endif()

if(IS_AN_MPI_TEST AND DLAF_MPI_PRESET STREQUAL "plain-mpi")
math(EXPR _DLAF_PIKA_THREADS "${MPIEXEC_MAX_NUMPROCS}/${DLAF_AT_MPIRANKS}")
math(EXPR _DLAF_PIKA_THREADS "${MPIEXEC_MAX_NUMPROCS}/${DLAF_ATT_MPIRANKS}")

if(_DLAF_PIKA_THREADS LESS 2)
set(_DLAF_PIKA_THREADS 2)
Expand All @@ -215,11 +216,50 @@ function(DLAF_addTest test_target_name)

endif()

add_test(NAME ${test_target_name} COMMAND ${_TEST_COMMAND} ${_TEST_ARGUMENTS})
set_tests_properties(${test_target_name} PROPERTIES LABELS "${_TEST_LABELS}")
endfunction()

function(DLAF_addTest test_target_name)
set(options "")
set(oneValueArgs MPIRANKS USE_MAIN)
set(multiValueArgs SOURCES COMPILE_DEFINITIONS INCLUDE_DIRS LIBRARIES ARGUMENTS)
cmake_parse_arguments(DLAF_AT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})

### Checks
if(DLAF_AT_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown arguments ${DLAF_AT_UNPARSED_ARGUMENTS}")
endif()

if(NOT DLAF_AT_SOURCES)
message(FATAL_ERROR "No sources specified for this test")
endif()

if(NOT DLAF_AT_USE_MAIN)
set(_gtest_tgt gtest)
elseif(DLAF_AT_USE_MAIN STREQUAL PLAIN)
set(_gtest_tgt gtest_main)
elseif(DLAF_AT_USE_MAIN STREQUAL PIKA)
set(_gtest_tgt DLAF_gtest_pika_main)
elseif(DLAF_AT_USE_MAIN STREQUAL MPI)
set(_gtest_tgt DLAF_gtest_mpi_main)
elseif(DLAF_AT_USE_MAIN STREQUAL MPIPIKA)
set(_gtest_tgt DLAF_gtest_mpipika_main)
elseif(DLAF_AT_USE_MAIN STREQUAL CAPI)
set(_gtest_tgt DLAF_gtest_mpi_main)
else()
message(FATAL_ERROR "USE_MAIN=${DLAF_AT_USE_MAIN} is not a supported option")
endif()

### Test executable target
add_executable(${test_target_name} ${DLAF_AT_SOURCES})
target_link_libraries(
${test_target_name} PRIVATE ${_gtest_tgt} DLAF_test ${DLAF_AT_LIBRARIES} dlaf.prop_private
)
set(IS_AN_MPI_TEST FALSE)
if(DLAF_AT_USE_MAIN MATCHES MPI OR DLAF_AT_USE_MAIN STREQUAL CAPI)
set(IS_AN_MPI_TEST TRUE)
endif()
target_compile_definitions(
${test_target_name} PRIVATE ${DLAF_AT_COMPILE_DEFINITIONS} $<$<BOOL:${IS_AN_MPI_TEST}>:
NUM_MPI_RANKS=${DLAF_AT_MPIRANKS}>
Expand All @@ -229,8 +269,6 @@ function(DLAF_addTest test_target_name)
)
target_add_warnings(${test_target_name})
DLAF_addPrecompiledHeaders(${test_target_name})
add_test(NAME ${test_target_name} COMMAND ${_TEST_COMMAND} ${_TEST_ARGUMENTS})
set_tests_properties(${test_target_name} PROPERTIES LABELS "${_TEST_LABEL}")

### DEPLOY
include(GNUInstallDirs)
Expand All @@ -242,4 +280,12 @@ function(DLAF_addTest test_target_name)
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
endif()

### Test
DLAF_addTargetTest(
${test_target_name}
MPIRANKS ${DLAF_AT_MPIRANKS}
USE_MAIN ${DLAF_AT_USE_MAIN}
ARGUMENTS ${DLAF_AT_ARGUMENTS}
)
endfunction()
5 changes: 5 additions & 0 deletions include/dlaf/communication/communicator_grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ class CommunicatorGrid {
return col_communicator_pipeline();
}

/// Synchronization barrier for all communicators in the grid
///
/// This function returns when all communications on the communicators in the grid have completed.
void wait_all_communicators();

/// Prints information about the CommunicationGrid.
friend std::ostream& operator<<(std::ostream& out, const CommunicatorGrid& grid) {
return out << "position=" << grid.position_ << ", size=" << grid.grid_size_;
Expand Down
Loading
Loading