Skip to content

Commit 31d3dc2

Browse files
committed
use cases: add debugging chapter
1 parent b39d482 commit 31d3dc2

File tree

4 files changed

+182
-89
lines changed

4 files changed

+182
-89
lines changed

App_Use_Cases.tex

Lines changed: 182 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -85,143 +85,236 @@ \subsection{Use Case Details}
8585

8686
There are other keys that are helpful to have before a synchronization point, this is not meant to be a comprehensive list.
8787

88-
\section{Hybrid Programming Models}
89-
\label{app:uc-hybrid-programming-models}
88+
\section{Debugging}
89+
\label{app:uc-debugging}
9090

91-
\subsection{Use Case Summary}
91+
This use case distills out the features/extensions requested in the RFCs that are related to debugging. We have identified parts of PR23 (Co-located process launch for debuggers), RFC0010 (MPIR-like query), RFC0002 (event pub/sub), and RFC0022 (Environmental Parameter Directives for Applications and Launchers) under this category.
9292

93-
Hybrid applications (i.e., applications that utilize more than one lprogramming model, such as an MPI application that also uses OpenMP or PGAS) are growing in popularity, especially as chips with increasingly large numbers of cores and processors proliferate. Unfortunately, the various models currently operate under the assumption that they alone control execution. This leads to conflicts in hybrid applications. Deadlock of parallel applications can occur when one model prevents the other from making progress due to lack of coordination between the multiple programming models~\cite{2016:Hamidouche}. Sub-optimal performance can also occur due to uncoordinated division of hardware resources between the programming models~\cite{2018:Vallee,ompix-moc}. This use-case offers potential solutions to the problem by providing a pathway for programming models to coordinate their actions.
93+
\subsection{Terminology}
9494

95-
\subsection{Use Case Details}
95+
\subsubsection{Tools vs Debuggers}
96+
97+
A \texttt{tool} is a process designed to monitor, record, analyze, or control the execution of another process. Typically used for the purposes of profiling and debugging. A \texttt{first-party tool} runs within the address space of the application process while a \texttt{third-party tool} run within its own process. A \texttt{debugger} is a third-party tool that inspects and controls an application process's execution using system-level debug APIs (e.g., \code{ptrace}).
98+
99+
\subsubsection{Parallel Launching Methods}
100+
A \texttt{starter} program is a program responsible for launching a parallel runtime, such as \ac{MPI}. \ac{PMIx} supports two primary methods for launching parallel applications under tools and debuggers: indirect and direct. In the indirect launching method, the tool is attached to the starter. In the direct launching method, the tool takes the place of the starter.
101+
\ac{PMIx} also supports attaching to already running programs via the \texttt{Process Acquisition} interfaces.
102+
103+
\subsubsection{Process Synchronization}
104+
Process Synchronization is the technique tools use to start the processes of a parallel application such that the tools can still attach to the process early in it's lifetime. Said another away, the tool must be able to start the application processes without them ``running away'' from the tool. In the case of \ac{MPI}, this means stopping the applications processes before they return from \code{MPI_Init}.
105+
106+
\subsubsection{Process Acquisition}\label{subsubsec:process-acq}
96107

97-
\subsubsection{Identifying Active Programming Models}
108+
Process Acquisition is technique tools use to locate all of the processes, local and remote, of a given parallel application. This typically boils down to collecting for every process in the parallel application: the hostname or IP of the machine running the process, the executable name, and the process ID.
98109

99-
The current state-of-the-practice for programming models to detect one another is via set environment variables. For example, OpenMP looks for environment variables to indicate that MPI is active. Unfortunately, this technique is not completely reliable as environment variables change over time and with new software versions. Also, the fact that an environment variable is present doesn't guarantee that a particular programming is in active use since Resource Managers routinely set environment variables "just in case" the application needs them. PMIx provides a reliable mechanism by which each library can determine that another library is in operation.
110+
\subsection{Use Case Details}
111+
\subsubsection{Direct-Launch Debugger Tool}
100112

