1
This directory contains an experimental, version 2 PMI interface. Both
2
the client API and the wire protocol for this version are different than
3
PMI version 1. This version is not yet in use in MPICH, and is
4
being developed to prototype the changes proposed. In particular, this version
5
adds support for better thread-safe behavior.
7
Currently, the source files simply define the interfaces. There is no
8
implementation yet. The files have been added to the repository so that they
9
can be reviewed by interested parties, particularly 3rd-parties that
10
will need to interface to this second-generation interface.
12
A major issue that PMI verison 2 needs to address is thread-safety and
13
responsiveness. In particular, no thread that is waiting on a PMI call can
14
block other threads, even PMI_Spawn. The design sketched out here
15
addresses these issues as well as providing a relatively simple model
16
for thread interaction.
18
To allow multiple threads to share the PMI socket; we use the
19
following model for mediating atomic access:
23
create operation with a completion flag "flag"
25
waitfor( &flag, atomic-ctx, wait-function, wait-ctx )
30
During the "waitfor" operation, other threads may enter this atomic
33
Here is a sketch of the implementation of "waitfor" that makes use of
34
the Posix condition variable to block the threads that are waiting for
40
if (atomic-ctx->wait-function-running) {
41
pthread_cond_wait( atomic-ctx->mutex, atomic-ctx->condvar );
44
atomic-ctx->wait-function-running = 1;
45
pthread_mutex_unlock( atomic-ctx->mutex );
46
wait-function( flag_ptr, wait-ctx );
47
pthread_cond_signal( atomic-ctx->condvar )
50
pthread_mutex_lock( atomic-ctx->mutex );
54
Here, the wait-function might look something like this:
56
int wait-function( int *flag, void *socket_set )
58
poll( socket_set ... );
60
process fd (may complete some operations).
64
Note that in the single-threaded case, the waitfor routine turns into
69
wait-function( flag_ptr, wait-ctx );
74
and the enter/exit atomic are no-ops. This makes each of the
75
implementation of each of the PMI routines essentially independent of
76
the number of threads.
78
For example, the PMI_KVS_Get operation will look more like
80
int PMI_KVS_Get( ... )
83
create operation, get opid
85
write ( pmifd, "nnnnnncmd=get;opid=...;name=..." );
86
waitfor( &operation->flag, ... );
88
extract response (e.g., the value and rc)
93
In principle, once the operation is dequeued, we could exit the atomic
94
section, but we may want to keep a pool of operations (instead of
95
malloc'ing it each time), and then we'd need to re-aquire the critical
96
section in order to free it (another option would be to allow one
97
operation per thread and allocate it once; that would fit with the
98
usage model but may not be worth the effort in this case).
100
The above is sufficient for the needs of PMI. One additional
101
optimization is to avoid the mutex by first doing a test:
103
test-function( test-ctx )
105
... the usual code above, including the trailing mutex lock
108
An easy way to do this with the single wait function is to make the
109
routine wait only if there is a non-null flag, i.e.,
111
wait-function( NULL, wait-ctx )