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 TAMPI model with `T` code.
|
||||
- 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
|
||||
|
||||
|
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 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/nanos6.md
|
||||
- user/emulation/tampi.md
|
||||
- user/emulation/mpi.md
|
||||
- user/emulation/events.md
|
||||
- 'Developer guide':
|
||||
- dev/index.md
|
||||
|
@ -53,6 +53,8 @@ add_library(emu STATIC
|
||||
nosv/event.c
|
||||
nodes/setup.c
|
||||
nodes/event.c
|
||||
mpi/setup.c
|
||||
mpi/event.c
|
||||
tampi/setup.c
|
||||
tampi/event.c
|
||||
kernel/setup.c
|
||||
|
@ -19,6 +19,7 @@ enum emu_prv_types {
|
||||
PRV_NOSV_SUBSYSTEM = 13,
|
||||
PRV_NOSV_RANK = 14,
|
||||
PRV_TAMPI_SUBSYSTEM = 20,
|
||||
PRV_MPI_FUNCTION = 25,
|
||||
PRV_NODES_SUBSYSTEM = 30,
|
||||
PRV_NANOS6_TASKID = 35,
|
||||
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_nodes;
|
||||
extern struct model_spec model_tampi;
|
||||
extern struct model_spec model_mpi;
|
||||
extern struct model_spec model_kernel;
|
||||
|
||||
static struct model_spec *models[] = {
|
||||
@ -20,6 +21,7 @@ static struct model_spec *models[] = {
|
||||
&model_nosv,
|
||||
&model_nodes,
|
||||
&model_tampi,
|
||||
&model_mpi,
|
||||
&model_kernel,
|
||||
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