Tutorial - Parallel Types

From Mesham
Revision as of 17:32, 18 January 2013 by Polas (talk | contribs) (Created page with '== Introduction == Up until this point we have been dealing with the default shared memory model of communication. Whilst this is a simple, safe and consistent model it can have…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Introduction

Up until this point we have been dealing with the default shared memory model of communication. Whilst this is a simple, safe and consistent model it can have a performance penalty associated with it. In this tutorial we shall look at overriding the default communication, via types, to a more message passing style.

A channel

#include <io>
#include <string>

function void main() {
   var a:Int::channel[1,2];
   var b:Int::allocated[single[on[2]]];
   proc 1 {
       a:=23;	
   };	
   proc 2 {
      b:=a;
      print(itostring(b)+"\n");
   };
};

In this example we are using variable a as a channel, between processes 1 and 2. At line 8, process 1 writes the value 23 into this channel and at line 11, process 2 reads that value out of the channel. Note that channels are unidirectional (i.e. process 2 could not write to process 1 in this example.)

Pipes

#include <io>
#include <string>

function void main() {
   var a:Int:: pipe[1,2];
   var b:Int;
   var p;
   par p from 0 to 2 {
      var i;
      for i from 0 to 9 {
         var master:=1;
         var slave:=2;
         if (i%2!=0) {
            master:=2;
            slave:=1;
         };
         if (p==master) a:=i;
         if (p==slave) {
            b:=a;
            print(itostring(p)+": "+itostring(b)+"\n");
         };
      };
   };

};

This code demonstrates using the pipe type for bidirectional point to point communication. If you change the pipe to a channel then you will see that instead, only process 1 may send and only 2 may receive.

Extra parallel control

By default the channel type is a blocking call, we have a number of fine grained types which you can use to modify this behaviour.

#include <io>
#include <string>

function void main() {
   var a:Int::channel[0,1]::nonblocking[];
   var b:Int;
   proc 0 {
      a:=23;
      sync a;	
   };
   proc 1 {
      b:=a;
      sync a;
      print(itostring(b)+"\n");
   };
};

In this code we are using the nonblocking type to override the default blocking behaviour of a channel. The type is connected to the sync keyword such that it will wait at that point for outstanding communication to complete. Try experimenting with the code to understand the differences these types make.

Collective communication

Mesham has a number of collective communication types, here we are just going to consider the reduce and broadcast.

A broadcast

The broadcast type allows us to explicitly specify that a communication is to involve all processes (in current parallel scope.)

#include <io>
#include <string>

function void main() {
   var a:Int;	
   a::broadcast[2]:=23;
   print(itostring(a)+"\n");
};

In this example we are declaring a to be a normal Int variable, then on line 6 we are coercing the broadcast type with the existing type chain of a just for that assignment and telling the type that process 2 is the root process. The root process is the one that drives the broadcast itself, i.e. here process 2 is sending the value 23 to all other processes. Then on line 7 we are just using a as a normal program variable to display its value. This use of types is actually quite a powerful one; we can append extra types for a specific expression and then after that expression has completed the behaviour is back to what it was before.