101-
When initializing PMIx, programming models can register themselves, including their name, version, and threading model. This information is then cached locally and can then be read asynchronously by other programming models using PMIx's Event Notification system (see next section for more details).
113+
PMIx can support the tool itself using the PMIx spawn options to control the app’s startup, including directing the RM/application as to when to block and wait for tool attachment, or stipulating that an interceptor library be preloaded. However, this means that the user is restricted to whatever command line options the tool vendor has provided for operations such as process placement and binding, which places a significant burden on the tool vendor. An example might look like the following: \code{dbgr -n 3 ./myapp}.
102114

103-
This initialization mechanism also allows libraries to share knowledge of each other's resources and intended resource utilization. For example, if OpenMP knows which hardware threads that MPI is using it could potentially avoid processor and cache contention.
115+
Assuming it is supported, co-launch of debugger daemons in this use-case is supported by adding a \code{pmix_app_t} to the \refapi{PMIx_Spawn} command, indicating that the resulting processes are debugger daemons by setting the \refattr{PMIX_DEBUGGER_DAEMONS} attribute.
104116

105-
\littleheader{Code Example}
117+
\begingroup
118+
\begin{figure*}
119+
\begin{center}
120+
\includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{figs/direct-launch}
121+
\end{center}
122+
\caption{Direct Launch}
123+
\label{fig:direct_launch}
124+
\end{figure*}
125+
\endgroup
106126

107-
\pmixCodeImportC[]{sources/hybrid-prog-model/declare_model.c}
108127

109128
\littleheader{Related Interfaces}
110129

111-
{\large \refapi{PMIx_Init}}
112-
\pasteSignature{PMIx_Init}
130+
{\large \refapi{PMIx_tool_init}}
131+
\pasteSignature{PMIx_tool_init}
132+
133+
{\large \refapi{PMIx_Register_event_handler}}
134+
\pasteSignature{PMIx_Register_event_handler}
135+
136+
{\large \refapi{PMIx_Query_info}}
137+
\pasteSignature{PMIx_Query_info}
138+
139+
{\large \refapi{PMIx_Spawn}}
140+
\pasteSignature{PMIx_Spawn}
141+
142+
{\large \refapi{PMIx_Get}}
143+
\pasteSignature{PMIx_Get}
144+
145+
{\large \refapi{PMIx_Notify_event}}
146+
\pasteSignature{PMIx_Notify_event}
113147

114148
\littleheader{Related Attributes}
115149

116-
\pasteAttributeItem{PMIX_PROGRAMMING_MODEL}
117-
\pasteAttributeItem{PMIX_MODEL_LIBRARY_NAME}
118-
\pasteAttributeItem{PMIX_MODEL_LIBRARY_VERSION}
119-
\pasteAttributeItem{PMIX_THREADING_MODEL}
120-
\pasteAttributeItem{PMIX_MODEL_NUM_THREADS}
121-
\pasteAttributeItem{PMIX_MODEL_NUM_CPUS}
122-
\pasteAttributeItem{PMIX_MODEL_CPU_TYPE}
123-
\pasteAttributeItem{PMIX_MODEL_PHASE_NAME}
124-
\pasteAttributeItem{PMIX_MODEL_PHASE_TYPE}
125-
\pasteAttributeItem{PMIX_MODEL_AFFINITY_POLICY}
150+
\pasteAttributeItem{PMIX_QUERY_SPAWN_SUPPORT}
151+
\pasteAttributeItem{PMIX_QUERY_DEBUG_SUPPORT}
152+
\pasteAttributeItem{PMIX_DEBUG_STOP_IN_INIT}
153+
\pasteAttributeItem{PMIX_FWD_STDOUT}
154+
\pasteAttributeItem{PMIX_FWD_STDERR}
155+
\pasteAttributeItem{PMIX_NOTIFY_COMPLETION}
156+
\pasteAttributeItem{PMIX_SETUP_APP_ENVARS}
157+
\pasteAttributeItem{PMIX_DEBUGGER_DAEMONS}
158+
\pasteAttributeItem{PMIX_DEBUG_JOB}
159+
\pasteAttributeItem{PMIX_QUERY_LOCAL_PROC_TABLE}
126160

