Chapter 15. OOSPMD

15.1. OOSPMD: Introduction

SPMD stands for Single Program Multiple Data. Merged into an object-oriented framework, an SPMD programming model becomes an OOSPMD programming model.

The typed group communication system can be used to simulate MPI-style collective communication. Contrary to MPI that requires all members of a group to collectively call the same communication primitive, our group communication scheme let the possibility to one activity to call a method on the group.

The purpose of the our group communication is to free the programmer from having to implement the complex communication code required for setting identical group in each SPMD activity, group communication, thereby allowing the focus to be on the application itself.

This page presents the mechanism of typed group communication as an new alternative to the old SPMD programming model. While being placed in an object-oriented context, this mechanism helps the definition and the coordination of distributed activities. The approach offers, through modest size API, a better structuring flexibility and implementation. The automation of key communication mechanisms and synchronization simplifies the writing of the code.

The main principle is rather simple: an spmd group is a group of active objects where each one has a group referencing all the active objects.

15.2. SPMD Groups

An spmd group is a ProActive typed group built with the ProSPMD.newSPMDGroup() method. This method looks like the ProActiveGroup.newGroup(); they have similar behavior (and overloads). The difference is that each members of an spmd group have a reference to a group containing all the others members and itself (i.e. a reference to the spmd group itself).

Given a standard Java class:

class A { 
  public A() {}
  public void foo (...) {...}
  public void bar (...) {...}
  ...
}

The spmd group is built as follow:

  Object[][] params = {{...} , {...} , ... }; 
  Node[] nodes  = { ... , ..., ... }; 
  A agroup = (A) ProSPMD.newSPMDGroup('A', params[], nodes); 

Object members of an spmd group are aware about the whole group. They can obtain some informations about the spmd group they belong to such as the size of the group, their rank in the group, and a reference to the group in order to get more informations or to communicate with method invocations. Those informations are respectively obtained using the static methods getMySPMDGroupSize(), getMyRank(), and getSPMDGroup() of the ProSPMD class.

15.3. Barrier: Introduction

ProActive provides three kinds of barrier to synchronize activities. The feature is specially useful in a SPMD programming style. A barrier stops the activity of the active object that invokes it until a special condition is satisfied. Notice that, as the opposite of MPI or such libraries, the ProActive barriers do not stop the current activity immediately (when the barrier method is encountered). The current method actually keeps on executing until the end. The barrier will be activated at the end of the service: no other service will be started until all the AOs involved in the barrier are at that same point.

The three barriers are named:

  • the Total Barrier

  • the Neighbor Barrier

  • the Method-based Barrier

Here is a presentation about how to use those barriers.

15.4. Total Barrier

Total barrier directly involves the spmd group. A call to barrier(String) will block until all the members in the spmd group have themselves reach and called the identical ProSPMD.barrier() primitive. A call communicates with all the members of the spmd group. The barrier is released when the Active Object has received a barrier message from all other members of the spmd group (including itself).

The string parameter is used as unique identity name for the barrier. It is the programmer responsibility to ensure that two (or more) different barriers with the same id name are not invoked simultaneously.

Let us take a Java class that contains a method calling a total barrier, here the method foo:

class A { 
  public A() {}
  public void foo (...) {
    ...
    ProSPMD.barrier('MyBarrier');
  }
  public void bar (...) {...}
  ...
}

Note that usually, strings used as unique ID are more complex; they can be based on the full name of the class or the package (org.objectweb.proactive.ClassName), for example. The spmd group is built as follow:

  Object[][] params = {{...} , {...} , ... }; 
  Node[] nodes  = { ... , ..., ... }; 
  A agroup = (A) ProSPMD.newSPMDGroup('A', params[], nodes); 

Here the main method of our application:

  agroup.foo();
  agroup.bar();

The call to barrier launched by all members (in the invocation of foo) ensures that no one will initiate the bar method before all the foo methods end.

The programmer have to ensure that all the members of an spmd group call the barrier method otherwise the members of the group may indefinitely wait.

15.5. Neighbor barrier

The Neighbor barrier is a kind of light weighted barrier, involving not all the member of an spmd group, but only the Active Objects specified in a given group.

barrier(String,group) initiates a barrier only with the objects of the specified group. Those objects, that contribute to the end of the barrier state, are called neighbors as they are usually local to a given topology, An object that invoke the Neighbor barrier HAVE TO BE IN THE GROUP given as parameter. The barrier message is only sent to the group of neighbors.

The programmer has to explicitly build this group of neighbors. The topology API can help him or her to build such group. Topologies are groups. They just give special access to their members or (sub)groups members. For instance, a matrix fits well with the topology Plan that provides methods to get the reference of neighbor members (left, right, up, down). See the javadoc of the topology package for more information:

org.objectweb.proactive.core.group.topology

Like for the Total barrier, the string parameter represents a unique identity name for the barrier. The second parameter is the group of neighbors built by the programmer. Here is an example:

 ProSPMD.barrier('MyString', neighborGroup); 

Refer to the Jacobi example to see a use of the Neighbor barrier. Each submatrix needs only to be synchronized with the submatrixes which it is in contact.

This barrier increases the asynchronism and reduce the amount of exchanged messages.

15.6. Method Barrier

The Method barrier does no more involve extra messages to communicate (i.e. the barrier messages). Communications between objects to release a barrier are achieved by the standard method call and request reception of ProActive.

The method barrier(String[]) stops the active object that calls it, and wait for a request on the specified methods to resume. The array of string contains the name of the awaited methods. The order of the methods does not matter. For example:

 ProSPMD.barrier({'foo', 'bar', 'gee'}); 

The caller will stop and wait for the three methods. bar or gee can came first, then foo. If one wants wait for foo, then wait for bar, then wait for gee, three calls can be successively done:

   ProSPMD.barrier({'foo'});
   ProSPMD.barrier({'bar'});
   ProSPMD.barrier({'gee'}); 

A method barrier is used without any group (spmd or not). To learn more on Groups, please refer to Chapter 14, Typed Group Communication.

15.7. When does a barrier get triggered?

Barriers are not triggered at the place they are declared in the code. Instead, they are run at the end of the method. Look at this code:

public void MyMethodWithBarrier () {
    foo();
    ProSPMD.barrier("barrier");
    bar();
    } 

In this case, the call to bar() will be made BEFORE the barrier is really triggered. In fact, the barriers only start blocking at the END of the method. If you use something like this.asyncRefToSelf.bar(), it's ok, because then this call is put on the request queue, and will be effectively run AFTER the end of the current method. But if, like in the previous case (with the bar() method), a call is declared before the end of the method, then the barrier will be run after this call is made.

To enforce the barrier, you should make the barrier the last action of your method, or you can use this trick:

    foo();
    ProSPMD.barrier("barrier");
    this.asyncRefToSelf.bar();
[Note]Note

The behavior of barrier is peculiar in this sense. You should keep in mind this particularity when writing code with barriers.