~ubuntu-branches/ubuntu/vivid/mpich/vivid-proposed

« back to all changes in this revision

Viewing changes to src/pmi/pmi2/README

  • Committer: Package Import Robot
  • Author(s): Anton Gladky
  • Date: 2014-04-01 20:24:20 UTC
  • mfrom: (5.2.4 sid)
  • Revision ID: package-import@ubuntu.com-20140401202420-t5ey1ia2klt5dkq3
Tags: 3.1-4
* [c3e3398] Disable test_primitives, which is unreliable on some platforms.
            (Closes: #743047)
* [265a699] Add minimal autotest.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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.
6
 
 
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.
11
 
 
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.
17
 
 
18
 
To allow multiple threads to share the PMI socket; we use the
19
 
following model for mediating atomic access:
20
 
 
21
 
enter-atomic
22
 
   make use of socket
23
 
   create operation with a completion flag "flag"
24
 
 
25
 
   waitfor( &flag, atomic-ctx, wait-function, wait-ctx )
26
 
 
27
 
   cleanup
28
 
exit-atomic
29
 
 
30
 
During the "waitfor" operation, other threads may enter this atomic
31
 
section.
32
 
 
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
35
 
a response.
36
 
 
37
 
waitfor( ... )
38
 
{
39
 
  do {
40
 
      if (atomic-ctx->wait-function-running) {
41
 
          pthread_cond_wait( atomic-ctx->mutex, atomic-ctx->condvar );
42
 
      }
43
 
      else {
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 )
48
 
      }
49
 
  } while (!*flag);
50
 
  pthread_mutex_lock( atomic-ctx->mutex );
51
 
}
52
 
 
53
 
 
54
 
Here, the wait-function might look something like this:
55
 
 
56
 
int wait-function( int *flag, void *socket_set )
57
 
do {
58
 
     poll( socket_set ... );
59
 
     for each active fd
60
 
          process fd (may complete some operations). 
61
 
    } while (!*flag);
62
 
}
63
 
 
64
 
Note that in the single-threaded case, the waitfor routine turns into
65
 
 
66
 
waitfor( ... )
67
 
{
68
 
  do {
69
 
     wait-function( flag_ptr, wait-ctx );
70
 
      }
71
 
  } while (!*flag);
72
 
}
73
 
 
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.  
77
 
 
78
 
For example, the PMI_KVS_Get operation will look more like
79
 
 
80
 
int PMI_KVS_Get( ... )
81
 
{
82
 
    enter-atomic
83
 
        create operation, get opid
84
 
        enqueue operation
85
 
        write ( pmifd, "nnnnnncmd=get;opid=...;name=..." );
86
 
        waitfor( &operation->flag, ... );
87
 
        dequeue operation
88
 
        extract response (e.g., the value and rc)
89
 
        free operation
90
 
    exit-atomic
91
 
}
92
 
 
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).
99
 
 
100
 
The above is sufficient for the needs of PMI.  One additional
101
 
optimization is to avoid the mutex by first doing a test:
102
 
 
103
 
test-function( test-ctx )
104
 
if (!*flag) {
105
 
   ... the usual code above, including the trailing mutex lock
106
 
}
107
 
 
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., 
110
 
 
111
 
wait-function( NULL, wait-ctx )
112
 
if (!*flag) {
113
 
       ....
114
 
}
115