127-
\subsubsection{Coordinating at Runtime}
161+
\littleheader{Related Constants}
128162

129-
The PMIx Event Notification system provides a mechanism by which the resource manager can communicate system events to applications, thus providing applications with an opportunity to generate an appropriate response. Hybrid applications can leverage these events for cross-library coordination.
163+
\refconst{PMIX_DEBUG_WAITING_FOR_NOTIFY} \\
164+
\refconst{PMIX_DEBUGGER_RELEASE}
130165

131-
Programming models can access the information provided by other programming models during their initialization using the event notification system. In this case, programming models should register a callback for the \refconst{PMIX_MODEL_DECLARED} event.
166+
\subsubsection{Indirect-Launch Debugger Tool}
132167

133-
Programming models can also use the PMIx event notification system to communicate dynamic information, such as entering a new application phase (\refconst{PMIX_MODEL_PHASE_NAME}) or a change in resources used (\refconst{PMIX_MODEL_RESOURCES}). This dynamic information can be broadcast to other programming models using the \refapi{PMIx_Notify_event} function. Other programming models can register callback functions to run when these events occur (i.e., callback functions) using \refapi{PMIx_Register_event_handler}.
168+
Executing a program under a tool using an intermediate launcher such as mpiexec can also be made possible. This requires some degree of coordination between the tool and the launcher. Ultimately, it is the launcher that is going to launch the application, and the tool must somehow inform it (and the application) that this is being done in a debug session so that the application knows to ``block'' until the tool attaches to it.
134169

135-
\littleheader{Code Example}
170+
In this operational mode, the user invokes a tool (typically on a non-compute, or ``head'', node) that in turn uses mpiexec to launch their application – a typical command line might look like the following: \code{dbgr -dbgoption mpiexec -n 32 ./myapp}.
136171

137-
Registering a callback to run when another programming model initializes:
138-
\pmixCodeJoinStart{}%
139-
\pmixCodeImportC[]{sources/hybrid-prog-model/declare_model_cb.c}
140-
\pmixCodeJoin{}%
141-
\pmixCodeImportC[]{sources/hybrid-prog-model/register_declare_model_cb.c}
142-
\pmixCodeJoinEnd{}%
172+
\begingroup
173+
\begin{figure*}
174+
\begin{center}
175+
\includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{figs/indirect-launch}
176+
\end{center}
177+
\caption{Indirect Launch}
178+
\label{fig:indirect_launch}
179+
\end{figure*}
180+
\endgroup
143181

144182

145-
Notifying an event:
146-
\pmixCodeImportC[]{sources/hybrid-prog-model/notify_event.c}
183+
\littleheader{Related Interfaces}
147184

148-
\littleheader{Related Interfaces and Constants}
185+
{\large \refapi{PMIx_tool_init}}
186+
\pasteSignature{PMIx_tool_init}
187+
188+
{\large \refapi{PMIx_Register_event_handler}}
189+
\pasteSignature{PMIx_Register_event_handler}
190+
191+
{\large \refapi{PMIx_Spawn}}
192+
\pasteSignature{PMIx_Spawn}
149193

150194
{\large \refapi{PMIx_Notify_event}}
151195
\pasteSignature{PMIx_Notify_event}
152196

