ParaSail in print

126 views
Skip to first unread message

Tuck

unread,
Jun 29, 2012, 4:57:52 PM6/29/12
to parasail-progr...@googlegroups.com

An article entitled "ParaSail: Less is More with Multicore" was published recently on eetimes.com (and its affiliates). Here is a link to a newsletter where the editor (Bernie Cole) highlights the article:

    http://i.cmpnet.com/audiencedevelopment/newsletters/06-21-2012-EmbeddedNL.html

Here is a direct link to the article:

    http://www.eetimes.com/design/embedded/4375616/ParaSail--Less-is-more-with-multicore

In addition to the above, a subset of the ParaSail blog is also now available online in a somewhat more polished format as a section of the following Ada User Journal issue (covers Sept 2009 to February 2011):

    http://www.ada-europe.org/archive/auj/auj-32-1.pdf

Finally, we participated in the New England Programming Languages and Systems Symposium on June 1 at the University of Southern Maine:

    http://www.nepls.org/Events/26/

The slides we presented are attached.

ParaSail_NEPLS_Jun_2012.pps

Marco

unread,
Jul 7, 2012, 11:37:46 AM7/7/12
to parasail-progr...@googlegroups.com

"
No Global Variables
Many of us have been warned of the evils of global variables in our early programming courses, but nevertheless, global variables are widely used in most programs. Sometimes they aren’t globally visible, but nevertheless, anything that represents variable global state, such as a static variable in C, C++, or Java, or a singleton object in Scala [2], can create the same kinds of problems associated with unexpected side-effects, hidden algorithmic coupling, etc.

In a sequential program, global variables are often considered bad practice. In a parallel program, global variables can create nasty race conditions, or synchronization bottlenecks.
"
First my term for global variable and yours are different.
Mine is the simple "globally visible to any code" such as:

extern int myGlobalvar;
I never do this - state ("static data" or "persistent data" not "global variable") needs to be hidden.

What about state.  Are you saying we never should keep the state of a system?
At some point a complex system changes state and behavior depends on that.
If you mean algorithm type computations such as signal processing shouldn't keep state then I agree. The most brittle and un-reusable code I see has static data peppered throughout the algorithms.


PS - you need to advertize this discussion group more.




Tuck

unread,
Jul 8, 2012, 12:11:29 PM7/8/12
to parasail-progr...@googlegroups.com

On Saturday, July 7, 2012 11:37:46 AM UTC-4, Marco wrote:

"No Global Variables
... anything that represents variable global state, such as a static variable in C, C++, or Java, or a singleton object in Scala [2], can create the same kinds of problems associated with unexpected side-effects, hidden algorithmic coupling, etc. ..."
 
First my term for global variable and yours are different.
Mine is the simple "globally visible to any code" such as:

extern int myGlobalvar;
I never do this - state ("static data" or "persistent data" not "global variable") needs to be hidden.

What about state.  Are you saying we never should keep the state of a system?

No, the issue is whether any function can directly modify the global state of the system, or whether it needs to be passed a "var" (in-out) parameter referencing some part of that global state to do the modification.  If any function can directly modify global state, parallelization is essentially impossible unless all references to global state involve some kind of mutual exclusion.  That produces a somewhat error-prone situation, or a global bottleneck. 

In ParaSail, functions can only directly modify objects passed as "var" parameters.  The objects themselves might originate in the main routine of the program, and in that sense represent global state, or they might be local variables of the calling function.  The key thing is that as part of the parameter passing, the object is "handed off" to the function receiving it, and as such, race conditions and/or the need for run-time mutual exclusion are eliminated.

At some point a complex system changes state and behavior depends on that.

Certainly true.  The question is how do functions gain access to variable state, and in ParaSail, it is only via parameters passed to them.
 
If you mean algorithm type computations such as signal processing shouldn't keep state then I agree. The most brittle and un-reusable code I see has static data peppered throughout the algorithms.

Static data buried inside a function is probably the worst situation, because then callers aren't even aware of the long-term side-effects and possible race conditions associated with calling the function. 

PS - you need to advertize this discussion group more.

I'll see what I can do!

Britt

unread,
Jul 8, 2012, 9:29:47 PM7/8/12
to ParaSail Programming Language
On Jul 8, 12:11 pm, Tuck <tucker.t...@gmail.com> wrote:

>
> No, the issue is whether any function can directly modify the global state
> of the system, or whether it needs to be passed a "var" (in-out) parameter
> referencing some part of that global state to do the modification.  If any
> function can directly modify global state, parallelization is essentially
> impossible unless all references to global state involve some kind of
> mutual exclusion.  That produces a somewhat error-prone situation, or a
> global bottleneck.
>
> In ParaSail, functions can only directly modify objects passed as "var"
> parameters.  The objects themselves might originate in the main routine of
> the program, and in that sense represent global state, or they might be
> local variables of the calling function.  The key thing is that as part of
> the parameter passing, the object is "handed off" to the function receiving
> it, and as such, race conditions and/or the need for run-time mutual
> exclusion are eliminated.
>

