Add MPI model with interface view
This commit is contained in:
parent
1e2102c0a0
commit
9a628e78ca
@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Add nOS-V API subsystem events for `nosv_create()` and `nosv_destroy()`.
|
- Add nOS-V API subsystem events for `nosv_create()` and `nosv_destroy()`.
|
||||||
- Add TAMPI model with `T` code.
|
- Add TAMPI model with `T` code.
|
||||||
- Add subsytem events and cfgs for TAMPI model.
|
- Add subsytem events and cfgs for TAMPI model.
|
||||||
|
- Add MPI model with `M` code.
|
||||||
|
- Add interface events and cfgs for MPI model.
|
||||||
|
|
||||||
## [1.2.2] - 2022-07-26
|
## [1.2.2] - 2022-07-26
|
||||||
|
|
||||||
|
42
cfg/cpu/mpi/function.cfg
Normal file
42
cfg/cpu/mpi/function.cfg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ParaverCFG
|
||||||
|
ConfigFile.Version: 3.4
|
||||||
|
ConfigFile.NumWindows: 1
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
< NEW DISPLAYING WINDOW CPU: MPI function of the RUNNING thread >
|
||||||
|
################################################################################
|
||||||
|
window_name CPU: MPI function of the RUNNING thread
|
||||||
|
window_type single
|
||||||
|
window_id 1
|
||||||
|
window_position_x 0
|
||||||
|
window_position_y 0
|
||||||
|
window_width 600
|
||||||
|
window_height 150
|
||||||
|
window_comm_lines_enabled true
|
||||||
|
window_flags_enabled false
|
||||||
|
window_noncolor_mode true
|
||||||
|
window_logical_filtered true
|
||||||
|
window_physical_filtered false
|
||||||
|
window_comm_fromto true
|
||||||
|
window_comm_tagsize true
|
||||||
|
window_comm_typeval true
|
||||||
|
window_units Microseconds
|
||||||
|
window_maximum_y 1000.0
|
||||||
|
window_minimum_y 1.0
|
||||||
|
window_compute_y_max true
|
||||||
|
window_level thread
|
||||||
|
window_scale_relative 1.000000000000
|
||||||
|
window_end_time_relative 1.000000000000
|
||||||
|
window_object appl { 1, { All } }
|
||||||
|
window_begin_time_relative 0.000000000000
|
||||||
|
window_open true
|
||||||
|
window_drawmode draw_randnotzero
|
||||||
|
window_drawmode_rows draw_randnotzero
|
||||||
|
window_pixel_size 1
|
||||||
|
window_labels_to_draw 1
|
||||||
|
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||||
|
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||||
|
window_filter_module evt_type 1 25
|
||||||
|
window_filter_module evt_type_label 1 "CPU: MPI function of the RUNNING thread"
|
||||||
|
|
42
cfg/thread/mpi/function.cfg
Normal file
42
cfg/thread/mpi/function.cfg
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ParaverCFG
|
||||||
|
ConfigFile.Version: 3.4
|
||||||
|
ConfigFile.NumWindows: 1
|
||||||
|
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
< NEW DISPLAYING WINDOW Thread: MPI function of the RUNNING thread >
|
||||||
|
################################################################################
|
||||||
|
window_name Thread: MPI function of the RUNNING thread
|
||||||
|
window_type single
|
||||||
|
window_id 1
|
||||||
|
window_position_x 0
|
||||||
|
window_position_y 0
|
||||||
|
window_width 600
|
||||||
|
window_height 150
|
||||||
|
window_comm_lines_enabled true
|
||||||
|
window_flags_enabled false
|
||||||
|
window_noncolor_mode true
|
||||||
|
window_logical_filtered true
|
||||||
|
window_physical_filtered false
|
||||||
|
window_comm_fromto true
|
||||||
|
window_comm_tagsize true
|
||||||
|
window_comm_typeval true
|
||||||
|
window_units Microseconds
|
||||||
|
window_maximum_y 1000.0
|
||||||
|
window_minimum_y 1.0
|
||||||
|
window_compute_y_max true
|
||||||
|
window_level thread
|
||||||
|
window_scale_relative 1.000000000000
|
||||||
|
window_end_time_relative 1.000000000000
|
||||||
|
window_object appl { 1, { All } }
|
||||||
|
window_begin_time_relative 0.000000000000
|
||||||
|
window_open true
|
||||||
|
window_drawmode draw_randnotzero
|
||||||
|
window_drawmode_rows draw_randnotzero
|
||||||
|
window_pixel_size 1
|
||||||
|
window_labels_to_draw 1
|
||||||
|
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||||
|
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||||
|
window_filter_module evt_type 1 25
|
||||||
|
window_filter_module evt_type_label 1 "Thread: MPI function of the RUNNING thread"
|
||||||
|
|
@ -226,3 +226,110 @@ TTC Ends creating a ticket linked to a set of requests and a task
|
|||||||
TTw Begins to wait a ticket completion
|
TTw Begins to wait a ticket completion
|
||||||
TTW Ends waiting a ticket completion
|
TTW Ends waiting a ticket completion
|
||||||
```
|
```
|
||||||
|
|
||||||
|
-------------------- MPI (model=M) -------------------------
|
||||||
|
|
||||||
|
MUi Enters MPI_Init
|
||||||
|
MUI Exits MPI_Init
|
||||||
|
MUt Enters MPI_Init_thread
|
||||||
|
MUT Exits MPI_Init_thread
|
||||||
|
MUf Enters MPI_Finalize
|
||||||
|
MUF Exits MPI_Finalize
|
||||||
|
|
||||||
|
MW[ Enters MPI_Wait
|
||||||
|
MW] Exits MPI_Wait
|
||||||
|
MWa Enters MPI_Waitall
|
||||||
|
MWA Exits MPI_Waitall
|
||||||
|
MWy Enters MPI_Waitany
|
||||||
|
MWY Exits MPI_Waitany
|
||||||
|
MWs Enters MPI_Waitsome
|
||||||
|
MWS Exits MPI_Waitsome
|
||||||
|
|
||||||
|
MT[ Enters MPI_Test
|
||||||
|
MT] Exits MPI_Test
|
||||||
|
MTa Enters MPI_Testall
|
||||||
|
MTA Exits MPI_Testall
|
||||||
|
MTy Enters MPI_Testany
|
||||||
|
MTY Exits MPI_Testany
|
||||||
|
MTs Enters MPI_Testsome
|
||||||
|
MTS Exits MPI_Testsome
|
||||||
|
|
||||||
|
MS[ Enters MPI_Send
|
||||||
|
MS] Exits MPI_Send
|
||||||
|
MSb Enters MPI_Bsend
|
||||||
|
MSB Exits MPI_Bsend
|
||||||
|
MSr Enters MPI_Rsend
|
||||||
|
MSR Exits MPI_Rsend
|
||||||
|
MSs Enters MPI_Ssend
|
||||||
|
MSS Exits MPI_Ssend
|
||||||
|
MR[ Enters MPI_Recv
|
||||||
|
MR] Exits MPI_Recv
|
||||||
|
MRs Enters MPI_Sendrecv
|
||||||
|
MRS Exits MPI_Sendrecv
|
||||||
|
MRo Enters MPI_Sendrecv_replace
|
||||||
|
MRO Exits MPI_Sendrecv_replace
|
||||||
|
|
||||||
|
MAg Enters MPI_Allgather
|
||||||
|
MAG Exits MPI_Allgather
|
||||||
|
MAr Enters MPI_Allreduce
|
||||||
|
MAR Exits MPI_Allreduce
|
||||||
|
MAa Enters MPI_Alltoall
|
||||||
|
MAA Exits MPI_Alltoall
|
||||||
|
MCb Enters MPI_Barrier
|
||||||
|
MCB Exits MPI_Barrier
|
||||||
|
MCe Enters MPI_Exscan
|
||||||
|
MCE Exits MPI_Exscan
|
||||||
|
MCs Enters MPI_Scan
|
||||||
|
MCS Exits MPI_Scan
|
||||||
|
MDb Enters MPI_Bcast
|
||||||
|
MDB Exits MPI_Bcast
|
||||||
|
MDg Enters MPI_Gather
|
||||||
|
MDG Exits MPI_Gather
|
||||||
|
MDs Enters MPI_Scatter
|
||||||
|
MDS Exits MPI_Scatter
|
||||||
|
ME[ Enters MPI_Reduce
|
||||||
|
ME] Exits MPI_Reduce
|
||||||
|
MEs Enters MPI_Reduce_scatter
|
||||||
|
MES Exits MPI_Reduce_scatter
|
||||||
|
MEb Enters MPI_Reduce_scatter_block
|
||||||
|
MEB Exits MPI_Reduce_scatter_block
|
||||||
|
|
||||||
|
Ms[ Enters MPI_Isend
|
||||||
|
Ms] Exits MPI_Isend
|
||||||
|
Msb Enters MPI_Ibsend
|
||||||
|
MsB Exits MPI_Ibsend
|
||||||
|
Msr Enters MPI_Irsend
|
||||||
|
MsR Exits MPI_Irsend
|
||||||
|
Mss Enters MPI_Issend
|
||||||
|
MsS Exits MPI_Issend
|
||||||
|
Mr[ Enters MPI_Irecv
|
||||||
|
Mr] Exits MPI_Irecv
|
||||||
|
Mrs Enters MPI_Isendrecv
|
||||||
|
MrS Exits MPI_Isendrecv
|
||||||
|
Mro Enters MPI_Isendrecv_replace
|
||||||
|
MrO Exits MPI_Isendrecv_replace
|
||||||
|
|
||||||
|
Mag Enters MPI_Iallgather
|
||||||
|
MaG Exits MPI_Iallgather
|
||||||
|
Mar Enters MPI_Iallreduce
|
||||||
|
MaR Exits MPI_Iallreduce
|
||||||
|
Maa Enters MPI_Ialltoall
|
||||||
|
MaA Exits MPI_Ialltoall
|
||||||
|
Mcb Enters MPI_Ibarrier
|
||||||
|
McB Exits MPI_Ibarrier
|
||||||
|
Mce Enters MPI_Iexscan
|
||||||
|
McE Exits MPI_Iexscan
|
||||||
|
Mcs Enters MPI_Iscan
|
||||||
|
McS Exits MPI_Iscan
|
||||||
|
Mdb Enters MPI_Ibcast
|
||||||
|
MdB Exits MPI_Ibcast
|
||||||
|
Mdg Enters MPI_Igather
|
||||||
|
MdG Exits MPI_Igather
|
||||||
|
Mds Enters MPI_Iscatter
|
||||||
|
MdS Exits MPI_Iscatter
|
||||||
|
Me[ Enters MPI_Ireduce
|
||||||
|
Me] Exits MPI_Ireduce
|
||||||
|
Mes Enters MPI_Ireduce_scatter
|
||||||
|
MeS Exits MPI_Ireduce_scatter
|
||||||
|
Meb Enters MPI_Ireduce_scatter_block
|
||||||
|
MeB Exits MPI_Ireduce_scatter_block
|
||||||
|
BIN
doc/user/emulation/fig/mpi-function.png
Normal file
BIN
doc/user/emulation/fig/mpi-function.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 32 KiB |
242
doc/user/emulation/mpi.md
Normal file
242
doc/user/emulation/mpi.md
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
# MPI model
|
||||||
|
|
||||||
|
The [Message Passing Interface (MPI)][mpi] is a standard library interface
|
||||||
|
specification for message-passing communication libraries targeting parallel
|
||||||
|
computing architectures. The interface defines functions for point-to-point
|
||||||
|
communication primitives, collectives, remote memory access (RMA), I/O and
|
||||||
|
process management.
|
||||||
|
|
||||||
|
The [Sonar][sonar] library instruments the most essential MPI functions that any
|
||||||
|
user application or any external library may execute. Sonar tracks the calls to
|
||||||
|
these MPI functions made at each point. Both users and developers can use this
|
||||||
|
information to analyze the time spent inside MPI functions. The next section
|
||||||
|
explains a view that is provided to achieve this goal.
|
||||||
|
|
||||||
|
The Sonar library is compatible with the MPI standards 3.0, 3.1 and 4.0. See the
|
||||||
|
[MPI documentation][mpi docs] for more information about the MPI standards and
|
||||||
|
their functions.
|
||||||
|
|
||||||
|
[mpi]: https://www.mpi-forum.org
|
||||||
|
[mpi docs]: https://www.mpi-forum.org/docs
|
||||||
|
[sonar]: https://pm.bsc.es/gitlab/ovni/sonar
|
||||||
|
[sonar docs]: https://pm.bsc.es/gitlab/ovni/sonar/-/blob/main/README.md
|
||||||
|
|
||||||
|
Sonar requires an installation of the ovni library and an MPI library. Use the
|
||||||
|
option `--with-ovni=prefix` when building Sonar to specify the ovni prefix. The
|
||||||
|
building procedure will compile and install the `libsonar-mpi.so`. See the
|
||||||
|
[Sonar documentation][sonar docs] for more details about the building steps.
|
||||||
|
|
||||||
|
An application can instrument the MPI function calls by linking with the Sonar
|
||||||
|
library `libsonar-mpi.so`. At run-time, the Sonar library does not enable the
|
||||||
|
instrumentation by default. Sonar instruments the MPI functions when the
|
||||||
|
environment variable `SONAR_MPI_INSTRUMENT` is defined to `ovni`. Its default
|
||||||
|
value is `none`.
|
||||||
|
|
||||||
|
As an example, a user can generate a trace with MPI function events of an MPI
|
||||||
|
program `app.c` in this way:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mpicc -c app.c -o app.o
|
||||||
|
$ mpicc app.o -o app -L${SONAR_PREFIX}/lib -lsonar-mpi
|
||||||
|
$ export SONAR_MPI_INSTRUMENT=ovni
|
||||||
|
$ mpirun -n 2 ./app
|
||||||
|
```
|
||||||
|
|
||||||
|
This will generate an ovni trace in the `ovni` directory, which can be emulated
|
||||||
|
using the `ovniemu` tool.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
Notice that the order of libraries at the linking stage is important. The
|
||||||
|
Sonar library should always have precedence on the MPI library. That's the
|
||||||
|
usual behavior when using `mpicc` tools. The `mpicc` tool should link the
|
||||||
|
application with the MPI libraries as the last libraries in the list of
|
||||||
|
application's dependencies. If this order is not respected, the Sonar
|
||||||
|
library would not be able to intercept the MPI function calls and instrument
|
||||||
|
them.
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
Notice the Task-Aware MPI (TAMPI), as well as other external libraries,
|
||||||
|
intercepts the MPI functions and may call MPI functions instead. Thus, the
|
||||||
|
order in which such libraries and Sonar are linked to the application will
|
||||||
|
also alter the resulting ovni trace. Give precedence to the Sonar library to
|
||||||
|
instrument the MPI function calls made by the application. You can achieve
|
||||||
|
by linking your application with the linking options `-lsonar-mpi -ltampi`.
|
||||||
|
Otherwise, give precendence to the TAMPI library to track the real MPI
|
||||||
|
functions that are being executed (i.e., the ones that the MPI library
|
||||||
|
actually runs). In this case, use the linking options `-ltampi -lsonar-mpi`.
|
||||||
|
|
||||||
|
## Function view
|
||||||
|
|
||||||
|
The function view attempts to provide a general overview of which are the MPI
|
||||||
|
functions being executed at any point in time. The function view shows the MPI
|
||||||
|
functions called by each thread (and for each CPU, the MPI functions executed
|
||||||
|
by the running thread in that CPU).
|
||||||
|
|
||||||
|
The function states shown in this view are listed below. Each function state
|
||||||
|
(in bold) includes a list of all the MPI functions that are instrumented as
|
||||||
|
that particular state. Notice that only the most important functions are
|
||||||
|
instrumented. Also, notice that not all functions have their own state. For
|
||||||
|
instance, the large count MPI (with `_c` suffix) introduced in MPI 4.0, the
|
||||||
|
extended functions (with `v` or `w` suffix), and Fortran functions (with lower
|
||||||
|
case name and `_` suffix) are instrumented as their simple C function without
|
||||||
|
suffix.
|
||||||
|
|
||||||
|
- *Setup functions*: The running thread is executing MPI setup functions to
|
||||||
|
initialize and finalize the MPI environment. The following function states
|
||||||
|
are shown:
|
||||||
|
|
||||||
|
- **MPI_Init**: `MPI_Init`, `mpi_init_`
|
||||||
|
|
||||||
|
- **MPI_Init_thread**: `MPI_Init_thread`, `mpi_init_thread_`
|
||||||
|
|
||||||
|
- **MPI_Finalize**: `MPI_Finalize`, `mpi_finalize_`
|
||||||
|
|
||||||
|
- *Request functions*: The running thread is executing MPI functions that wait
|
||||||
|
or test MPI requests after being generated by non-blocking MPI operations. The
|
||||||
|
following functions are instrumented:
|
||||||
|
|
||||||
|
- **MPI_Wait**: `MPI_Wait`, `mpi_wait_`
|
||||||
|
|
||||||
|
- **MPI_Waitall**: `MPI_Waitall`, `mpi_waitall_`
|
||||||
|
|
||||||
|
- **MPI_Waitany**: `MPI_Waitany`, `mpi_waitany_`
|
||||||
|
|
||||||
|
- **MPI_Waitsome**: `MPI_Waitsome`, `mpi_waitsome_`
|
||||||
|
|
||||||
|
- **MPI_Test**: `MPI_Test`, `mpi_test_`
|
||||||
|
|
||||||
|
- **MPI_Testall**: `MPI_Testall`, `mpi_testall_`
|
||||||
|
|
||||||
|
- **MPI_Testany**: `MPI_Testany`, `mpi_testany_`
|
||||||
|
|
||||||
|
- **MPI_Testsome**: `MPI_Testsome`, `mpi_testsome_`
|
||||||
|
|
||||||
|
- *Point-to-point functions*: The running thread is communicating through MPI
|
||||||
|
by executing point-to-point primitives. The instrumented functions are:
|
||||||
|
|
||||||
|
- **MPI_Recv**: `MPI_Recv`, `MPI_Recv_c`, `mpi_recv_`
|
||||||
|
|
||||||
|
- **MPI_Send**: `MPI_Send`, `MPI_Send_c`, `mpi_send_`
|
||||||
|
|
||||||
|
- **MPI_Bsend**: `MPI_Bsend`, `MPI_Bsend_c`, `mpi_bsend_`
|
||||||
|
|
||||||
|
- **MPI_Rsend**: `MPI_Rsend`, `MPI_Rsend_c`, `mpi_rsend_`
|
||||||
|
|
||||||
|
- **MPI_Ssend**: `MPI_Ssend`, `MPI_Ssend_c`, `mpi_ssend_`
|
||||||
|
|
||||||
|
- **MPI_Sendrecv**: `MPI_Sendrecv`, `MPI_Sendrecv_c`, `mpi_sendrecv_`
|
||||||
|
|
||||||
|
- **MPI_Sendrecv_replace**: `MPI_Sendrecv_replace`, `MPI_Sendrecv_replace_c`,
|
||||||
|
`mpi_sendrecv_replace_`
|
||||||
|
|
||||||
|
- **MPI_Irecv**: `MPI_Irecv`, `MPI_Irecv_c`, `mpi_irecv_`
|
||||||
|
|
||||||
|
- **MPI_Isend**: `MPI_Isend`, `MPI_Isend_c`, `mpi_isend_`
|
||||||
|
|
||||||
|
- **MPI_Ibsend**: `MPI_Ibsend`, `MPI_Ibsend_c`, `mpi_ibsend_`
|
||||||
|
|
||||||
|
- **MPI_Irsend**: `MPI_Irsend`, `MPI_Irsend_c`, `mpi_irsend_`
|
||||||
|
|
||||||
|
- **MPI_Issend**: `MPI_Issend`, `MPI_Issend_c`, `mpi_issend_`
|
||||||
|
|
||||||
|
- **MPI_Isendrecv**: `MPI_Isendrecv`, `MPI_Isendrecv_c`, `mpi_isendrecv_`
|
||||||
|
|
||||||
|
- **MPI_Isendrecv_replace**: `MPI_Isendrecv_replace`,
|
||||||
|
`MPI_Isendrecv_replace_c`, `mpi_isendrecv_replace_`
|
||||||
|
|
||||||
|
- *Collective functions*: The running thread is communicating through MPI by
|
||||||
|
executing collective functions. The instrumented functions are:
|
||||||
|
|
||||||
|
- **MPI_Gather**: `MPI_Gather`, `MPI_Gatherv`, `MPI_Gather_c`,
|
||||||
|
`MPI_Gatherv_c`, `mpi_gather_`, `mpi_gatherv_`
|
||||||
|
|
||||||
|
- **MPI_Allgather**: `MPI_Allgather`, `MPI_Allgatherv`, `MPI_Allgather_c`,
|
||||||
|
`MPI_Allgatherv_c`, `mpi_allgather_`, `mpi_allgatherv_`
|
||||||
|
|
||||||
|
- **MPI_Scatter**: `MPI_Scatter`, `MPI_Scatterv`, `MPI_Scatter_c`,
|
||||||
|
`MPI_Scatterv_c`, `mpi_scatter_`, `mpi_scatterv_`
|
||||||
|
|
||||||
|
- **MPI_Reduce**: `MPI_Reduce`, `MPI_Reduce_c`, `mpi_reduce_`
|
||||||
|
|
||||||
|
- **MPI_Reduce_scatter**: `MPI_Reduce_scatter`, `MPI_Reduce_scatter_c`,
|
||||||
|
`mpi_reduce_scatter_`
|
||||||
|
|
||||||
|
- **MPI_Reduce_scatter_block**: `MPI_Reduce_scatter_block`,
|
||||||
|
`MPI_Reduce_scatter_block_c`, `mpi_reduce_scatter_block_`
|
||||||
|
|
||||||
|
- **MPI_Allreduce**: `MPI_Allreduce`, `MPI_Allreduce_c`, `mpi_allreduce_`
|
||||||
|
|
||||||
|
- **MPI_Barrier**: `MPI_Barrier`, `MPI_Barrier_c`, `mpi_barrier_`
|
||||||
|
|
||||||
|
- **MPI_Bcast**: `MPI_Bcast`, `MPI_Bcast_c`, `mpi_bcast`
|
||||||
|
|
||||||
|
- **MPI_Alltoall**: `MPI_Alltoall`, `MPI_Alltoallv`, `MPI_Alltoallw`,
|
||||||
|
`MPI_Alltoall_c`, `MPI_Alltoallv_c`, `MPI_Alltoallw_c`, `mpi_alltoall_`,
|
||||||
|
`mpi_alltoallv_`, `mpi_alltoallw_`
|
||||||
|
|
||||||
|
- **MPI_Scan**: `MPI_Scan`, `MPI_Scan_c`, `mpi_scan_`
|
||||||
|
|
||||||
|
- **MPI_Exscan**: `MPI_Exscan`, `MPI_Exscan_c`, `mpi_exscan_`
|
||||||
|
|
||||||
|
- **MPI_Igather**: `MPI_Igather`, `MPI_Igatherv`, `MPI_Igather_c`,
|
||||||
|
`MPI_Igatherv_c`, `mpi_igather_`, `mpi_igatherv_`
|
||||||
|
|
||||||
|
- **MPI_Iallgather**: `MPI_Iallgather`, `MPI_Iallgatherv`,
|
||||||
|
`MPI_Iallgather_c`, `MPI_Iallgatherv_c`, `mpi_iallgather_`,
|
||||||
|
`mpi_iallgatherv_`
|
||||||
|
|
||||||
|
- **MPI_Iscatter**: `MPI_Iscatter`, `MPI_Iscatterv`, `MPI_Iscatter_c`,
|
||||||
|
`MPI_Iscatterv_c`, `mpi_iscatter_`, `mpi_iscatterv_`
|
||||||
|
|
||||||
|
- **MPI_Ireduce**: `MPI_Ireduce`, `MPI_Ireduce_c`, `mpi_ireduce_`
|
||||||
|
|
||||||
|
- **MPI_Iallreduce**: `MPI_Iallreduce`, `MPI_Iallreduce_c`, `mpi_iallreduce_`
|
||||||
|
|
||||||
|
- **MPI_Ireduce_scatter**: `MPI_Ireduce_scatter`, `MPI_Ireduce_scatter_c`,
|
||||||
|
`mpi_ireduce_scatter_`
|
||||||
|
|
||||||
|
- **MPI_Ireduce_scatter_block**: `MPI_Ireduce_scatter_block`,
|
||||||
|
`MPI_Ireduce_scatter_block_c`, `mpi_ireduce_scatter_block_`
|
||||||
|
|
||||||
|
- **MPI_Ibarrier**: `MPI_Ibarrier`, `MPI_Ibarrier_c`, `mpi_ibarrier_`
|
||||||
|
|
||||||
|
- **MPI_Ibcast**: `MPI_Ibcast`, `MPI_Ibcast_c`, `mpi_ibcast_`
|
||||||
|
|
||||||
|
- **MPI_Ialltoall**: `MPI_Ialltoall`, `MPI_Ialltoallv`, `MPI_Ialltoallw`,
|
||||||
|
`MPI_Ialltoall_c`, `MPI_Ialltoallv_c`, `MPI_Ialltoallw_c`,
|
||||||
|
`mpi_ialltoall_`, `mpi_ialltoallv_`, `mpi_ialltoallw_`
|
||||||
|
|
||||||
|
- **MPI_Iscan**: `MPI_Iscan`, `MPI_Iscan_c`, `mpi_iscan_`
|
||||||
|
|
||||||
|
- **MPI_Iexscan**: `MPI_Iexscan`, `MPI_Iexscan_c`, `mpi_iexscan_`
|
||||||
|
|
||||||
|
!!! Note
|
||||||
|
|
||||||
|
The Sonar library does not support large count MPI functions for the Fortran
|
||||||
|
language yet, and thus, these functions are not instrumented.
|
||||||
|
|
||||||
|
The figure below shows an example of the MPI function view. The program executes
|
||||||
|
a distributed stencil algorithm with MPI and OmpSs-2. There are several MPI
|
||||||
|
processes, each running OmpSs-2 tasks on an exclusive set of CPUs. Most of these
|
||||||
|
are computation tasks, while the others are concurrent tasks performing
|
||||||
|
communications using the blocking mode of the TAMPI library. These use `MPI_Send`
|
||||||
|
and `MPI_Recv` functions to send and receive blocks of data. The program was
|
||||||
|
linked with Sonar and preceding the TAMPI library. Thus, the trace shows the
|
||||||
|
blocking MPI function calls made by the application.
|
||||||
|
|
||||||
|
![MPI function view example](fig/mpi-function.png)
|
||||||
|
|
||||||
|
The light green areas correspond to the `MPI_Init_thread` calls, the grey ones
|
||||||
|
are `MPI_Send` calls and the dark green areas are `MPI_Recv` calls. There are
|
||||||
|
other secondary calls like `MPI_Bcast` (orange), `MPI_Barrier` (blue) and
|
||||||
|
`MPI_Finalize` (red) calls.
|
||||||
|
|
||||||
|
As mentioned above, the trace shows the blocking MPI functions called by the
|
||||||
|
application because Sonar was placed before TAMPI in the linking order. However,
|
||||||
|
these blocking calls may not be actually executed by the MPI library; TAMPI will
|
||||||
|
transparently replace them with non-blocking calls (e.g., `MPI_Isend` and
|
||||||
|
`MPI_Irecv`) and a polling mechanism for the generated MPI requests. If you want
|
||||||
|
to explore the actual MPI functions being executed, you should link the Sonar
|
||||||
|
library after TAMPI.
|
@ -33,6 +33,7 @@ nav:
|
|||||||
- user/emulation/nosv.md
|
- user/emulation/nosv.md
|
||||||
- user/emulation/nanos6.md
|
- user/emulation/nanos6.md
|
||||||
- user/emulation/tampi.md
|
- user/emulation/tampi.md
|
||||||
|
- user/emulation/mpi.md
|
||||||
- user/emulation/events.md
|
- user/emulation/events.md
|
||||||
- 'Developer guide':
|
- 'Developer guide':
|
||||||
- dev/index.md
|
- dev/index.md
|
||||||
|
@ -53,6 +53,8 @@ add_library(emu STATIC
|
|||||||
nosv/event.c
|
nosv/event.c
|
||||||
nodes/setup.c
|
nodes/setup.c
|
||||||
nodes/event.c
|
nodes/event.c
|
||||||
|
mpi/setup.c
|
||||||
|
mpi/event.c
|
||||||
tampi/setup.c
|
tampi/setup.c
|
||||||
tampi/event.c
|
tampi/event.c
|
||||||
kernel/setup.c
|
kernel/setup.c
|
||||||
|
@ -19,6 +19,7 @@ enum emu_prv_types {
|
|||||||
PRV_NOSV_SUBSYSTEM = 13,
|
PRV_NOSV_SUBSYSTEM = 13,
|
||||||
PRV_NOSV_RANK = 14,
|
PRV_NOSV_RANK = 14,
|
||||||
PRV_TAMPI_SUBSYSTEM = 20,
|
PRV_TAMPI_SUBSYSTEM = 20,
|
||||||
|
PRV_MPI_FUNCTION = 25,
|
||||||
PRV_NODES_SUBSYSTEM = 30,
|
PRV_NODES_SUBSYSTEM = 30,
|
||||||
PRV_NANOS6_TASKID = 35,
|
PRV_NANOS6_TASKID = 35,
|
||||||
PRV_NANOS6_TYPE = 36,
|
PRV_NANOS6_TYPE = 36,
|
||||||
|
@ -12,6 +12,7 @@ extern struct model_spec model_nanos6;
|
|||||||
extern struct model_spec model_nosv;
|
extern struct model_spec model_nosv;
|
||||||
extern struct model_spec model_nodes;
|
extern struct model_spec model_nodes;
|
||||||
extern struct model_spec model_tampi;
|
extern struct model_spec model_tampi;
|
||||||
|
extern struct model_spec model_mpi;
|
||||||
extern struct model_spec model_kernel;
|
extern struct model_spec model_kernel;
|
||||||
|
|
||||||
static struct model_spec *models[] = {
|
static struct model_spec *models[] = {
|
||||||
@ -20,6 +21,7 @@ static struct model_spec *models[] = {
|
|||||||
&model_nosv,
|
&model_nosv,
|
||||||
&model_nodes,
|
&model_nodes,
|
||||||
&model_tampi,
|
&model_tampi,
|
||||||
|
&model_mpi,
|
||||||
&model_kernel,
|
&model_kernel,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
201
src/emu/mpi/event.c
Normal file
201
src/emu/mpi/event.c
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#include "mpi_priv.h"
|
||||||
|
#include "chan.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "emu.h"
|
||||||
|
#include "emu_ev.h"
|
||||||
|
#include "extend.h"
|
||||||
|
#include "model_thread.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "value.h"
|
||||||
|
|
||||||
|
enum { PUSH = 1, POP = 2, IGN = 3 };
|
||||||
|
|
||||||
|
static const int fn_table[256][256][3] = {
|
||||||
|
['U'] = {
|
||||||
|
['i'] = { CH_FUNCTION, PUSH, ST_MPI_INIT },
|
||||||
|
['I'] = { CH_FUNCTION, POP, ST_MPI_INIT },
|
||||||
|
['t'] = { CH_FUNCTION, PUSH, ST_MPI_INIT_THREAD },
|
||||||
|
['T'] = { CH_FUNCTION, POP, ST_MPI_INIT_THREAD },
|
||||||
|
['f'] = { CH_FUNCTION, PUSH, ST_MPI_FINALIZE },
|
||||||
|
['F'] = { CH_FUNCTION, POP, ST_MPI_FINALIZE },
|
||||||
|
},
|
||||||
|
['W'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_WAIT },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_WAIT },
|
||||||
|
['a'] = { CH_FUNCTION, PUSH, ST_MPI_WAITALL },
|
||||||
|
['A'] = { CH_FUNCTION, POP, ST_MPI_WAITALL },
|
||||||
|
['y'] = { CH_FUNCTION, PUSH, ST_MPI_WAITANY },
|
||||||
|
['Y'] = { CH_FUNCTION, POP, ST_MPI_WAITANY },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_WAITSOME },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_WAITSOME },
|
||||||
|
},
|
||||||
|
['T'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_TEST },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_TEST },
|
||||||
|
['a'] = { CH_FUNCTION, PUSH, ST_MPI_TESTALL },
|
||||||
|
['A'] = { CH_FUNCTION, POP, ST_MPI_TESTALL },
|
||||||
|
['y'] = { CH_FUNCTION, PUSH, ST_MPI_TESTANY },
|
||||||
|
['Y'] = { CH_FUNCTION, POP, ST_MPI_TESTANY },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_TESTSOME },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_TESTSOME },
|
||||||
|
},
|
||||||
|
['R'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_RECV },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_RECV },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_SENDRECV },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_SENDRECV },
|
||||||
|
['o'] = { CH_FUNCTION, PUSH, ST_MPI_SENDRECV_REPLACE },
|
||||||
|
['O'] = { CH_FUNCTION, POP, ST_MPI_SENDRECV_REPLACE },
|
||||||
|
},
|
||||||
|
['r'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_IRECV },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_IRECV },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_ISENDRECV },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_ISENDRECV },
|
||||||
|
['o'] = { CH_FUNCTION, PUSH, ST_MPI_ISENDRECV_REPLACE },
|
||||||
|
['O'] = { CH_FUNCTION, POP, ST_MPI_ISENDRECV_REPLACE },
|
||||||
|
},
|
||||||
|
['S'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_SEND },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_SEND },
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_BSEND },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_BSEND },
|
||||||
|
['r'] = { CH_FUNCTION, PUSH, ST_MPI_RSEND },
|
||||||
|
['R'] = { CH_FUNCTION, POP, ST_MPI_RSEND },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_SSEND },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_SSEND },
|
||||||
|
},
|
||||||
|
['s'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_ISEND },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_ISEND },
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_IBSEND },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_IBSEND },
|
||||||
|
['r'] = { CH_FUNCTION, PUSH, ST_MPI_IRSEND },
|
||||||
|
['R'] = { CH_FUNCTION, POP, ST_MPI_IRSEND },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_ISSEND },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_ISSEND },
|
||||||
|
},
|
||||||
|
['A'] = {
|
||||||
|
['g'] = { CH_FUNCTION, PUSH, ST_MPI_ALLGATHER },
|
||||||
|
['G'] = { CH_FUNCTION, POP, ST_MPI_ALLGATHER },
|
||||||
|
['r'] = { CH_FUNCTION, PUSH, ST_MPI_ALLREDUCE },
|
||||||
|
['R'] = { CH_FUNCTION, POP, ST_MPI_ALLREDUCE },
|
||||||
|
['a'] = { CH_FUNCTION, PUSH, ST_MPI_ALLTOALL },
|
||||||
|
['A'] = { CH_FUNCTION, POP, ST_MPI_ALLTOALL },
|
||||||
|
},
|
||||||
|
['a'] = {
|
||||||
|
['g'] = { CH_FUNCTION, PUSH, ST_MPI_IALLGATHER },
|
||||||
|
['G'] = { CH_FUNCTION, POP, ST_MPI_IALLGATHER },
|
||||||
|
['r'] = { CH_FUNCTION, PUSH, ST_MPI_IALLREDUCE },
|
||||||
|
['R'] = { CH_FUNCTION, POP, ST_MPI_IALLREDUCE },
|
||||||
|
['a'] = { CH_FUNCTION, PUSH, ST_MPI_IALLTOALL },
|
||||||
|
['A'] = { CH_FUNCTION, POP, ST_MPI_IALLTOALL },
|
||||||
|
},
|
||||||
|
['C'] = {
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_BARRIER },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_BARRIER },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_SCAN },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_SCAN },
|
||||||
|
['e'] = { CH_FUNCTION, PUSH, ST_MPI_EXSCAN },
|
||||||
|
['E'] = { CH_FUNCTION, POP, ST_MPI_EXSCAN },
|
||||||
|
},
|
||||||
|
['c'] = {
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_IBARRIER },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_IBARRIER },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_ISCAN },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_ISCAN },
|
||||||
|
['e'] = { CH_FUNCTION, PUSH, ST_MPI_IEXSCAN },
|
||||||
|
['E'] = { CH_FUNCTION, POP, ST_MPI_IEXSCAN },
|
||||||
|
},
|
||||||
|
['D'] = {
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_BCAST },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_BCAST },
|
||||||
|
['g'] = { CH_FUNCTION, PUSH, ST_MPI_GATHER },
|
||||||
|
['G'] = { CH_FUNCTION, POP, ST_MPI_GATHER },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_SCATTER },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_SCATTER },
|
||||||
|
},
|
||||||
|
['d'] = {
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_IBCAST },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_IBCAST },
|
||||||
|
['g'] = { CH_FUNCTION, PUSH, ST_MPI_IGATHER },
|
||||||
|
['G'] = { CH_FUNCTION, POP, ST_MPI_IGATHER },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_ISCATTER },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_ISCATTER },
|
||||||
|
},
|
||||||
|
['E'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_REDUCE },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_REDUCE },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_REDUCE_SCATTER },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_REDUCE_SCATTER },
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_REDUCE_SCATTER_BLOCK },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_REDUCE_SCATTER_BLOCK },
|
||||||
|
},
|
||||||
|
['e'] = {
|
||||||
|
['['] = { CH_FUNCTION, PUSH, ST_MPI_IREDUCE },
|
||||||
|
[']'] = { CH_FUNCTION, POP, ST_MPI_IREDUCE },
|
||||||
|
['s'] = { CH_FUNCTION, PUSH, ST_MPI_IREDUCE_SCATTER },
|
||||||
|
['S'] = { CH_FUNCTION, POP, ST_MPI_IREDUCE_SCATTER },
|
||||||
|
['b'] = { CH_FUNCTION, PUSH, ST_MPI_IREDUCE_SCATTER_BLOCK },
|
||||||
|
['B'] = { CH_FUNCTION, POP, ST_MPI_IREDUCE_SCATTER_BLOCK },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
process_ev(struct emu *emu)
|
||||||
|
{
|
||||||
|
if (!emu->thread->is_running) {
|
||||||
|
err("current thread %d not running", emu->thread->tid);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int *entry = fn_table[emu->ev->c][emu->ev->v];
|
||||||
|
int chind = entry[0];
|
||||||
|
int action = entry[1];
|
||||||
|
int st = entry[2];
|
||||||
|
|
||||||
|
struct mpi_thread *th = EXT(emu->thread, 'M');
|
||||||
|
struct chan *ch = &th->m.ch[chind];
|
||||||
|
|
||||||
|
if (action == PUSH) {
|
||||||
|
return chan_push(ch, value_int64(st));
|
||||||
|
} else if (action == POP) {
|
||||||
|
return chan_pop(ch, value_int64(st));
|
||||||
|
} else if (action == IGN) {
|
||||||
|
return 0; /* do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
err("unknown mpi function event");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
model_mpi_event(struct emu *emu)
|
||||||
|
{
|
||||||
|
static int enabled = 0;
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
if (model_mpi_connect(emu) != 0) {
|
||||||
|
err("mpi_connect failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
enabled = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("in mpi_event");
|
||||||
|
if (emu->ev->m != 'M') {
|
||||||
|
err("unexpected event model %c", emu->ev->m);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("got mpi event %s", emu->ev->mcv);
|
||||||
|
if (process_ev(emu) != 0) {
|
||||||
|
err("error processing mpi event");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
84
src/emu/mpi/mpi_priv.h
Normal file
84
src/emu/mpi/mpi_priv.h
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#ifndef MPI_PRIV_H
|
||||||
|
#define MPI_PRIV_H
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "model_cpu.h"
|
||||||
|
#include "model_thread.h"
|
||||||
|
|
||||||
|
/* Private enums */
|
||||||
|
|
||||||
|
enum mpi_chan {
|
||||||
|
CH_FUNCTION = 0,
|
||||||
|
CH_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mpi_function_values {
|
||||||
|
ST_MPI_INIT = 1,
|
||||||
|
ST_MPI_INIT_THREAD,
|
||||||
|
ST_MPI_FINALIZE,
|
||||||
|
ST_MPI_WAIT,
|
||||||
|
ST_MPI_WAITALL,
|
||||||
|
ST_MPI_WAITANY,
|
||||||
|
ST_MPI_WAITSOME,
|
||||||
|
ST_MPI_TEST,
|
||||||
|
ST_MPI_TESTALL,
|
||||||
|
ST_MPI_TESTANY,
|
||||||
|
ST_MPI_TESTSOME,
|
||||||
|
ST_MPI_RECV,
|
||||||
|
ST_MPI_SEND,
|
||||||
|
ST_MPI_BSEND,
|
||||||
|
ST_MPI_RSEND,
|
||||||
|
ST_MPI_SSEND,
|
||||||
|
ST_MPI_SENDRECV,
|
||||||
|
ST_MPI_SENDRECV_REPLACE,
|
||||||
|
ST_MPI_IRECV,
|
||||||
|
ST_MPI_ISEND,
|
||||||
|
ST_MPI_IBSEND,
|
||||||
|
ST_MPI_IRSEND,
|
||||||
|
ST_MPI_ISSEND,
|
||||||
|
ST_MPI_ISENDRECV,
|
||||||
|
ST_MPI_ISENDRECV_REPLACE,
|
||||||
|
ST_MPI_ALLGATHER,
|
||||||
|
ST_MPI_ALLREDUCE,
|
||||||
|
ST_MPI_ALLTOALL,
|
||||||
|
ST_MPI_BARRIER,
|
||||||
|
ST_MPI_BCAST,
|
||||||
|
ST_MPI_GATHER,
|
||||||
|
ST_MPI_REDUCE,
|
||||||
|
ST_MPI_REDUCE_SCATTER,
|
||||||
|
ST_MPI_REDUCE_SCATTER_BLOCK,
|
||||||
|
ST_MPI_SCATTER,
|
||||||
|
ST_MPI_SCAN,
|
||||||
|
ST_MPI_EXSCAN,
|
||||||
|
ST_MPI_IALLGATHER,
|
||||||
|
ST_MPI_IALLREDUCE,
|
||||||
|
ST_MPI_IALLTOALL,
|
||||||
|
ST_MPI_IBARRIER,
|
||||||
|
ST_MPI_IBCAST,
|
||||||
|
ST_MPI_IGATHER,
|
||||||
|
ST_MPI_IREDUCE,
|
||||||
|
ST_MPI_IREDUCE_SCATTER,
|
||||||
|
ST_MPI_IREDUCE_SCATTER_BLOCK,
|
||||||
|
ST_MPI_ISCATTER,
|
||||||
|
ST_MPI_ISCAN,
|
||||||
|
ST_MPI_IEXSCAN,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mpi_thread {
|
||||||
|
struct model_thread m;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mpi_cpu {
|
||||||
|
struct model_cpu m;
|
||||||
|
};
|
||||||
|
|
||||||
|
int model_mpi_probe(struct emu *emu);
|
||||||
|
int model_mpi_create(struct emu *emu);
|
||||||
|
int model_mpi_connect(struct emu *emu);
|
||||||
|
int model_mpi_event(struct emu *emu);
|
||||||
|
int model_mpi_finish(struct emu *emu);
|
||||||
|
|
||||||
|
#endif /* MPI_PRIV_H */
|
252
src/emu/mpi/setup.c
Normal file
252
src/emu/mpi/setup.c
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#include "mpi_priv.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "chan.h"
|
||||||
|
#include "common.h"
|
||||||
|
#include "emu.h"
|
||||||
|
#include "emu_args.h"
|
||||||
|
#include "emu_prv.h"
|
||||||
|
#include "extend.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "model_chan.h"
|
||||||
|
#include "model_cpu.h"
|
||||||
|
#include "model_pvt.h"
|
||||||
|
#include "model_thread.h"
|
||||||
|
#include "pv/pcf.h"
|
||||||
|
#include "pv/prv.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "thread.h"
|
||||||
|
#include "track.h"
|
||||||
|
#include "value.h"
|
||||||
|
|
||||||
|
static const char model_name[] = "mpi";
|
||||||
|
enum { model_id = 'M' };
|
||||||
|
|
||||||
|
struct model_spec model_mpi = {
|
||||||
|
.name = model_name,
|
||||||
|
.model = model_id,
|
||||||
|
.create = model_mpi_create,
|
||||||
|
// .connect = model_mpi_connect,
|
||||||
|
.event = model_mpi_event,
|
||||||
|
.probe = model_mpi_probe,
|
||||||
|
.finish = model_mpi_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------- channels ------------------ */
|
||||||
|
|
||||||
|
static const char *chan_name[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = "function",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int chan_stack[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------- pvt ------------------ */
|
||||||
|
|
||||||
|
static const int pvt_type[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = PRV_MPI_FUNCTION,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *pcf_prefix[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = "MPI function",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pcf_value_label mpi_function_values[] = {
|
||||||
|
{ ST_MPI_INIT, "MPI_Init" },
|
||||||
|
{ ST_MPI_INIT_THREAD, "MPI_Init_thread" },
|
||||||
|
{ ST_MPI_FINALIZE, "MPI_Finalize" },
|
||||||
|
{ ST_MPI_WAIT, "MPI_Wait" },
|
||||||
|
{ ST_MPI_WAITALL, "MPI_Waitall" },
|
||||||
|
{ ST_MPI_WAITANY, "MPI_Waitany" },
|
||||||
|
{ ST_MPI_WAITSOME, "MPI_Waitsome" },
|
||||||
|
{ ST_MPI_TEST, "MPI_Test" },
|
||||||
|
{ ST_MPI_TESTALL, "MPI_Testall" },
|
||||||
|
{ ST_MPI_TESTANY, "MPI_Testany" },
|
||||||
|
{ ST_MPI_TESTSOME, "MPI_Testsome" },
|
||||||
|
{ ST_MPI_RECV, "MPI_Recv" },
|
||||||
|
{ ST_MPI_SEND, "MPI_Send" },
|
||||||
|
{ ST_MPI_BSEND, "MPI_Bsend" },
|
||||||
|
{ ST_MPI_RSEND, "MPI_Rsend" },
|
||||||
|
{ ST_MPI_SSEND, "MPI_Ssend" },
|
||||||
|
{ ST_MPI_SENDRECV, "MPI_Sendrecv" },
|
||||||
|
{ ST_MPI_SENDRECV_REPLACE, "MPI_Sendrecv_replace" },
|
||||||
|
{ ST_MPI_IRECV, "MPI_Irecv" },
|
||||||
|
{ ST_MPI_ISEND, "MPI_Isend" },
|
||||||
|
{ ST_MPI_IBSEND, "MPI_Ibsend" },
|
||||||
|
{ ST_MPI_IRSEND, "MPI_Irsend" },
|
||||||
|
{ ST_MPI_ISSEND, "MPI_Issend" },
|
||||||
|
{ ST_MPI_ISENDRECV, "MPI_Isendrecv" },
|
||||||
|
{ ST_MPI_ISENDRECV_REPLACE, "MPI_Isendrecv_replace" },
|
||||||
|
{ ST_MPI_ALLGATHER, "MPI_Allgather" },
|
||||||
|
{ ST_MPI_ALLREDUCE, "MPI_Allreduce" },
|
||||||
|
{ ST_MPI_ALLTOALL, "MPI_Alltoall" },
|
||||||
|
{ ST_MPI_BARRIER, "MPI_Barrier" },
|
||||||
|
{ ST_MPI_BCAST, "MPI_Bcast" },
|
||||||
|
{ ST_MPI_GATHER, "MPI_Gather" },
|
||||||
|
{ ST_MPI_REDUCE, "MPI_Reduce" },
|
||||||
|
{ ST_MPI_REDUCE_SCATTER, "MPI_Reduce_scatter" },
|
||||||
|
{ ST_MPI_REDUCE_SCATTER_BLOCK, "MPI_Reduce_scatter_block" },
|
||||||
|
{ ST_MPI_SCATTER, "MPI_Scatter" },
|
||||||
|
{ ST_MPI_SCAN, "MPI_Scan" },
|
||||||
|
{ ST_MPI_EXSCAN, "MPI_Exscan" },
|
||||||
|
{ ST_MPI_IALLGATHER, "MPI_Iallgather" },
|
||||||
|
{ ST_MPI_IALLREDUCE, "MPI_Iallreduce" },
|
||||||
|
{ ST_MPI_IALLTOALL, "MPI_Ialltoall" },
|
||||||
|
{ ST_MPI_IBARRIER, "MPI_Ibarrier" },
|
||||||
|
{ ST_MPI_IBCAST, "MPI_Ibcast" },
|
||||||
|
{ ST_MPI_IGATHER, "MPI_Igather" },
|
||||||
|
{ ST_MPI_IREDUCE, "MPI_Ireduce" },
|
||||||
|
{ ST_MPI_IREDUCE_SCATTER, "MPI_Ireduce_scatter" },
|
||||||
|
{ ST_MPI_IREDUCE_SCATTER_BLOCK, "MPI_Ireduce_scatter_block" },
|
||||||
|
{ ST_MPI_ISCATTER, "MPI_Iscatter" },
|
||||||
|
{ ST_MPI_ISCAN, "MPI_Iscan" },
|
||||||
|
{ ST_MPI_IEXSCAN, "MPI_Iexscan" },
|
||||||
|
{ -1, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pcf_value_label *pcf_labels[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = mpi_function_values,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const long prv_flags[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = PRV_SKIPDUP,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct model_pvt_spec pvt_spec = {
|
||||||
|
.type = pvt_type,
|
||||||
|
.prefix = pcf_prefix,
|
||||||
|
.label = pcf_labels,
|
||||||
|
.flags = prv_flags,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------- tracking ------------------ */
|
||||||
|
|
||||||
|
static const int th_track[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = TRACK_TH_RUN,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int cpu_track[CH_MAX] = {
|
||||||
|
[CH_FUNCTION] = TRACK_TH_RUN,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------- chan_spec ------------------ */
|
||||||
|
|
||||||
|
static const struct model_chan_spec th_chan = {
|
||||||
|
.nch = CH_MAX,
|
||||||
|
.prefix = model_name,
|
||||||
|
.ch_names = chan_name,
|
||||||
|
.ch_stack = chan_stack,
|
||||||
|
.pvt = &pvt_spec,
|
||||||
|
.track = th_track,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct model_chan_spec cpu_chan = {
|
||||||
|
.nch = CH_MAX,
|
||||||
|
.prefix = model_name,
|
||||||
|
.ch_names = chan_name,
|
||||||
|
.ch_stack = chan_stack,
|
||||||
|
.pvt = &pvt_spec,
|
||||||
|
.track = cpu_track,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------- models ------------------ */
|
||||||
|
|
||||||
|
static const struct model_cpu_spec cpu_spec = {
|
||||||
|
.size = sizeof(struct mpi_cpu),
|
||||||
|
.chan = &cpu_chan,
|
||||||
|
.model = &model_mpi,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct model_thread_spec th_spec = {
|
||||||
|
.size = sizeof(struct mpi_thread),
|
||||||
|
.chan = &th_chan,
|
||||||
|
.model = &model_mpi,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----------------------------------------------------- */
|
||||||
|
|
||||||
|
int
|
||||||
|
model_mpi_probe(struct emu *emu)
|
||||||
|
{
|
||||||
|
if (emu->system.nthreads == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
model_mpi_create(struct emu *emu)
|
||||||
|
{
|
||||||
|
if (model_thread_create(emu, &th_spec) != 0) {
|
||||||
|
err("model_thread_init failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model_cpu_create(emu, &cpu_spec) != 0) {
|
||||||
|
err("model_cpu_init failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
model_mpi_connect(struct emu *emu)
|
||||||
|
{
|
||||||
|
if (model_thread_connect(emu, &th_spec) != 0) {
|
||||||
|
err("model_thread_connect failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model_cpu_connect(emu, &cpu_spec) != 0) {
|
||||||
|
err("model_cpu_connect failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
end_lint(struct emu *emu)
|
||||||
|
{
|
||||||
|
/* Only run the check if we finished the complete trace */
|
||||||
|
if (!emu->finished)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct system *sys = &emu->system;
|
||||||
|
|
||||||
|
/* Ensure we run out of function states */
|
||||||
|
for (struct thread *t = sys->threads; t; t = t->gnext) {
|
||||||
|
struct mpi_thread *th = EXT(t, model_id);
|
||||||
|
struct chan *ch = &th->m.ch[CH_FUNCTION];
|
||||||
|
int stacked = ch->data.stack.n;
|
||||||
|
if (stacked > 0) {
|
||||||
|
struct value top;
|
||||||
|
if (chan_read(ch, &top) != 0) {
|
||||||
|
err("chan_read failed for function");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err("thread %d ended with %d stacked mpi functions",
|
||||||
|
t->tid, stacked);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
model_mpi_finish(struct emu *emu)
|
||||||
|
{
|
||||||
|
/* When running in linter mode perform additional checks */
|
||||||
|
if (emu->args.linter_mode && end_lint(emu) != 0) {
|
||||||
|
err("end_lint failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user