153-
\refconst{PMIX_MODEL_DECLARED} \\
154-
\refconst{PMIX_MODEL_RESOURCES} \\
155-
\refconst{PMIX_OPENMP_PARALLEL_ENTERED} \\
156-
\refconst{PMIX_OPENMP_PARALLEL_EXITED} \\
197+
{\large \refapi{PMIx_tool_attach_to_server}}
198+
\pasteSignature{PMIx_tool_attach_to_server}
199+
200+
{\large \refapi{PMIx_Query_info}}
201+
\pasteSignature{PMIx_Query_info}
202+
203+
{\large \refapi{PMIx_Get}}
204+
\pasteSignature{PMIx_Get}
205+
206+
\littleheader{Related Attributes}
207+
208+
\pasteAttributeItem{PMIX_SPAWN_TOOL}
209+
\pasteAttributeItem{PMIX_FWD_STDOUT}
210+
\pasteAttributeItem{PMIX_FWD_STDERR}
211+
\pasteAttributeItem{PMIX_SETUP_APP_ENVARS}
212+
\pasteAttributeItem{PMIX_DEBUG_STOP_IN_INIT}
213+
\pasteAttributeItem{PMIX_QUERY_PROC_TABLE}
214+
\pasteAttributeItem{PMIX_DEBUGGER_DAEMONS}
215+
\pasteAttributeItem{PMIX_DEBUG_JOB}
216+
\pasteAttributeItem{PMIX_FWD_STDOUT}
217+
\pasteAttributeItem{PMIX_FWD_STDERR}
218+
\pasteAttributeItem{PMIX_NOTIFY_COMPLETION}
219+
\pasteAttributeItem{PMIX_SETUP_APP_ENVARS}
220+
\pasteAttributeItem{PMIX_DEBUG_JOB}
221+
\pasteAttributeItem{PMIX_QUERY_LOCAL_PROC_TABLE}
222+
223+
\littleheader{Related Constants}
224+
225+
\refconst{PMIX_LAUNCHER_READY} \\
226+
\refconst{PMIX_LAUNCH_DIRECTIVE} \\
227+
\refconst{PMIX_LAUNCH_COMPLETE} \\
228+
\refconst{PMIX_DEBUG_WAITING_FOR_NOTIFY} \\
229+
\refconst{PMIX_DEBUGGER_RELEASE}
230+
231+
\subsubsection{Attaching to a Running Job}
232+
233+
PMIx supports attaching to an already running parallel job in two ways. In the first way, the main process of a tool calls \refapi{PMIx_Query_info} with the \refattr{PMIX_QUERY_PROC_TABLE} attribute. This returns an array of structs containing the information required for \hyperref[subsubsec:process-acq]{process acquisition}. This includes remote hostnames, executable names, and process IDs. In the second way, every tool daemon calls \refapi{PMIx_Query_info} with the \refattr{PMIX_QUERY_LOCAL_PROC_TABLE} attribute. This returns a similar array of structs but only for processes on the same node.
234+
235+
An example of this use-case may look like the following: \code{mpiexec -n32~./myApp \&\& dbgr attach \$!}.
236+
237+
\begingroup
238+
\begin{figure*}
239+
\begin{center}
240+
\includegraphics[width=\textwidth,height=\textheight,keepaspectratio]{figs/process-acquisition}
241+
\end{center}
242+
\caption{Attaching to a Running Job}
243+
\label{fig:proc_acq}
244+
\end{figure*}
245+
\endgroup
246+
247+
{\large \refapi{PMIx_tool_init}}
248+
\pasteSignature{PMIx_tool_init}
157249

158250
{\large \refapi{PMIx_Register_event_handler}}
159251
\pasteSignature{PMIx_Register_event_handler}
160252

161-
%\pastePRIAttributeItem{PMIX_RANGE}
253+
{\large \refapi{PMIx_Query_info}}
254+
\pasteSignature{PMIx_Query_info}
255+
256+
{\large \refapi{PMIx_Spawn}}
257+
\pasteSignature{PMIx_Spawn}
258+
259+
\pasteAttributeItem{PMIX_QUERY_PROC_TABLE}
260+
\pasteAttributeItem{PMIX_DEBUGGER_DAEMONS}
261+
\pasteAttributeItem{PMIX_DEBUG_JOB}
262+
\pasteAttributeItem{PMIX_FWD_STDOUT}
263+
\pasteAttributeItem{PMIX_FWD_STDERR}
264+
\pasteAttributeItem{PMIX_NOTIFY_COMPLETION}
265+
\pasteAttributeItem{PMIX_SETUP_APP_ENVARS}
162266