I like this approach. I've seen a lot of abuse of global variables in
complex systems, making these systems very difficult to analyze or
test. Is it fair to say your approach in ParaSail is equivalent to a
SPARK program where global (package state) variables are prohibited
(via convention and/or tool) from ever having an "out" or "in out"
mode in a moded global annotation?

I just looked in the ParaSail reference manual for a description of
function parameter modes. I found the section and now I'm hoping you
will expand on why ParaSail's mode scheme is different (more specific)
than simply "in", out" and "in out"?

- Britt

Tuck

unread,
Jul 9, 2012, 11:13:10 AM7/9/12
to parasail-progr...@googlegroups.com
On Sunday, July 8, 2012 9:29:47 PM UTC-4, Britt wrote:
On Jul 8, 12:11 pm, Tuck <tucker.t...@gmail.com> wrote:

> In ParaSail, functions can only directly modify objects passed as "var"
> parameters.  The objects themselves might originate in the main routine of
> the program, and in that sense represent global state, or they might be
> local variables of the calling function.  The key thing is that as part of
> the parameter passing, the object is "handed off" to the function receiving
> it, and as such, race conditions and/or the need for run-time mutual
> exclusion are eliminated.
>

I like this approach. I've seen a lot of abuse of global variables in
complex systems, making these systems very difficult to analyze or
test. Is it fair to say your approach in ParaSail is equivalent to a
SPARK program where global (package state) variables are prohibited
(via convention and/or tool) from ever having an "out" or "in out"
mode in a moded global annotation?

In some sense SPARK moded globals are accomplishing the same goal,
by documenting in the interface all of the data that might be read or updated
by the routine.  However, moded globals are somewhat limiting in that they
refer to the entire global, rather than just to the components of interest.

Note that in ParaSail, even *reading* a global variable directly is not permitted,
since you have some of the same synchronization issues if some part of
the global is being concurrently updated.  So even to read a global variable, it
must be passed as a non-var parameter to the function.


I just looked in the ParaSail reference manual for a description of
function parameter modes. I found the section and now I'm hoping you
will expand on why ParaSail's mode scheme is different (more specific)
than simply "in", out" and "in out"?

In ParaSail, as in Ada, the default parameter mode is read-only.  A "var" parameter
in ParaSail is essentially equivalent to an "in out" parameter in Ada, though there
is a "hand off" semantics implied in ParaSail which is relevant to the pervasively
parallel nature of ParaSail.  An "out" parameter in Ada is equivalent to a ParaSail
"output" parameter, which comes after the "->" in the declaration of an operation.
The current prototype doesn't support more than one output parameter, but once
they are supported, then multiple outputs would be handled by a simultaneous
assignment, such as:

   (Q, R) := Quotient_Remainder(Dividend, Divisor);

or you could just use one of the outputs, such as :

    Q := Quotient_Remainder(Dividend, Divisor).Quotient;

or you could save the pair of results, and then use them later:

    const QR := Quotient_Remainder(Dividend, Divisor);
       ...
    X := QR.Quotient;
    Y := QR.Remainder;

Multiple outputs are essentially equivalent to returning a composite
object or a tuple, where the type is anonymous, though the fields are named.

The most common case is where there is a single output parameter, and then
you have the equivalent of an Ada or Pascal function.

- Britt

-Tuck

Anton Lobach

unread,
Jul 28, 2019, 2:22:40 PM7/28/19
to ParaSail Programming Language
Hi Tucker,
 
Note that in ParaSail, even *reading* a global variable directly is not permitted,
since you have some of the same synchronization issues if some part of
the global is being concurrently updated.  So even to read a global variable, it
must be passed as a non-var parameter to the function.


Is my understanding correct that the following should not compile?

func main () is

  // Global variable
  const Delta : Integer := 1;
 
  // Function to use global variable
  func Shift (This : Integer) -> Integer is
    return This + Delta; // using global variable
  end func Shift;

  // Result of the Shift
  const Shifted : Integer := Shift (This => 0);

  // Print results
  Println (Shifted);

end func main;


But somehow it still compiles and outputs 1.

Best,
Anton

Tucker Taft

unread,
Jul 29, 2019, 2:38:19 PM7/29/19
to ParaSail Programming Language
There are three reasons why this doesn't complain.  First is that "Delta' is not a "variable" -- it is a "constant."  In some programming languages, declared objects are always called "variables," but in ParaSail, only objects that can be assigned different values over their lifetime are called "variables" (and would need to be declared using "var" rather than "const"). 

The second reason, is that currently for *nested* operations, the use of up-level variables (as opposed to "level 0", "class-level" globals) is not limited unless they introduce a data race condition.  So you can introduce nested operations to replace any repeated sequence of code, even if it reads or updates local variables of the enclosing scope.  There was a design for restricting such up-level variable usage by using  an explicit "global" specification at the point of the declaration of the nested operation, but that has not been implemented.  In any case the code to check that up-level variable usage is "safe" from the point of view of parallel execution does exist.  So it would be interesting to verify whether your test program would fail if you called "Shift" on one side of a "||" operator while updating Delta on the other side.

