| [9f53b6c] | 1 |
|
|---|
| 2 | % \subsection{Example 1}
|
|---|
| 3 |
|
|---|
| 4 | % Here is a simple example based on a tricky MPI+Pthreads example given
|
|---|
| 5 | % to us once by Rajeev Thakur at Argonne. It has nondeterministic
|
|---|
| 6 | % behavior which can lead to a deadlock for certain interleavings, even
|
|---|
| 7 | % though it does not use wildcards (\code{ANY{\U}SOURCE}). Very subtle
|
|---|
| 8 | % bug. I can show you MPI-Spin finding the bug if you are interested. I
|
|---|
| 9 | % don't actually have the original code, but could probably dig it up.
|
|---|
| 10 |
|
|---|
| 11 | % \begin{verbatim}
|
|---|
| 12 | % #include <mp.civl> /* includes basic message-passing library */
|
|---|
| 13 |
|
|---|
| 14 | % void System() {
|
|---|
| 15 | % proc procs[2];
|
|---|
| 16 |
|
|---|
| 17 | % void MPI_Process(int pid) {
|
|---|
| 18 | % proc threads[2];
|
|---|
| 19 |
|
|---|
| 20 | % void Thread(int tid) {
|
|---|
| 21 | % int x=0, y=0;
|
|---|
| 22 |
|
|---|
| 23 | % for (int j=0; j<2; j++) {
|
|---|
| 24 | % if (pid == 1) {
|
|---|
| 25 | % for (int i=0; i<3; i++) send(procs[pid], &x, 1, procs[1-pid], 0);
|
|---|
| 26 | % for (int i=0; i<3; i++) recv(procs[pid], &y, 1, procs[1-pid], 0);
|
|---|
| 27 | % } else { /* pid==0 */
|
|---|
| 28 | % for (int i=0; i<3; i++) recv(procs[pid], &y, 1, procs[1-pid], 0);
|
|---|
| 29 | % for (int i=0; i<3; i++) send(procs[pid], &x, 1, procs[1-pid], 0);
|
|---|
| 30 | % }
|
|---|
| 31 | % }
|
|---|
| 32 | % }
|
|---|
| 33 |
|
|---|
| 34 | % for (int i=0; i<2; i++) threads[i] = fork Thread(i);
|
|---|
| 35 | % for (int i=0; i<2; i++) join threads[i];
|
|---|
| 36 | % }
|
|---|
| 37 |
|
|---|
| 38 | % for (int i=0; i<2; i++) procs[i] = fork MPI_Process(i);
|
|---|
| 39 | % for (int i=0; i<2; i++) join procs[i];
|
|---|
| 40 | % }
|
|---|
| 41 | % \end{verbatim}
|
|---|
| 42 |
|
|---|
| 43 | \appendix
|
|---|
| 44 |
|
|---|
| 45 |
|
|---|
| 46 | \end{document}
|
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 | OpenMP loop?
|
|---|
| 50 | \begin{verbatim}
|
|---|
| 51 | T1 x1; ... // private
|
|---|
| 52 | U1 y1; ... // shared
|
|---|
| 53 | #pragma omp parallel private(x1,...)
|
|---|
| 54 | S(x1,...,y1,...);
|
|---|
| 55 |
|
|---|
| 56 | =>
|
|---|
| 57 |
|
|---|
| 58 | T1 x1; ...
|
|---|
| 59 | U1 y1; ...
|
|---|
| 60 | {
|
|---|
| 61 | void _tmp(int _tid) {
|
|---|
| 62 | T1 _x1; ...
|
|---|
| 63 | S(_x1,...,y1,...);
|
|---|
| 64 | }
|
|---|
| 65 | int numThreads = $choose_int(THREAD_MAX);
|
|---|
| 66 | $proc _threads[numThreads];
|
|---|
| 67 | int i;
|
|---|
| 68 |
|
|---|
| 69 | for (i=0; i<numThreads; i++)
|
|---|
| 70 | _threads[i] = $spawn _tmp(i);
|
|---|
| 71 | for (i=0; i<numThreads; i++)
|
|---|
| 72 | $wait _threads[i];
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | --
|
|---|
| 76 |
|
|---|
| 77 | #pragma parallel
|
|---|
| 78 | { ...
|
|---|
| 79 | int i; ...
|
|---|
| 80 | #pragma for
|
|---|
| 81 | for (i=...) S(i)
|
|---|
| 82 | }
|
|---|
| 83 |
|
|---|
| 84 | =>
|
|---|
| 85 |
|
|---|
| 86 | {
|
|---|
| 87 | void _tmp1(int _tid) {
|
|---|
| 88 | int i; ...
|
|---|
| 89 | {
|
|---|
| 90 | void _tmp2(int _i) { S(_i) }
|
|---|
| 91 | int j;
|
|---|
| 92 | for (j=...) {
|
|---|
| 93 | int w = $choose_int(numThreads);
|
|---|
| 94 | }
|
|---|
| 95 | }
|
|---|
| 96 | }
|
|---|
| 97 |
|
|---|
| 98 |
|
|---|
| 99 | \end{verbatim}
|
|---|
| 100 |
|
|---|
| 101 |
|
|---|
| 102 | In CIVL-C, functions can be defined in any scope, not just in file
|
|---|
| 103 | scope. The lexical scope structure and placement of function
|
|---|
| 104 | definitions determine the static scope tree $\Sigma$ and the function
|
|---|
| 105 | prototype system. A function's defining scope is, as you would
|
|---|
| 106 | expect, the scope in which its definition occurs.
|
|---|
| 107 |
|
|---|
| 108 | The CIVL-C code will not have an explicit ``root'' procedure.
|
|---|
| 109 | Instead, a root procedure will be implicitly wrapped around the entire
|
|---|
| 110 | code. The global input variables will become the inputs to the root
|
|---|
| 111 | procedure. A ``\texttt{main}'' procedure must be delcared that takes
|
|---|
| 112 | no parameters but can have any return type. The body of \texttt{main}
|
|---|
| 113 | becomes the body of the root procedure. The return type of
|
|---|
| 114 | \texttt{main} becomes the return type of the root procedure. The
|
|---|
| 115 | \texttt{main} procedure itself disappears in translation.
|
|---|
| 116 |
|
|---|
| 117 | The reason for this protocol is that an arbitrary (sequential) C program
|
|---|
| 118 | is a legal (and reasonable) CIVL-C program. The global variables in the
|
|---|
| 119 | C program simply become variables declared in the root scope.
|
|---|
| 120 |
|
|---|
| 121 | The additional language elements are shown in Figure \ref{fig:cc}.
|
|---|
| 122 |
|
|---|
| 123 | \begin{figure}[t]
|
|---|
| 124 | \begin{tabular}{ll}
|
|---|
| 125 | \cassert & check something holds \\
|
|---|
| 126 | \cassume & assume something holds \\
|
|---|
| 127 | \catom & defines statements to be executed as one transition\\
|
|---|
| 128 | \catomic & defines statements to be executed without interleaving other processes\\
|
|---|
| 129 | \cchoose & nondeterministic choice statement \\
|
|---|
| 130 | \ccollective & a collective expression\\
|
|---|
| 131 | \censures & procedure postcondition \\
|
|---|
| 132 | \cfalse & boolean value false, used in assertions \\
|
|---|
| 133 | \cheap & the heap type \\
|
|---|
| 134 | \cinput & type qualifier declaring variable to be a program input \\
|
|---|
| 135 | \cinvariant & declare a loop invariant \\
|
|---|
| 136 | \cmalloc & malloc function with additional heap arguments \\
|
|---|
| 137 | \coutput & type qualifier declaring variable to be a program output \\
|
|---|
| 138 | \cproc & the process type \\
|
|---|
| 139 | \crequires & procedure precondition \\
|
|---|
| 140 | \cresult & refers to result returned by procedure in contracts \\
|
|---|
| 141 | \cscope & the scope type, used to give a name to a scope \\
|
|---|
| 142 | \cself & the evaluating process (constant of type \cproc) \\
|
|---|
| 143 | \cspawn & create a new process running procedure \\
|
|---|
| 144 | \ctrue & boolean value true, used in assertions \\
|
|---|
| 145 | \cwait & wait for a process to terminate \\
|
|---|
| 146 | \cwhen & guarded statement \\
|
|---|
| 147 | \cat & refer to variable in other process, e.g., \texttt{p@x} \\
|
|---|
| 148 | \texttt{*<...>} & scope-qualified pointer type
|
|---|
| 149 | \end{tabular}
|
|---|
| 150 | \caption{CIVL-C primitives. Some of these are part of the grammar of the language;
|
|---|
| 151 | others are defined in the header file \texttt{civlc.h}.}
|
|---|
| 152 | \label{fig:cc}
|
|---|
| 153 | \end{figure}
|
|---|
| 154 |
|
|---|