diff --git a/test/emu/CMakeLists.txt b/test/emu/CMakeLists.txt index 4d3c6de..9768c38 100644 --- a/test/emu/CMakeLists.txt +++ b/test/emu/CMakeLists.txt @@ -12,3 +12,4 @@ add_subdirectory(ovni) add_subdirectory(nosv) add_subdirectory(nanos6) add_subdirectory(tampi) +add_subdirectory(mpi) diff --git a/test/emu/mpi/CMakeLists.txt b/test/emu/mpi/CMakeLists.txt new file mode 100644 index 0000000..610c85e --- /dev/null +++ b/test/emu/mpi/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Barcelona Supercomputing Center (BSC) +# SPDX-License-Identifier: GPL-3.0-or-later + +test_emu(func.c MP) +test_emu(func-mismatch.c SHOULD_FAIL + REGEX "thread [0-9]\\+ ended with 1 stacked mpi functions") +test_emu(func-nested.c SHOULD_FAIL + REGEX "same value as last_value") diff --git a/test/emu/mpi/func-mismatch.c b/test/emu/mpi/func-mismatch.c new file mode 100644 index 0000000..2ccc20c --- /dev/null +++ b/test/emu/mpi/func-mismatch.c @@ -0,0 +1,23 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include "compat.h" +#include "instr.h" +#include "instr_mpi.h" + +int +main(void) +{ + /* Test that a thread ending while there is still a mpi function in the + * stack causes the emulator to fail */ + + instr_start(0, 1); + + instr_mpi_init_thread_enter(); + /* The thread is left in the MPI_Init_thread state (should fail) */ + + instr_end(); + + return 0; +} diff --git a/test/emu/mpi/func-nested.c b/test/emu/mpi/func-nested.c new file mode 100644 index 0000000..acbeac8 --- /dev/null +++ b/test/emu/mpi/func-nested.c @@ -0,0 +1,26 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include "compat.h" +#include "instr.h" +#include "instr_mpi.h" + +int +main(void) +{ + /* Test that a thread calling the mpi function that is already executing + * causes the emulator to fail */ + + instr_start(0, 1); + + instr_mpi_init_thread_enter(); + /* The thread runs the same mpi function in a nested way (should fail) */ + instr_mpi_init_thread_enter(); + instr_mpi_init_thread_exit(); + instr_mpi_init_thread_exit(); + + instr_end(); + + return 0; +} diff --git a/test/emu/mpi/func.c b/test/emu/mpi/func.c new file mode 100644 index 0000000..411f7c7 --- /dev/null +++ b/test/emu/mpi/func.c @@ -0,0 +1,65 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include "compat.h" +#include "instr.h" +#include "instr_mpi.h" + +int +main(void) +{ + /* Test that simulates the execution of MPI functions */ + + const int rank = atoi(getenv("OVNI_RANK")); + const int nranks = atoi(getenv("OVNI_NRANKS")); + + instr_start(rank, nranks); + + /* Initialize MPI */ + instr_mpi_init_thread_enter(); + instr_mpi_init_thread_exit(); + + /* Issue a non-blocking broadcast */ + instr_mpi_ibcast_enter(); + instr_mpi_ibcast_exit(); + + /* Wait the broadcast request */ + instr_mpi_wait_enter(); + instr_mpi_wait_exit(); + + /* Perform a barrier */ + instr_mpi_barrier_enter(); + instr_mpi_barrier_exit(); + + const int ncomms = 100; + + /* Simulate multiple nonb-blocking communications */ + for (int c = 0; c < ncomms; c++) { + /* Issue a non-blocking synchronous send */ + instr_mpi_issend_enter(); + instr_mpi_issend_exit(); + + /* Issue a non-blocking receive */ + instr_mpi_irecv_enter(); + instr_mpi_irecv_exit(); + } + + /* Simulate testsome calls until all communications are completed */ + for (int c = 0; c < ncomms; c++) { + instr_mpi_testsome_enter(); + instr_mpi_testsome_exit(); + } + + /* Allreduce a value */ + instr_mpi_allreduce_enter(); + instr_mpi_allreduce_exit(); + + /* Finalize MPI */ + instr_mpi_finalize_enter(); + instr_mpi_finalize_exit(); + + instr_end(); + + return 0; +} diff --git a/test/emu/mpi/instr_mpi.h b/test/emu/mpi/instr_mpi.h new file mode 100644 index 0000000..9dde6aa --- /dev/null +++ b/test/emu/mpi/instr_mpi.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef INSTR_MPI_H +#define INSTR_MPI_H + +#include "instr.h" + +INSTR_0ARG(instr_mpi_init_thread_enter, "MUt") +INSTR_0ARG(instr_mpi_init_thread_exit, "MUT") +INSTR_0ARG(instr_mpi_finalize_enter, "MUf") +INSTR_0ARG(instr_mpi_finalize_exit, "MUF") + +INSTR_0ARG(instr_mpi_wait_enter, "MW[") +INSTR_0ARG(instr_mpi_wait_exit, "MW]") +INSTR_0ARG(instr_mpi_testsome_enter, "MTs") +INSTR_0ARG(instr_mpi_testsome_exit, "MTS") + +INSTR_0ARG(instr_mpi_issend_enter, "Mss") +INSTR_0ARG(instr_mpi_issend_exit, "MsS") +INSTR_0ARG(instr_mpi_irecv_enter, "Mr[") +INSTR_0ARG(instr_mpi_irecv_exit, "Mr]") + +INSTR_0ARG(instr_mpi_barrier_enter, "MCb") +INSTR_0ARG(instr_mpi_barrier_exit, "MCB") +INSTR_0ARG(instr_mpi_allreduce_enter, "MAr") +INSTR_0ARG(instr_mpi_allreduce_exit, "MAR") +INSTR_0ARG(instr_mpi_ibcast_enter, "Mdb") +INSTR_0ARG(instr_mpi_ibcast_exit, "MdB") + +#endif /* INSTR_MPI_H */