163-
{\large \refapi{pmix_event_notification_cbfunc_fn_t}}
164-
\pasteSignature{pmix_event_notification_cbfunc_fn_t}
267+
\pasteAttributeItem{PMIX_QUERY_NAMESPACES}
165268

166-
\refconst{PMIX_EVENT_ACTION_COMPLETE}
269+
\subsubsection{Tool Interaction with RM}
167270

271+
Tools can benefit from a mechanism by which they may interact with a local PMIx server that has opted to accept such connections along with support for tool connections to system-level PMIx servers, and a logging feature. To add support for tool connections to a specified system-level, PMIx server environments could choose to launch a set of PMIx servers to support a given allocation - these servers will (if so instructed) provide a tool rendezvous point that is tagged with their pid and typically placed in an allocation-specific temporary directory to allow for possible multi-tenancy scenarios. Supporting such operations requires that a system-level PMIx connection be provided which is not associated with a specific user or allocation. A new key has been added to direct the PMIx server to expose a rendezvous point specifically for this purpose.
168272

273+
{\large \refapi{PMIx_Query_info_nb}}
274+
\pasteSignature{PMIx_Query_info_nb}
169275

170-
\subsubsection{Coordinating at Runtime with Multiple Event Handlers}
276+
{\large \refapi{PMIx_Register_event_handler}}
277+
\pasteSignature{PMIx_Register_event_handler}
171278

172-
Coordinating with a threading library such as OpenMP creates the need for separate event handlers for threads of the same process. For example in an MPI+OpenMP hybrid application, the MPI thread and the main OpenMP thread may both want to be notified anytime an OpenMP worker thread enters a parallel region. This requiring support for multiple threads to potentially register different event handlers against the same status code.
279+
{\large \refapi{PMIx_Deregister_event_handler}}
280+
\pasteSignature{PMIx_Deregister_event_handler}
173281

174-
Multiple event handlers registered against the same event are processed in a chain-like manner based on the order in which they were registered, as modified by directive. Registrations against specific event codes are processed first, followed by registrations against multiple event codes and then any default registrations. At each point in the chain, an event handler is called by the PMIx progress thread and given a function to call when that handler has completed its operation. The handler callback notifies PMIx that the handler is done, returning a status code to indicate the result of its work. The results are appended to the array of prior results, with the returned values combined into an array within a single pmix_info_t as follows:
175-
\begin{itemize}
176-
\item \texttt{array[0]}: the event handler name provided at registration (may be an empty field if a string name was not given) will be in the key, with the pmix_status_t value returned by the handler
177-
\item \texttt{array[*]}: the array of results returned by the handler, if any.
178-
\end{itemize}
282+
{\large \refapi{PMIx_Notify_event}}
283+
\pasteSignature{PMIx_Notify_event}
179284

180-
The current PMIx standard does not actually specify a default ordering for event handlers as they are being registered. However, it does include an inherent ordering for invocation. Specifically, PMIx stipulates that handlers be called in the following categorical order:
285+
{\large \refapi{PMIx_server_init}}
286+
\pasteSignature{PMIx_server_init}
181287

182-
\begin{itemize}
183-
\item single status event handlers - i.e., handlers that were registered against a single specific status.
184-
\item multi status event handlers - those registered against more than one specific status
185-
\item default event handlers - those registered against no specific status
186-
\end{itemize}
288+
\littleheader{Job-specific events}
289+
\code{PMIX_EVENT_JOB_LEVEL /* debugger attached, process failure */}
187290

188-
\littleheader{Code Example}
291+
\littleheader{Environment events}
292+
\code{PMIX_EVENT_ENVIRO_LEVEL /*ECC errors, temperature excursions */}
189293

190-
From the OpenMP master thread:
294+
\littleheader{Errors detected by clients/peers}
295+
\code{Network fabric manager detects data corruption}
191296

192-
\pmixCodeJoinStart{}%
193-
\pmixCodeImportC[]{sources/hybrid-prog-model/parallel_omp_cb.c}%
194-
\pmixCodeJoin{}%
195-
\pmixCodeImportC[]{sources/hybrid-prog-model/omp_thread.c}
196-
\pmixCodeJoinEnd{}%
297+
\subsubsection{Environmental Parameter Directives for Applications and Launchers}
197298

198-
From the MPI thread:
299+
It is sometimes desirable or required that standard environmental variables (e.g., \code{PATH}, \code{LD_LIBRARY_PATH}, \code{LD_PRELOAD}) be modified prior to executing an application binary or a starter such as mpiexec - this is particularly true when tools/debuggers are used to start the application. This RFC proposes the definition of a new PMIx structure (\refstruct{pmix_envar_t}) and associated attributes for specifying such operations.
199300

200-
\pmixCodeJoinStart{}%
201-
\pmixCodeImportC[]{sources/hybrid-prog-model/parallel_mpi_cb.c}
202-
\pmixCodeJoin{}%
203-
\pmixCodeImportC[]{sources/hybrid-prog-model/mpi_thread.c}
204-
\pmixCodeJoinEnd{}%
301+
\littleheader{Related Interfaces}
205302

206-
\littleheader{Related Interfaces, Attributes, and Constants}
303+
{\large \refapi{PMIx_Spawn}}
304+
\pasteSignature{PMIx_Spawn}
207305

208-
{\large \refapi{PMIx_Register_event_handler}}
209-
\pasteSignature{PMIx_Register_event_handler}
306+
\littleheader{Related Structs}
307+
308+
\refstruct{pmix_envar_t}
309+
310+
\littleheader{Related Attributes}
311+
312+
\pasteAttributeItem{PMIX_SET_ENVAR}
313+
\pasteAttributeItem{PMIX_ADD_ENVAR}
314+
\pasteAttributeItem{PMIX_UNSET_ENVAR}
315+
\pasteAttributeItem{PMIX_PREPEND_ENVAR}
316+
\pasteAttributeItem{PMIX_APPEND_ENVAR}
210317

211-
\pasteAttributeItem{PMIX_EVENT_HDLR_NAME}
212-
\pasteAttributeItem{PMIX_EVENT_HDLR_FIRST}
213-
\pasteAttributeItem{PMIX_EVENT_HDLR_LAST}
214-
\pasteAttributeItem{PMIX_EVENT_HDLR_FIRST_IN_CATEGORY}
215-
\pasteAttributeItem{PMIX_EVENT_HDLR_LAST_IN_CATEGORY}
216-
\pasteAttributeItem{PMIX_EVENT_HDLR_BEFORE}
217-
\pasteAttributeItem{PMIX_EVENT_HDLR_AFTER}
218-
\pasteAttributeItem{PMIX_EVENT_HDLR_APPEND}
219-
220-
{\large \refapi{pmix_event_notification_cbfunc_fn_t}}
221-
\pasteSignature{pmix_event_notification_cbfunc_fn_t}
222-
223-
\refconst{PMIX_EVENT_NO_ACTION_TAKEN} \\
224-
\refconst{PMIX_EVENT_PARTIAL_ACTION_TAKEN} \\
225-
\refconst{PMIX_EVENT_ACTION_DEFERRED} \\
318+
Resource managers and launchers must scan for relevant directives, modifying environmental parameters as directed. Directives are to be processed in the order in which they were given, starting with job-level directives (applied to each app) followed by app-level directives.
226319

227320
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

figs/direct-launch.jpg

272 KB
Loading

figs/indirect-launch.jpg

355 KB
Loading

figs/process-acquisition.jpg

172 KB
Loading

0 commit comments

Comments
 (0)