Which brings us to the third reason.  If in fact you do the experiment suggested, you will find it still doesn't complain.  It turns out that we were inadvertently ignoring up-level references that occurred inside a return statement.  You could verify this by changing "Shift" to refer to Delta outside the "return" statement.

After making the following changes to your test program:

 1:func main () is
 2:
 3:  // Global variable
 4:  var Delta : Integer := 1;   //  Note, making this a variable
 5:
 6:  // Function to use global variable
 7:  func Shift (This : Integer) -> Integer is
 8:    return This + Delta; // using global variable
 9:  end func Shift;
10:
11:  // Result of the Shift
12:  const Shifted : Integer := Shift (This => 0);
13:
14:  // Print results
15:  Println (Shifted);
16:
17:  then
18:     //  Testing the data race condition
19:     Println (Shift(This => 0)) || Delta += 1;
20:
21:end func main;

and fixing the problem with up-level references from return statements, we get the following:

     up_level.psl:19:36: Warning: R/W Data Race on Delta at up_level.psl:19:15:

which points at the increment of Delta.

Running this program three times in a row shows the data race:

Command to execute: main
1
2
Command to execute: main
1
2
Command to execute: main
1
1
Command to execute: quit

Take care,
-Tuck



--
You received this message because you are subscribed to the Google Groups "ParaSail Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to parasail-programming...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/parasail-programming-language/6b1e918a-1e3b-40d1-99dd-56aaade3a341%40googlegroups.com.

Anton Lobach

unread,
Aug 9, 2019, 6:42:29 PM8/9/19
to ParaSail Programming Language


On Monday, July 29, 2019 at 2:38:19 PM UTC-4, Tucker Taft wrote:
There are three reasons why this doesn't complain.  First is that "Delta' is not a "variable" -- it is a "constant."  In some programming languages, declared objects are always called "variables," but in ParaSail, only objects that can be assigned different values over their lifetime are called "variables" (and would need to be declared using "var" rather than "const").  

Ok, I see. I was thinking of them more as mutable (var) vs immutable (const) variables. 

The second reason, is that currently for *nested* operations, the use of up-level variables (as opposed to "level 0", "class-level" globals) is not limited unless they introduce a data race condition.  So you can introduce nested operations to replace any repeated sequence of code, even if it reads or updates local variables of the enclosing scope.  There was a design for restricting such up-level variable usage by using  an explicit "global" specification at the point of the declaration of the nested operation, but that has not been implemented. 

Is it dropped from the language or is it not implemented at the compiler level?
Ok, I see now. 

Thank you very much for the explanation!

P.S. 
It seems that not allowing (by default) to read global constants should make the language even safer (not just for parallel programming), shouldn't it?

Best,
Anton

Tucker Taft

unread,
Aug 10, 2019, 8:46:43 AM8/10/19
to ParaSail Programming Language
On Fri, Aug 9, 2019 at 6:42 PM Anton Lobach <anton...@uri.edu> wrote:


On Monday, July 29, 2019 at 2:38:19 PM UTC-4, Tucker Taft wrote:
There are three reasons why this doesn't complain.  First is that "Delta' is not a "variable" -- it is a "constant."  In some programming languages, declared objects are always called "variables," but in ParaSail, only objects that can be assigned different values over their lifetime are called "variables" (and would need to be declared using "var" rather than "const").  

Ok, I see. I was thinking of them more as mutable (var) vs immutable (const) variables. 

Unfortunately, such vocabulary seems to be somewhat language-specific.  In ParaSail we use the neutral term "object" and then have "constant objects" and "variable objects" both of which get shortened to typically "constant" and "variable."  An "immutable variable" seems a bit of an oxymoron! ;-)


The second reason, is that currently for *nested* operations, the use of up-level variables (as opposed to "level 0", "class-level" globals) is not limited unless they introduce a data race condition.  So you can introduce nested operations to replace any repeated sequence of code, even if it reads or updates local variables of the enclosing scope.  There was a design for restricting such up-level variable usage by using  an explicit "global" specification at the point of the declaration of the nested operation, but that has not been implemented. 

Is it dropped from the language or is it not implemented at the compiler level?

Not implemented yet.

 
...
It seems that not allowing (by default) to read global constants should make the language even safer (not just for parallel programming), shouldn't it?

Reading global constants is no different from reading a local constant, or calling a parameterless function that returns the same thing each time, so I don't see a safety issue.  It seems better to have one global constant that is used everywhere than to repeat the information in multiple places.  But perhaps I don't understand the safety issue you perceive.

Best,
Anton

Take care,
-Tuck

--
You received this message because you are subscribed to the Google Groups "ParaSail Programming Language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to parasail-programming...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages